From 8353f61fe986e98ae9f370aa370e9146f6d5f122 Mon Sep 17 00:00:00 2001 From: DivineSpring <46858816+MaayanBogin@users.noreply.github.com> Date: Sun, 14 Jul 2024 15:39:31 +0300 Subject: [PATCH] Added ComfyUI Manager --- custom_nodes/ComfyUI-Manager/LICENSE.txt | 674 + custom_nodes/ComfyUI-Manager/README.md | 415 + custom_nodes/ComfyUI-Manager/__init__.py | 15 + custom_nodes/ComfyUI-Manager/alter-list.json | 224 + .../ComfyUI-Manager/channels.list.template | 6 + custom_nodes/ComfyUI-Manager/check.bat | 21 + custom_nodes/ComfyUI-Manager/check.sh | 42 + custom_nodes/ComfyUI-Manager/cm-cli.py | 1029 + .../ComfyUI-Manager/custom-node-list.json | 11693 +++++++++++ .../ComfyUI-Manager/docs/en/cm-cli.md | 146 + .../ComfyUI-Manager/docs/en/use_aria2.md | 40 + .../ComfyUI-Manager/docs/ko/cm-cli.md | 149 + .../ComfyUI-Manager/extension-node-map.json | 15962 ++++++++++++++++ custom_nodes/ComfyUI-Manager/git_helper.py | 426 + .../ComfyUI-Manager/github-stats.json | 5232 +++++ .../ComfyUI-Manager/glob/cm_global.py | 112 + .../ComfyUI-Manager/glob/manager_core.py | 1217 ++ .../glob/manager_downloader.py | 70 + .../ComfyUI-Manager/glob/manager_server.py | 1707 ++ .../ComfyUI-Manager/glob/manager_util.py | 63 + .../ComfyUI-Manager/glob/security_check.py | 80 + custom_nodes/ComfyUI-Manager/js/cm-api.js | 63 + .../ComfyUI-Manager/js/comfyui-manager.js | 1513 ++ .../js/comfyui-share-common.js | 1064 + .../ComfyUI-Manager/js/comfyui-share-copus.js | 892 + .../js/comfyui-share-openart.js | 745 + .../ComfyUI-Manager/js/comfyui-share-youml.js | 568 + custom_nodes/ComfyUI-Manager/js/common.js | 240 + .../ComfyUI-Manager/js/components-manager.js | 809 + .../js/custom-nodes-manager.js | 1381 ++ .../ComfyUI-Manager/js/model-manager.js | 891 + custom_nodes/ComfyUI-Manager/js/node_fixer.js | 211 + custom_nodes/ComfyUI-Manager/js/snapshot.js | 300 + custom_nodes/ComfyUI-Manager/js/terminal.js | 81 + .../ComfyUI-Manager/js/turbogrid.esm.js | 1 + custom_nodes/ComfyUI-Manager/json-checker.py | 23 + custom_nodes/ComfyUI-Manager/misc/Impact.pack | 444 + .../ComfyUI-Manager/misc/custom-nodes.jpg | Bin 0 -> 163372 bytes custom_nodes/ComfyUI-Manager/misc/main.jpg | Bin 0 -> 31758 bytes custom_nodes/ComfyUI-Manager/misc/menu.jpg | Bin 0 -> 93152 bytes .../ComfyUI-Manager/misc/missing-list.jpg | Bin 0 -> 174344 bytes .../ComfyUI-Manager/misc/missing-menu.jpg | Bin 0 -> 132247 bytes custom_nodes/ComfyUI-Manager/misc/models.png | Bin 0 -> 167680 bytes .../ComfyUI-Manager/misc/nickname.jpg | Bin 0 -> 186689 bytes .../ComfyUI-Manager/misc/portable-install.png | Bin 0 -> 24418 bytes .../ComfyUI-Manager/misc/share-setting.jpg | Bin 0 -> 29478 bytes custom_nodes/ComfyUI-Manager/misc/share.jpg | Bin 0 -> 98371 bytes .../ComfyUI-Manager/misc/snapshot.jpg | Bin 0 -> 92776 bytes custom_nodes/ComfyUI-Manager/model-list.json | 3364 ++++ .../node_db/dev/custom-node-list.json | 1750 ++ .../node_db/dev/extension-node-map.json | 2119 ++ .../node_db/dev/github-stats.json | 762 + .../node_db/dev/model-list.json | 3 + .../ComfyUI-Manager/node_db/dev/scan.sh | 3 + .../node_db/forked/custom-node-list.json | 54 + .../node_db/forked/extension-node-map.json | 1 + .../node_db/forked/model-list.json | 3 + .../ComfyUI-Manager/node_db/forked/scan.sh | 4 + .../node_db/legacy/alter-list.json | 1 + .../node_db/legacy/custom-node-list.json | 587 + .../node_db/legacy/extension-node-map.json | 1 + .../node_db/legacy/model-list.json | 3 + .../node_db/new/alter-list.json | 4 + .../node_db/new/custom-node-list.json | 702 + .../node_db/new/extension-node-map.json | 15962 ++++++++++++++++ .../node_db/new/model-list.json | 710 + .../node_db/tutorial/custom-node-list.json | 244 + .../node_db/tutorial/extension-node-map.json | 1 + .../node_db/tutorial/model-list.json | 3 + .../ComfyUI-Manager/node_db/tutorial/scan.sh | 4 + .../comfyui_colab_with_manager.ipynb | 372 + .../pip_overrides.json.template | 21 + .../ComfyUI-Manager/prestartup_script.py | 665 + custom_nodes/ComfyUI-Manager/pyproject.toml | 15 + custom_nodes/ComfyUI-Manager/requirements.txt | 8 + custom_nodes/ComfyUI-Manager/scan.sh | 7 + custom_nodes/ComfyUI-Manager/scanner.py | 527 + .../scripts/colab-dependencies.py | 39 + .../scripts/install-comfyui-venv-linux.sh | 21 + .../scripts/install-comfyui-venv-win.bat | 17 + .../install-manager-for-portable-version.bat | 2 + .../ComfyUI-Manager/scripts/update-fix.py | 12 + .../the_snapshot_files_are_located_here | 0 83 files changed, 76540 insertions(+) create mode 100644 custom_nodes/ComfyUI-Manager/LICENSE.txt create mode 100644 custom_nodes/ComfyUI-Manager/README.md create mode 100644 custom_nodes/ComfyUI-Manager/__init__.py create mode 100644 custom_nodes/ComfyUI-Manager/alter-list.json create mode 100644 custom_nodes/ComfyUI-Manager/channels.list.template create mode 100644 custom_nodes/ComfyUI-Manager/check.bat create mode 100644 custom_nodes/ComfyUI-Manager/check.sh create mode 100644 custom_nodes/ComfyUI-Manager/cm-cli.py create mode 100644 custom_nodes/ComfyUI-Manager/custom-node-list.json create mode 100644 custom_nodes/ComfyUI-Manager/docs/en/cm-cli.md create mode 100644 custom_nodes/ComfyUI-Manager/docs/en/use_aria2.md create mode 100644 custom_nodes/ComfyUI-Manager/docs/ko/cm-cli.md create mode 100644 custom_nodes/ComfyUI-Manager/extension-node-map.json create mode 100644 custom_nodes/ComfyUI-Manager/git_helper.py create mode 100644 custom_nodes/ComfyUI-Manager/github-stats.json create mode 100644 custom_nodes/ComfyUI-Manager/glob/cm_global.py create mode 100644 custom_nodes/ComfyUI-Manager/glob/manager_core.py create mode 100644 custom_nodes/ComfyUI-Manager/glob/manager_downloader.py create mode 100644 custom_nodes/ComfyUI-Manager/glob/manager_server.py create mode 100644 custom_nodes/ComfyUI-Manager/glob/manager_util.py create mode 100644 custom_nodes/ComfyUI-Manager/glob/security_check.py create mode 100644 custom_nodes/ComfyUI-Manager/js/cm-api.js create mode 100644 custom_nodes/ComfyUI-Manager/js/comfyui-manager.js create mode 100644 custom_nodes/ComfyUI-Manager/js/comfyui-share-common.js create mode 100644 custom_nodes/ComfyUI-Manager/js/comfyui-share-copus.js create mode 100644 custom_nodes/ComfyUI-Manager/js/comfyui-share-openart.js create mode 100644 custom_nodes/ComfyUI-Manager/js/comfyui-share-youml.js create mode 100644 custom_nodes/ComfyUI-Manager/js/common.js create mode 100644 custom_nodes/ComfyUI-Manager/js/components-manager.js create mode 100644 custom_nodes/ComfyUI-Manager/js/custom-nodes-manager.js create mode 100644 custom_nodes/ComfyUI-Manager/js/model-manager.js create mode 100644 custom_nodes/ComfyUI-Manager/js/node_fixer.js create mode 100644 custom_nodes/ComfyUI-Manager/js/snapshot.js create mode 100644 custom_nodes/ComfyUI-Manager/js/terminal.js create mode 100644 custom_nodes/ComfyUI-Manager/js/turbogrid.esm.js create mode 100644 custom_nodes/ComfyUI-Manager/json-checker.py create mode 100644 custom_nodes/ComfyUI-Manager/misc/Impact.pack create mode 100644 custom_nodes/ComfyUI-Manager/misc/custom-nodes.jpg create mode 100644 custom_nodes/ComfyUI-Manager/misc/main.jpg create mode 100644 custom_nodes/ComfyUI-Manager/misc/menu.jpg create mode 100644 custom_nodes/ComfyUI-Manager/misc/missing-list.jpg create mode 100644 custom_nodes/ComfyUI-Manager/misc/missing-menu.jpg create mode 100644 custom_nodes/ComfyUI-Manager/misc/models.png create mode 100644 custom_nodes/ComfyUI-Manager/misc/nickname.jpg create mode 100644 custom_nodes/ComfyUI-Manager/misc/portable-install.png create mode 100644 custom_nodes/ComfyUI-Manager/misc/share-setting.jpg create mode 100644 custom_nodes/ComfyUI-Manager/misc/share.jpg create mode 100644 custom_nodes/ComfyUI-Manager/misc/snapshot.jpg create mode 100644 custom_nodes/ComfyUI-Manager/model-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/dev/custom-node-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/dev/extension-node-map.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/dev/github-stats.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/dev/model-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/dev/scan.sh create mode 100644 custom_nodes/ComfyUI-Manager/node_db/forked/custom-node-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/forked/extension-node-map.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/forked/model-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/forked/scan.sh create mode 100644 custom_nodes/ComfyUI-Manager/node_db/legacy/alter-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/legacy/custom-node-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/legacy/extension-node-map.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/legacy/model-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/new/alter-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/new/custom-node-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/new/extension-node-map.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/new/model-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/tutorial/custom-node-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/tutorial/extension-node-map.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/tutorial/model-list.json create mode 100644 custom_nodes/ComfyUI-Manager/node_db/tutorial/scan.sh create mode 100644 custom_nodes/ComfyUI-Manager/notebooks/comfyui_colab_with_manager.ipynb create mode 100644 custom_nodes/ComfyUI-Manager/pip_overrides.json.template create mode 100644 custom_nodes/ComfyUI-Manager/prestartup_script.py create mode 100644 custom_nodes/ComfyUI-Manager/pyproject.toml create mode 100644 custom_nodes/ComfyUI-Manager/requirements.txt create mode 100644 custom_nodes/ComfyUI-Manager/scan.sh create mode 100644 custom_nodes/ComfyUI-Manager/scanner.py create mode 100644 custom_nodes/ComfyUI-Manager/scripts/colab-dependencies.py create mode 100644 custom_nodes/ComfyUI-Manager/scripts/install-comfyui-venv-linux.sh create mode 100644 custom_nodes/ComfyUI-Manager/scripts/install-comfyui-venv-win.bat create mode 100644 custom_nodes/ComfyUI-Manager/scripts/install-manager-for-portable-version.bat create mode 100644 custom_nodes/ComfyUI-Manager/scripts/update-fix.py create mode 100644 custom_nodes/ComfyUI-Manager/snapshots/the_snapshot_files_are_located_here diff --git a/custom_nodes/ComfyUI-Manager/LICENSE.txt b/custom_nodes/ComfyUI-Manager/LICENSE.txt new file mode 100644 index 000000000..f288702d2 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/LICENSE.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/custom_nodes/ComfyUI-Manager/README.md b/custom_nodes/ComfyUI-Manager/README.md new file mode 100644 index 000000000..259168126 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/README.md @@ -0,0 +1,415 @@ +# ComfyUI Manager + +**ComfyUI-Manager** is an extension designed to enhance the usability of [ComfyUI](https://github.com/comfyanonymous/ComfyUI). It offers management functions to **install, remove, disable, and enable** various custom nodes of ComfyUI. Furthermore, this extension provides a hub feature and convenience functions to access a wide range of information within ComfyUI. + +![menu](misc/menu.jpg) + +## NOTICE +* V2.37 Show a ✅ mark to accounts that have been active on GitHub for more than six months. +* V2.33 Security policy is applied. +* V2.21 [cm-cli](docs/en/cm-cli.md) tool is added. +* V2.18 to V2.18.3 is not functioning due to a severe bug. Users on these versions are advised to promptly update to V2.18.4. Please navigate to the `ComfyUI/custom_nodes/ComfyUI-Manager` directory and execute `git pull` to update. +* You can see whole nodes info on [ComfyUI Nodes Info](https://ltdrdata.github.io/) page. + +## Installation + +### Installation[method1] (General installation method: ComfyUI-Manager only) + +To install ComfyUI-Manager in addition to an existing installation of ComfyUI, you can follow the following steps: + +1. goto `ComfyUI/custom_nodes` dir in terminal(cmd) +2. `git clone https://github.com/ltdrdata/ComfyUI-Manager.git` +3. Restart ComfyUI + + +### Installation[method2] (Installation for portable ComfyUI version: ComfyUI-Manager only) +1. install git +- https://git-scm.com/download/win +- standalone version +- select option: use windows default console window +2. Download [scripts/install-manager-for-portable-version.bat](https://github.com/ltdrdata/ComfyUI-Manager/raw/main/scripts/install-manager-for-portable-version.bat) into installed `"ComfyUI_windows_portable"` directory +3. double click `install-manager-for-portable-version.bat` batch file + +![portable-install](misc/portable-install.png) + + +### Installation[method3] (Installation through comfy-cli: install ComfyUI and ComfyUI-Manager at once.) +> RECOMMENDED: comfy-cli provides various features to manage ComfyUI from the CLI. + +* **prerequisite: python 3, git** + +Windows: +```commandline +python -m venv venv +venv\Scripts\activate +pip install comfy-cli +comfy install +``` + +Linux/OSX: +```commandline +python -m venv venv +. venv/bin/activate +pip install comfy-cli +comfy install +``` + + +### Installation[method4] (Installation for linux+venv: ComfyUI + ComfyUI-Manager) + +To install ComfyUI with ComfyUI-Manager on Linux using a venv environment, you can follow these steps: +* **prerequisite: python-is-python3, python3-venv, git** + +1. Download [scripts/install-comfyui-venv-linux.sh](https://github.com/ltdrdata/ComfyUI-Manager/raw/main/scripts/install-comfyui-venv-linux.sh) into empty install directory +- ComfyUI will be installed in the subdirectory of the specified directory, and the directory will contain the generated executable script. +2. `chmod +x install-comfyui-venv-linux.sh` +3. `./install-comfyui-venv-linux.sh` + +### Installation Precautions +* **DO**: `ComfyUI-Manager` files must be accurately located in the path `ComfyUI/custom_nodes/ComfyUI-Manager` + * Installing in a compressed file format is not recommended. +* **DON'T**: Decompress directly into the `ComfyUI/custom_nodes` location, resulting in the Manager contents like `__init__.py` being placed directly in that directory. + * You have to remove all ComfyUI-Manager files from `ComfyUI/custom_nodes` +* **DON'T**: In a form where decompression occurs in a path such as `ComfyUI/custom_nodes/ComfyUI-Manager/ComfyUI-Manager`. + * You have to move `ComfyUI/custom_nodes/ComfyUI-Manager/ComfyUI-Manager` to `ComfyUI/custom_nodes/ComfyUI-Manager` +* **DON'T**: In a form where decompression occurs in a path such as `ComfyUI/custom_nodes/ComfyUI-Manager-main`. + * In such cases, `ComfyUI-Manager` may operate, but it won't be recognized within `ComfyUI-Manager`, and updates cannot be performed. It also poses the risk of duplicate installations. + * You have to rename `ComfyUI/custom_nodes/ComfyUI-Manager-main` to `ComfyUI/custom_nodes/ComfyUI-Manager` + + +You can execute ComfyUI by running either `./run_gpu.sh` or `./run_cpu.sh` depending on your system configuration. + +## Colab Notebook +This repository provides Colab notebooks that allow you to install and use ComfyUI, including ComfyUI-Manager. To use ComfyUI, [click on this link](https://colab.research.google.com/github/ltdrdata/ComfyUI-Manager/blob/main/notebooks/comfyui_colab_with_manager.ipynb). +* Support for installing ComfyUI +* Support for basic installation of ComfyUI-Manager +* Support for automatically installing dependencies of custom nodes upon restarting Colab notebooks. + +## Changes +* **2.38** `Install Custom Nodes` menu is changed to `Custom Nodes Manager`. +* **2.21** [cm-cli](docs/en/cm-cli.md) tool is added. +* **2.4** Copy the connections of the nearest node by double-clicking. +* **2.2.3** Support Components System +* **0.29** Add `Update all` feature +* **0.25** support db channel + * You can directly modify the db channel settings in the `config.ini` file. + * If you want to maintain a new DB channel, please modify the `channels.list` and submit a PR. +* **0.23** support multiple selection +* **0.18.1** `skip update check` feature added. + * A feature that allows quickly opening windows in environments where update checks take a long time. +* **0.17.1** Bug fix for the issue where enable/disable of the web extension was not working. Compatibility patch for StableSwarmUI. + * Requires latest version of ComfyUI (Revision: 1240) +* **0.17** Support preview method setting feature. +* **0.14** Support robust update. +* **0.13** Support additional 'pip' section for install spec. +* **0.12** Better installation support for Windows. +* **0.9** Support keyword search in installer menu. +* **V0.7.1** Bug fix for the issue where updates were not being applied on Windows. + * **For those who have been using versions 0.6, please perform a manual git pull in the custom_nodes/ComfyUI-Manager directory.** +* **V0.7** To address the issue of a slow list refresh, separate the fetch update and update check processes. +* **V0.6** Support extension installation for missing nodes. +* **V0.5** Removed external git program dependencies. + + +## How To Use + +1. Click "Manager" button on main menu + + ![mainmenu](misc/main.jpg) + + +2. If you click on 'Install Custom Nodes' or 'Install Models', an installer dialog will open. + + ![menu](misc/menu.jpg) + + * There are three DB modes: `DB: Channel (1day cache)`, `DB: Local`, and `DB: Channel (remote)`. + * `Channel (1day cache)` utilizes Channel cache information with a validity period of one day to quickly display the list. + * This information will be updated when there is no cache, when the cache expires, or when external information is retrieved through the Channel (remote). + * Whenever you start ComfyUI anew, this mode is always set as the **default** mode. + * `Local` uses information stored locally in ComfyUI-Manager. + * This information will be updated only when you update ComfyUI-Manager. + * For custom node developers, they should use this mode when registering their nodes in `custom-node-list.json` and testing them. + * `Channel (remote)` retrieves information from the remote channel, always displaying the latest list. + * In cases where retrieval is not possible due to network errors, it will forcibly use local information. + + * The ```Fetch Updates``` menu retrieves update data for custom nodes locally. Actual updates are applied by clicking the ```Update``` button in the ```Install Custom Nodes``` menu. + +3. Click 'Install' or 'Try Install' button. + + ![node-install-dialog](misc/custom-nodes.jpg) + + ![model-install-dialog](misc/models.png) + + * Installed: This item is already installed. + * Install: Clicking this button will install the item. + * Try Install: This is a custom node of which installation information cannot be confirmed. Click the button to try installing it. + + * If a red background `Channel` indicator appears at the top, it means it is not the default channel. Since the amount of information held is different from the default channel, many custom nodes may not appear in this channel state. + * Channel settings have a broad impact, affecting not only the node list but also all functions like "Update all." + * Conflicted Nodes with a yellow background show a list of nodes conflicting with other extensions in the respective extension. This issue needs to be addressed by the developer, and users should be aware that due to these conflicts, some nodes may not function correctly and may need to be installed accordingly. + +4. If you set the `Badge:` item in the menu as `Badge: Nickname`, `Badge: Nickname (hide built-in)`, `Badge: #ID Nickname`, `Badge: #ID Nickname (hide built-in)` the information badge will be displayed on the node. + * When selecting (hide built-in), it hides the 🦊 icon, which signifies built-in nodes. + * Nodes without any indication on the badge are custom nodes that Manager cannot recognize. + * `Badge: Nickname` displays the nickname of custom nodes, while `Badge: #ID Nickname` also includes the internal ID of the node. + + ![model-install-dialog](misc/nickname.jpg) + + +5. Share + ![menu](misc/main.jpg) ![share](misc/share.jpg) + + * You can share the workflow by clicking the Share button at the bottom of the main menu or selecting Share Output from the Context Menu of the Image node. + * Currently, it supports sharing via [https://comfyworkflows.com/](https://comfyworkflows.com/), + [https://openart.ai](https://openart.ai/workflows/dev), [https://youml.com](https://youml.com) + as well as through the Matrix channel. + + ![menu](misc/share-setting.jpg) + + * Through the Share settings in the Manager menu, you can configure the behavior of the Share button in the Main menu or Share Ouput button on Context Menu. + * `None`: hide from Main menu + * `All`: Show a dialog where the user can select a title for sharing. + + +## Snapshot-Manager +* When you press `Save snapshot` or use `Update All` on `Manager Menu`, the current installation status snapshot is saved. + * Snapshot file dir: `ComfyUI-Manager/snapshots` + * You can rename snapshot file. +* Press the "Restore" button to revert to the installation status of the respective snapshot. + * However, for custom nodes not managed by Git, snapshot support is incomplete. +* When you press `Restore`, it will take effect on the next ComfyUI startup. + * The selected snapshot file is saved in `ComfyUI-Manager/startup-scripts/restore-snapshot.json`, and upon restarting ComfyUI, the snapshot is applied and then deleted. + +![model-install-dialog](misc/snapshot.jpg) + + +## cm-cli: command line tools for power user +* A tool is provided that allows you to use the features of ComfyUI-Manager without running ComfyUI. +* For more details, please refer to the [cm-cli documentation](docs/en/cm-cli.md). + + +## How to register your custom node into ComfyUI-Manager + +* Add an entry to `custom-node-list.json` located in the root of ComfyUI-Manager and submit a Pull Request. +* NOTE: Before submitting the PR after making changes, please check `Use local DB` and ensure that the extension list loads without any issues in the `Install custom nodes` dialog. Occasionally, missing or extra commas can lead to JSON syntax errors. +* The remaining JSON will be updated through scripts in the future, so you don't need to worry about it. + + +## Custom node support guide + +* Currently, the system operates by cloning the git repository and sequentially installing the dependencies listed in requirements.txt using pip, followed by invoking the install.py script. In the future, we plan to discuss and determine the specifications for supporting custom nodes. + +* Please submit a pull request to update either the custom-node-list.json or model-list.json file. + +* The scanner currently provides a detection function for missing nodes, which is capable of detecting nodes described by the following two patterns. + * Or you can provide manually `node_list.json` file. + +``` +NODE_CLASS_MAPPINGS = { + "ExecutionSwitch": ExecutionSwitch, + "ExecutionBlocker": ExecutionBlocker, + ... +} + +NODE_CLASS_MAPPINGS.update({ + "UniFormer-SemSegPreprocessor": Uniformer_SemSegPreprocessor, + "SemSegPreprocessor": Uniformer_SemSegPreprocessor, +}) +``` + +* When you write a docstring in the header of the .py file for the Node as follows, it will be used for managing the database in the Manager. + * Currently, only the `nickname` is being used, but other parts will also be utilized in the future. + * The `nickname` will be the name displayed on the badge of the node. + * If there is no `nickname`, it will be truncated to 20 characters from the arbitrarily written title and used. +``` +""" +@author: Dr.Lt.Data +@title: Impact Pack +@nickname: Impact Pack +@description: This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler. +""" +``` + + +* **Special purpose files** (optional) + * `node_list.json` - When your custom nodes pattern of NODE_CLASS_MAPPINGS is not conventional, it is used to manually provide a list of nodes for reference. ([example](https://github.com/melMass/comfy_mtb/raw/main/node_list.json)) + * `requirements.txt` - When installing, this pip requirements will be installed automatically + * `install.py` - When installing, it is automatically called + * `uninstall.py` - When uninstalling, it is automatically called + * `disable.py` - When disabled, it is automatically called + * When installing a custom node setup `.js` file, it is recommended to write this script for disabling. + * `enable.py` - When enabled, it is automatically called + * **All scripts are executed from the root path of the corresponding custom node.** + + +## Component Sharing +* **Copy & Paste** + * [Demo Page](https://ltdrdata.github.io/component-demo/) + * When pasting a component from the clipboard, it supports text in the following JSON format. (text/plain) + ``` + { + "kind": "ComfyUI Components", + "timestamp": , + "components": + { + : + } + } + ``` + * `` Ensure that the timestamp is always unique. + * "components" should have the same structure as the content of the file stored in ComfyUI-Manager/components. + * ``: The name should be in the format `::`. + * ``: In the nodedata of the group node. + * ``: Only two formats are allowed: `major.minor.patch` or `major.minor`. (e.g. `1.0`, `2.2.1`) + * ``: Saved time + * ``: If the packname is not empty, the category becomes packname/workflow, and it is saved in the .pack file in ComfyUI-Manager/components. + * ``: If there is neither a category nor a packname, it is saved in the components category. + ``` + "version":"1.0", + "datetime": 1705390656516, + "packname": "mypack", + "category": "util/pipe", + ``` +* **Drag & Drop** + * Dragging and dropping a `.pack` or `.json` file will add the corresponding components. + * Example pack: [Impact.pack](misc/Impact.pack) + +* Dragging and dropping or pasting a single component will add a node. However, when adding multiple components, nodes will not be added. + + +## Support of missing nodes installation + +![missing-menu](misc/missing-menu.jpg) + +* When you click on the ```Install Missing Custom Nodes``` button in the menu, it displays a list of extension nodes that contain nodes not currently present in the workflow. + +![missing-list](misc/missing-list.jpg) + + +## Additional Feature +* Logging to file feature + * This feature is enabled by default and can be disabled by setting `file_logging = False` in the `config.ini`. + +* Fix node(recreate): When right-clicking on a node and selecting `Fix node (recreate)`, you can recreate the node. The widget's values are reset, while the connections maintain those with the same names. + * It is used to correct errors in nodes of old workflows created before, which are incompatible with the version changes of custom nodes. + +* Double-Click Node Title: You can set the double click behavior of nodes in the ComfyUI-Manager menu. + * `Copy All Connections`, `Copy Input Connections`: Double-clicking a node copies the connections of the nearest node. + * This action targets the nearest node within a straight-line distance of 1000 pixels from the center of the node. + * In the case of `Copy All Connections`, it duplicates existing outputs, but since it does not allow duplicate connections, the existing output connections of the original node are disconnected. + * This feature copies only the input and output that match the names. + + * `Possible Input Connections`: It connects all outputs that match the closest type within the specified range. + * This connection links to the closest outputs among the nodes located on the left side of the target node. + + * `Possible(left) + Copy(right)`: When you Double-Click on the left half of the title, it operates as `Possible Input Connections`, and when you Double-Click on the right half, it operates as `Copy All Connections`. + +* Prevent downgrade of specific packages + * List the package names in the `downgrade_blacklist` section of the `config.ini` file, separating them with commas. + * e.g + ``` + downgrade_blacklist = diffusers, kornia + ``` + +* Custom pip mapping + * When you create the `pip_overrides.json` file, it changes the installation of specific pip packages to installations defined by the user. + * Please refer to the `pip_overrides.json.template` file. + +* Use `aria2` as downloader + * [howto](docs/en/use_aria2.md) + +## Scanner +When you run the `scan.sh` script: + +* It updates the `extension-node-map.json`. + * To do this, it pulls or clones the custom nodes listed in `custom-node-list.json` into `~/.tmp/default`. + * To skip this step, add the `--skip-update` option. + * If you want to specify a different path instead of `~/.tmp/default`, run `python scanner.py [path]` directly instead of `scan.sh`. + +* It updates the `github-stats.json`. + * This uses the GitHub API, so set your token with `export GITHUB_TOKEN=your_token_here` to avoid quickly reaching the rate limit and malfunctioning. + * To skip this step, add the `--skip-update-stat` option. + +* The `--skip-all` option applies both `--skip-update` and `--skip-stat-update`. + + +## Troubleshooting +* If your `git.exe` is installed in a specific location other than system git, please install ComfyUI-Manager and run ComfyUI. Then, specify the path including the file name in `git_exe = ` in the ComfyUI-Manager/config.ini file that is generated. +* If updating ComfyUI-Manager itself fails, please go to the **ComfyUI-Manager** directory and execute the command `git update-ref refs/remotes/origin/main a361cc1 && git fetch --all && git pull`. + * Alternatively, download the update-fix.py script from [update-fix.py](https://github.com/ltdrdata/ComfyUI-Manager/raw/main/scripts/update-fix.py) and place it in the ComfyUI-Manager directory. Then, run it using your Python command. + For the portable version, use `..\..\..\python_embeded\python.exe update-fix.py`. +* For cases where nodes like `PreviewTextNode` from `ComfyUI_Custom_Nodes_AlekPet` are only supported as front-end nodes, we currently do not provide missing nodes for them. +* Currently, `vid2vid` is not being updated, causing compatibility issues. +* If you encounter the error message `Overlapped Object has pending operation at deallocation on Comfyui Manager load` under Windows + * Edit `config.ini` file: add `windows_selector_event_loop_policy = True` +* if `SSL: CERTIFICATE_VERIFY_FAILED` error is occured. + * Edit `config.ini` file: add `bypass_ssl = True` + +## Security policy + * Edit `config.ini` file: add `security_level = ` + * `strong` + * doesn't allow `high` and `middle` level risky feature + * `normal` + * doesn't allow `high` level risky feature if `--listen` is specified and not starts with `127.` + * `middle` level risky feature is available + * `weak` + * all feature is available + + * `high` level risky features + * `Install via git url`, `pip install` + * Installation of custom nodes registered not in the `default channel`. + * Display terminal log + + * `middle` level risky features + * Uninstall/Update/Fix custom nodes + * Installation of custom nodes registered in the `default channel`. + * Restore/Remove Snapshot + * Restart + + * `low` level risky features + * Update ComfyUI + + +## TODO: Unconventional form of custom node list + +* https://github.com/diontimmer/Sample-Diffusion-ComfyUI-Extension +* https://github.com/senshilabs/NINJA-plugin +* https://github.com/MockbaTheBorg/Nodes +* https://github.com/StartHua/Comfyui_GPT_Story +* https://github.com/NielsGercama/comfyui_customsampling +* https://github.com/wrightdaniel2017/ComfyUI-VideoLipSync +* https://github.com/bxdsjs/ComfyUI-Image-preprocessing +* https://github.com/SMUELDigital/ComfyUI-ONSET +* https://github.com/SimithWang/comfyui-renameImages +* https://github.com/icefairy64/comfyui-model-tilt +* https://github.com/andrewharp/ComfyUI-EasyNodes +* https://github.com/SimithWang/comfyui-renameImages +* https://github.com/Tcheko243/ComfyUI-Photographer-Alpha7-Nodes +* https://github.com/Limbicnation/ComfyUINodeToolbox + +## Roadmap + +- [x] System displaying information about failed custom nodes import. +- [x] Guide for missing nodes in ComfyUI vanilla nodes. +- [x] Collision checking system for nodes with the same ID across extensions. +- [x] Template sharing system. (-> Component system based on Group Nodes) +- [x] 3rd party API system. +- [ ] Auto migration for custom nodes with changed structures. +- [ ] Version control feature for nodes. +- [ ] List of currently used custom nodes. +- [x] Download support multiple model download. +- [x] Model download via url. +- [x] List sorting (custom nodes). +- [x] List sorting (model). +- [ ] Provides description of node. + + +# Disclaimer + +* This extension simply provides the convenience of installing custom nodes and does not guarantee their proper functioning. + + +## Credit +ComfyUI/[ComfyUI](https://github.com/comfyanonymous/ComfyUI) - A powerful and modular stable diffusion GUI. + +**And, for all ComfyUI custom node developers** diff --git a/custom_nodes/ComfyUI-Manager/__init__.py b/custom_nodes/ComfyUI-Manager/__init__.py new file mode 100644 index 000000000..ab85975c3 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/__init__.py @@ -0,0 +1,15 @@ +import os + +cli_mode_flag = os.path.join(os.path.dirname(__file__), '.enable-cli-only-mode') + +if not os.path.exists(cli_mode_flag): + from .glob import manager_server + WEB_DIRECTORY = "js" +else: + print(f"\n[ComfyUI-Manager] !! cli-only-mode is enabled !!\n") + +NODE_CLASS_MAPPINGS = {} +__all__ = ['NODE_CLASS_MAPPINGS'] + + + diff --git a/custom_nodes/ComfyUI-Manager/alter-list.json b/custom_nodes/ComfyUI-Manager/alter-list.json new file mode 100644 index 000000000..33398277e --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/alter-list.json @@ -0,0 +1,224 @@ +{ + "items": [ + { + "id":"https://github.com/Fannovel16/comfyui_controlnet_aux", + "tags":"controlnet", + "description": "This extension provides preprocessor nodes for using controlnet." + }, + { + "id":"https://github.com/comfyanonymous/ComfyUI_experiments", + "tags":"Dynamic Thresholding, DT, CFG, controlnet, reference only", + "description": "This experimental nodes contains a 'Reference Only' node and a 'ModelSamplerTonemapNoiseTest' node corresponding to the 'Dynamic Threshold'." + }, + { + "id":"https://github.com/ltdrdata/ComfyUI-Impact-Pack", + "tags":"ddetailer, adetailer, ddsd, DD, loopback scaler, prompt, wildcard, dynamic prompt", + "description": "To implement the feature of automatically detecting faces and enhancing details, various detection nodes and detailers provided by the Impact Pack can be applied. Similarly to Loopback Scaler, it also provides various custom workflows that can apply Ksampler while gradually scaling up." + }, + { + "id":"https://github.com/ltdrdata/ComfyUI-Inspire-Pack", + "tags":"lora block weight, effective block analyzer, lbw, variation seed", + "description": "The Inspire Pack provides the functionality of Lora Block Weight, Variation Seed." + }, + { + "id":"https://github.com/biegert/ComfyUI-CLIPSeg/raw/main/custom_nodes/clipseg.py", + "tags":"ddsd", + "description": "This extension provides a feature that generates segment masks on an image using a text prompt. When used in conjunction with Impact Pack, it enables applications such as DDSD." + }, + { + "id":"https://github.com/BadCafeCode/masquerade-nodes-comfyui", + "tags":"ddetailer", + "description": "This extension is a less feature-rich and well-maintained alternative to Impact Pack, but it has fewer dependencies and may be easier to install on abnormal configurations. The author recommends trying Impact Pack first." + }, + { + "id":"https://github.com/BlenderNeko/ComfyUI_Cutoff", + "tags":"cutoff", + "description": "By using this extension, prompts like 'blue hair' can be prevented from interfering with other prompts by blocking the attribute 'blue' from being used in prompts other than 'hair'." + }, + { + "id":"https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb", + "tags":"prompt, weight", + "description": "There are differences in the processing methods of prompts, such as weighting and scheduling, between A1111 and ComfyUI. With this extension, various settings can be used to implement prompt processing methods similar to A1111. As this feature is also integrated into ComfyUI Cutoff, please download the Cutoff extension if you plan to use it in conjunction with Cutoff." + }, + { + "id":"https://github.com/shiimizu/ComfyUI_smZNodes", + "tags":"prompt, weight", + "description": "There are differences in the processing methods of prompts, such as weighting and scheduling, between A1111 and ComfyUI. This extension helps to reproduce the same embedding as A1111." + }, + { + "id":"https://github.com/BlenderNeko/ComfyUI_Noise", + "tags":"img2img alt, random", + "description": "The extension provides an unsampler that reverses the sampling process, allowing for a function similar to img2img alt to be implemented. Furthermore, ComfyUI uses CPU's Random instead of GPU's Random for better reproducibility compared to A1111. This extension provides the ability to use GPU's Random for Latent Noise. However, since GPU's Random may vary depending on the GPU model, reproducibility on different devices cannot be guaranteed." + }, + { + "id":"https://github.com/BlenderNeko/ComfyUI_SeeCoder", + "tags":"seecoder, prompt-free-diffusion", + "description": "The extension provides seecoder feature." + }, + { + "id":"https://github.com/lilly1987/ComfyUI_node_Lilly", + "tags":"prompt, wildcard", + "description": "This extension provides features such as a wildcard function that randomly selects prompts belonging to a category and the ability to directly load lora from prompts." + }, + { + "id":"https://github.com/Davemane42/ComfyUI_Dave_CustomNode", + "tags":"latent couple", + "description": "ComfyUI already provides the ability to composite latents by default. However, this extension makes it more convenient to use by visualizing the composite area." + }, + { + "id":"https://github.com/LEv145/images-grid-comfy-plugin", + "tags":"X/Y Plot", + "description": "This tool provides a viewer node that allows for checking multiple outputs in a grid, similar to the X/Y Plot extension." + }, + { + "id":"https://github.com/pythongosssss/ComfyUI-WD14-Tagger", + "tags":"deepbooru, clip interrogation", + "description": "This extension generates clip text by taking an image as input and using the Deepbooru model." + }, + { + "id":"https://github.com/szhublox/ambw_comfyui", + "tags":"supermerger", + "description": "This node takes two models, merges individual blocks together at various ratios, and automatically rates each merge, keeping the ratio with the highest score. " + }, + { + "id":"https://github.com/ssitu/ComfyUI_UltimateSDUpscale", + "tags":"upscaler, Ultimate SD Upscale", + "description": "ComfyUI nodes for the Ultimate Stable Diffusion Upscale script by Coyote-A. Uses the same script used in the A1111 extension to hopefully replicate images generated using the A1111 webui." + }, + { + "id":"https://github.com/dawangraoming/ComfyUI_ksampler_gpu/raw/main/ksampler_gpu.py", + "tags":"random, noise", + "description": "A1111 provides KSampler that uses GPU-based random noise. This extension offers KSampler utilizing GPU-based random noise." + }, + { + "id":"https://github.com/space-nuko/nui-suite", + "tags":"prompt, dynamic prompt", + "description": "This extension provides nodes with the functionality of dynamic prompts." + }, + { + "id":"https://github.com/melMass/comfy_mtb", + "tags":"roop", + "description": "This extension provides bunch of nodes including roop" + }, + { + "id":"https://github.com/ssitu/ComfyUI_roop", + "tags":"roop", + "description": "This extension provides nodes for the roop A1111 webui script." + }, + { + "id":"https://github.com/asagi4/comfyui-prompt-control", + "tags":"prompt, prompt editing", + "description": "This extension provides the ability to use prompts like \n\n**a [large::0.1] [cat|dog:0.05] [::0.5] [in a park:in space:0.4]**\n\n" + }, + { + "id":"https://github.com/adieyal/comfyui-dynamicprompts", + "tags":"prompt, dynamic prompt", + "description": "This extension is a port of sd-dynamic-prompt to ComfyUI." + }, + { + "id":"https://github.com/kwaroran/abg-comfyui", + "tags":"abg, background remover", + "description": "A Anime Background Remover node for comfyui, based on this hf space, works same as AGB extention in automatic1111." + }, + { + "id":"https://github.com/Gourieff/comfyui-reactor-node", + "tags":"reactor, sd-webui-roop-nsfw", + "description": "This is a ported version of ComfyUI for the sd-webui-roop-nsfw extension." + }, + { + "id":"https://github.com/laksjdjf/cgem156-ComfyUI", + "tags":"regional prompt, latent couple, prompt", + "description": "This custom nodes provide a functionality similar to regional prompts, offering couple features at the attention level." + }, + { + "id":"https://github.com/FizzleDorf/ComfyUI_FizzNodes", + "tags":"deforum", + "description": "This custom nodes provide functionality that assists in animation creation, similar to deforum." + }, + { + "id":"https://github.com/seanlynch/comfyui-optical-flow", + "tags":"deforum, vid2vid", + "description": "This custom nodes provide functionality that assists in animation creation, similar to deforum." + }, + { + "id":"https://github.com/ssitu/ComfyUI_fabric", + "tags":"fabric", + "description": "Similar to sd-webui-fabric, this custom nodes provide the functionality of [a/FABRIC](https://github.com/sd-fabric/fabric)." + }, + { + "id":"https://github.com/Zuellni/ComfyUI-ExLlama", + "tags":"ExLlama, prompt, language model", + "description": "Similar to text-generation-webui, this custom nodes provide the functionality of [a/exllama](https://github.com/turboderp/exllama)." + }, + { + "id":"https://github.com/spinagon/ComfyUI-seamless-tiling", + "tags":"tiling", + "description": "ComfyUI node for generating seamless textures Replicates 'Tiling' option from A1111" + }, + { + "id":"https://github.com/laksjdjf/cd-tuner_negpip-ComfyUI", + "tags":"cd-tuner, negpip", + "description": "This extension is a port of the [a/sd-webui-cd-tuner](https://github.com/hako-mikan/sd-webui-cd-tuner)(a.k.a. CD(color/Detail) Tuner )and [a/sd-webui-negpip](https://github.com/hako-mikan/sd-webui-negpip)(a.k.a. NegPiP) extensions of A1111 to ComfyUI." + }, + { + "id":"https://github.com/mcmonkeyprojects/sd-dynamic-thresholding", + "tags":"DT, dynamic thresholding", + "description": "This custom node is a port of the Dynamic Thresholding extension from A1111 to make it available for use in ComfyUI." + }, + { + "id":"https://github.com/hhhzzyang/Comfyui_Lama", + "tags":"lama, inpainting anything", + "description": "This extension provides custom nodes developed based on [a/LaMa](https://github.com/advimman/lama) and [a/Inpainting anything](https://github.com/geekyutao/Inpaint-Anything)." + }, + { + "id":"https://github.com/mlinmg/ComfyUI-LaMA-Preprocessor", + "tags":"lama", + "description": "This extension provides custom nodes for [a/LaMa](https://github.com/advimman/lama) functionality." + }, + { + "id":"https://github.com/Haoming02/comfyui-diffusion-cg", + "tags":"diffusion-cg", + "description": "This extension provides custom nodes for [a/SD Webui Diffusion Color Grading](https://github.com/Haoming02/sd-webui-diffusion-cg) functionality." + }, + { + "id":"https://github.com/asagi4/ComfyUI-CADS", + "tags":"diffusion-cg", + "description": "This extension provides custom nodes for [a/sd-webui-cads](https://github.com/v0xie/sd-webui-cads) functionality." + }, + { + "id":"https://git.mmaker.moe/mmaker/sd-webui-color-enhance", + "tags":"color-enhance", + "description": "This extension supports both A1111 and ComfyUI simultaneously." + }, + { + "id":"https://github.com/shiimizu/ComfyUI-TiledDiffusion", + "tags":"multidiffusion", + "description": "This extension provides custom nodes for [a/Mixture of Diffusers](https://github.com/albarji/mixture-of-diffusers) and [a/MultiDiffusion](https://github.com/omerbt/MultiDiffusion)" + }, + { + "id":"https://github.com/abyz22/image_control", + "tags":"BMAB", + "description": "This extension provides some alternative functionalities of the [a/sd-webui-bmab](https://github.com/portu-sim/sd-webui-bmab) extension." + }, + { + "id":"https://github.com/blepping/ComfyUI-sonar", + "tags":"sonar", + "description": "This extension provides some alternative functionalities of the [a/stable-diffusion-webui-sonar](https://github.com/Kahsolt/stable-diffusion-webui-sonar) extension." + }, + { + "id":"https://github.com/AIFSH/ComfyUI-RVC", + "tags":"sonar", + "description": "a comfyui custom node for [a/Retrieval-based-Voice-Conversion-WebUI](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git), you can Voice-Conversion in comfyui now!" + }, + { + "id":"https://github.com/portu-sim/comfyui-bmab", + "tags":"bmab", + "description": "a comfyui custom node for [a/sd-webui-bmab](https://github.com/portu-sim/sd-webui-bmab)" + }, + { + "id":"https://github.com/ThereforeGames/ComfyUI-Unprompted", + "tags":"unprompted", + "description": "This extension is a port of [a/unprompted](https://github.com/ThereforeGames/unprompted)" + } + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/channels.list.template b/custom_nodes/ComfyUI-Manager/channels.list.template new file mode 100644 index 000000000..9a8d6877b --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/channels.list.template @@ -0,0 +1,6 @@ +default::https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main +recent::https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/node_db/new +legacy::https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/node_db/legacy +forked::https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/node_db/forked +dev::https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/node_db/dev +tutorial::https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/node_db/tutorial \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/check.bat b/custom_nodes/ComfyUI-Manager/check.bat new file mode 100644 index 000000000..e7a3b09fc --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/check.bat @@ -0,0 +1,21 @@ +@echo off + +python json-checker.py "custom-node-list.json" +python json-checker.py "model-list.json" +python json-checker.py "alter-list.json" +python json-checker.py "extension-node-map.json" +python json-checker.py "node_db\new\custom-node-list.json" +python json-checker.py "node_db\new\model-list.json" +python json-checker.py "node_db\new\extension-node-map.json" +python json-checker.py "node_db\dev\custom-node-list.json" +python json-checker.py "node_db\dev\model-list.json" +python json-checker.py "node_db\dev\extension-node-map.json" +python json-checker.py "node_db\tutorial\custom-node-list.json" +python json-checker.py "node_db\tutorial\model-list.json" +python json-checker.py "node_db\tutorial\extension-node-map.json" +python json-checker.py "node_db\legacy\custom-node-list.json" +python json-checker.py "node_db\legacy\model-list.json" +python json-checker.py "node_db\legacy\extension-node-map.json" +python json-checker.py "node_db\forked\custom-node-list.json" +python json-checker.py "node_db\forked\model-list.json" +python json-checker.py "node_db\forked\extension-node-map.json" \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/check.sh b/custom_nodes/ComfyUI-Manager/check.sh new file mode 100644 index 000000000..6fa408c7c --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/check.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +echo +echo CHECK1 + +files=( + "custom-node-list.json" + "model-list.json" + "alter-list.json" + "extension-node-map.json" + "github-stats.json" + "node_db/new/custom-node-list.json" + "node_db/new/model-list.json" + "node_db/new/extension-node-map.json" + "node_db/dev/custom-node-list.json" + "node_db/dev/model-list.json" + "node_db/dev/extension-node-map.json" + "node_db/tutorial/custom-node-list.json" + "node_db/tutorial/model-list.json" + "node_db/tutorial/extension-node-map.json" + "node_db/legacy/custom-node-list.json" + "node_db/legacy/model-list.json" + "node_db/legacy/extension-node-map.json" + "node_db/forked/custom-node-list.json" + "node_db/forked/model-list.json" + "node_db/forked/extension-node-map.json" +) + +for file in "${files[@]}"; do + python json-checker.py "$file" +done + +echo +echo CHECK2 +find ~/.tmp/default -name "*.py" -print0 | xargs -0 grep "crypto" + +echo +echo CHECK3 +find ~/.tmp/default -name "requirements.txt" | xargs grep "^\s*https\\?:" +find ~/.tmp/default -name "requirements.txt" | xargs grep "\.whl" + +echo diff --git a/custom_nodes/ComfyUI-Manager/cm-cli.py b/custom_nodes/ComfyUI-Manager/cm-cli.py new file mode 100644 index 000000000..518461c56 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/cm-cli.py @@ -0,0 +1,1029 @@ +import os +import sys +import traceback +import json +import asyncio +import subprocess +import shutil +import concurrent +import threading +from typing import Optional + +import typer +from rich import print +from typing_extensions import List, Annotated +import re +import git + +sys.path.append(os.path.dirname(__file__)) +sys.path.append(os.path.join(os.path.dirname(__file__), "glob")) +import manager_core as core +import cm_global + +comfyui_manager_path = os.path.dirname(__file__) +comfy_path = os.environ.get('COMFYUI_PATH') + +if comfy_path is None: + print(f"\n[bold yellow]WARN: The `COMFYUI_PATH` environment variable is not set. Assuming `custom_nodes/ComfyUI-Manager/../../` as the ComfyUI path.[/bold yellow]", file=sys.stderr) + comfy_path = os.path.abspath(os.path.join(comfyui_manager_path, '..', '..')) + +startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts") +custom_nodes_path = os.path.join(comfy_path, 'custom_nodes') + +script_path = os.path.join(startup_script_path, "install-scripts.txt") +restore_snapshot_path = os.path.join(startup_script_path, "restore-snapshot.json") +pip_overrides_path = os.path.join(comfyui_manager_path, "pip_overrides.json") +git_script_path = os.path.join(comfyui_manager_path, "git_helper.py") + +cm_global.pip_downgrade_blacklist = ['torch', 'torchsde', 'torchvision', 'transformers', 'safetensors', 'kornia'] +cm_global.pip_overrides = {} +if os.path.exists(pip_overrides_path): + with open(pip_overrides_path, 'r', encoding="UTF-8", errors="ignore") as json_file: + cm_global.pip_overrides = json.load(json_file) + + +def check_comfyui_hash(): + repo = git.Repo(comfy_path) + core.comfy_ui_revision = len(list(repo.iter_commits('HEAD'))) + + comfy_ui_hash = repo.head.commit.hexsha + cm_global.variables['comfyui.revision'] = core.comfy_ui_revision + + core.comfy_ui_commit_datetime = repo.head.commit.committed_datetime + + +check_comfyui_hash() # This is a preparation step for manager_core + + +def read_downgrade_blacklist(): + try: + import configparser + config_path = os.path.join(os.path.dirname(__file__), "config.ini") + config = configparser.ConfigParser() + config.read(config_path) + default_conf = config['default'] + + if 'downgrade_blacklist' in default_conf: + items = default_conf['downgrade_blacklist'].split(',') + items = [x.strip() for x in items if x != ''] + cm_global.pip_downgrade_blacklist += items + cm_global.pip_downgrade_blacklist = list(set(cm_global.pip_downgrade_blacklist)) + except: + pass + + +read_downgrade_blacklist() # This is a preparation step for manager_core + + +class Ctx: + def __init__(self): + self.channel = 'default' + self.mode = 'remote' + self.processed_install = set() + self.custom_node_map_cache = None + + def set_channel_mode(self, channel, mode): + if mode is not None: + self.mode = mode + + valid_modes = ["remote", "local", "cache"] + if mode and mode.lower() not in valid_modes: + typer.echo( + f"Invalid mode: {mode}. Allowed modes are 'remote', 'local', 'cache'.", + err=True, + ) + exit(1) + + if channel is not None: + self.channel = channel + + def post_install(self, url): + try: + repository_name = url.split("/")[-1].strip() + repo_path = os.path.join(custom_nodes_path, repository_name) + repo_path = os.path.abspath(repo_path) + + requirements_path = os.path.join(repo_path, 'requirements.txt') + install_script_path = os.path.join(repo_path, 'install.py') + + if os.path.exists(requirements_path): + with (open(requirements_path, 'r', encoding="UTF-8", errors="ignore") as file): + for line in file: + package_name = core.remap_pip_package(line.strip()) + if package_name and not core.is_installed(package_name): + install_cmd = [sys.executable, "-m", "pip", "install", package_name] + output = subprocess.check_output(install_cmd, cwd=repo_path, text=True) + for msg_line in output.split('\n'): + if 'Requirement already satisfied:' in msg_line: + print('.', end='') + else: + print(msg_line) + + if os.path.exists(install_script_path) and f'{repo_path}/install.py' not in self.processed_install: + self.processed_install.add(f'{repo_path}/install.py') + install_cmd = [sys.executable, install_script_path] + output = subprocess.check_output(install_cmd, cwd=repo_path, text=True) + for msg_line in output.split('\n'): + if 'Requirement already satisfied:' in msg_line: + print('.', end='') + else: + print(msg_line) + + except Exception: + print(f"ERROR: Restoring '{url}' is failed.") + + def restore_dependencies(self): + node_paths = [os.path.join(custom_nodes_path, name) for name in os.listdir(custom_nodes_path) + if os.path.isdir(os.path.join(custom_nodes_path, name)) and not name.endswith('.disabled')] + + total = len(node_paths) + i = 1 + for x in node_paths: + print(f"----------------------------------------------------------------------------------------------------") + print(f"Restoring [{i}/{total}]: {x}") + self.post_install(x) + i += 1 + + def load_custom_nodes(self): + channel_dict = core.get_channel_dict() + if self.channel not in channel_dict: + print(f"[bold red]ERROR: Invalid channel is specified `--channel {self.channel}`[/bold red]", file=sys.stderr) + exit(1) + + if self.mode not in ['remote', 'local', 'cache']: + print(f"[bold red]ERROR: Invalid mode is specified `--mode {self.mode}`[/bold red]", file=sys.stderr) + exit(1) + + channel_url = channel_dict[self.channel] + + res = {} + json_obj = asyncio.run(core.get_data_by_mode(self.mode, 'custom-node-list.json', channel_url=channel_url)) + for x in json_obj['custom_nodes']: + for y in x['files']: + if 'github.com' in y and not (y.endswith('.py') or y.endswith('.js')): + repo_name = y.split('/')[-1] + res[repo_name] = (x, False) + + if 'id' in x: + if x['id'] not in res: + res[x['id']] = (x, True) + + return res + + def get_custom_node_map(self): + if self.custom_node_map_cache is not None: + return self.custom_node_map_cache + + self.custom_node_map_cache = self.load_custom_nodes() + + return self.custom_node_map_cache + + def lookup_node_path(self, node_name, robust=False): + if '..' in node_name: + print(f"\n[bold red]ERROR: Invalid node name '{node_name}'[/bold red]\n") + exit(2) + + custom_node_map = self.get_custom_node_map() + if node_name in custom_node_map: + node_url = custom_node_map[node_name][0]['files'][0] + repo_name = node_url.split('/')[-1] + node_path = os.path.join(custom_nodes_path, repo_name) + return node_path, custom_node_map[node_name][0] + elif robust: + node_path = os.path.join(custom_nodes_path, node_name) + return node_path, None + + print(f"\n[bold red]ERROR: Invalid node name '{node_name}'[/bold red]\n") + exit(2) + + +cm_ctx = Ctx() + + +def install_node(node_name, is_all=False, cnt_msg=''): + if core.is_valid_url(node_name): + # install via urls + res = core.gitclone_install([node_name]) + if not res: + print(f"[bold red]ERROR: An error occurred while installing '{node_name}'.[/bold red]") + else: + print(f"{cnt_msg} [INSTALLED] {node_name:50}") + else: + node_path, node_item = cm_ctx.lookup_node_path(node_name) + + if os.path.exists(node_path): + if not is_all: + print(f"{cnt_msg} [ SKIPPED ] {node_name:50} => Already installed") + elif os.path.exists(node_path + '.disabled'): + enable_node(node_name) + else: + res = core.gitclone_install(node_item['files'], instant_execution=True, msg_prefix=f"[{cnt_msg}] ") + if not res: + print(f"[bold red]ERROR: An error occurred while installing '{node_name}'.[/bold red]") + else: + print(f"{cnt_msg} [INSTALLED] {node_name:50}") + + +def reinstall_node(node_name, is_all=False, cnt_msg=''): + node_path, node_item = cm_ctx.lookup_node_path(node_name) + + if os.path.exists(node_path): + shutil.rmtree(node_path) + if os.path.exists(node_path + '.disabled'): + shutil.rmtree(node_path + '.disabled') + + install_node(node_name, is_all=is_all, cnt_msg=cnt_msg) + + +def fix_node(node_name, is_all=False, cnt_msg=''): + node_path, node_item = cm_ctx.lookup_node_path(node_name, robust=True) + + files = node_item['files'] if node_item is not None else [node_path] + + if os.path.exists(node_path): + print(f"{cnt_msg} [ FIXING ]: {node_name:50} => Disabled") + res = core.gitclone_fix(files, instant_execution=True) + if not res: + print(f"ERROR: An error occurred while fixing '{node_name}'.") + elif not is_all and os.path.exists(node_path + '.disabled'): + print(f"{cnt_msg} [ SKIPPED ]: {node_name:50} => Disabled") + elif not is_all: + print(f"{cnt_msg} [ SKIPPED ]: {node_name:50} => Not installed") + + +def uninstall_node(node_name, is_all=False, cnt_msg=''): + node_path, node_item = cm_ctx.lookup_node_path(node_name, robust=True) + + files = node_item['files'] if node_item is not None else [node_path] + + if os.path.exists(node_path) or os.path.exists(node_path + '.disabled'): + res = core.gitclone_uninstall(files) + if not res: + print(f"ERROR: An error occurred while uninstalling '{node_name}'.") + else: + print(f"{cnt_msg} [UNINSTALLED] {node_name:50}") + else: + print(f"{cnt_msg} [ SKIPPED ]: {node_name:50} => Not installed") + + +def update_node(node_name, is_all=False, cnt_msg=''): + node_path, node_item = cm_ctx.lookup_node_path(node_name, robust=True) + + files = node_item['files'] if node_item is not None else [node_path] + + res = core.gitclone_update(files, skip_script=True, msg_prefix=f"[{cnt_msg}] ") + + if not res: + print(f"ERROR: An error occurred while updating '{node_name}'.") + return None + + return node_path + + +def update_parallel(nodes): + is_all = False + if 'all' in nodes: + is_all = True + nodes = [x for x in cm_ctx.get_custom_node_map().keys() if os.path.exists(os.path.join(custom_nodes_path, x)) or os.path.exists(os.path.join(custom_nodes_path, x) + '.disabled')] + + nodes = [x for x in nodes if x.lower() not in ['comfy', 'comfyui', 'all']] + + total = len(nodes) + + lock = threading.Lock() + processed = [] + + i = 0 + + def process_custom_node(x): + nonlocal i + nonlocal processed + + with lock: + i += 1 + + try: + node_path = update_node(x, is_all=is_all, cnt_msg=f'{i}/{total}') + with lock: + processed.append(node_path) + except Exception as e: + print(f"ERROR: {e}") + traceback.print_exc() + + with concurrent.futures.ThreadPoolExecutor(4) as executor: + for item in nodes: + executor.submit(process_custom_node, item) + + i = 1 + for node_path in processed: + if node_path is None: + print(f"[{i}/{total}] Post update: ERROR") + else: + print(f"[{i}/{total}] Post update: {node_path}") + cm_ctx.post_install(node_path) + i += 1 + + +def update_comfyui(): + res = core.update_path(comfy_path, instant_execution=True) + if res == 'fail': + print("Updating ComfyUI has failed.") + elif res == 'updated': + print("ComfyUI is updated.") + else: + print("ComfyUI is already up to date.") + + +def enable_node(node_name, is_all=False, cnt_msg=''): + if node_name == 'ComfyUI-Manager': + return + + node_path, node_item = cm_ctx.lookup_node_path(node_name, robust=True) + + if os.path.exists(node_path + '.disabled'): + current_name = node_path + '.disabled' + os.rename(current_name, node_path) + print(f"{cnt_msg} [ENABLED] {node_name:50}") + elif os.path.exists(node_path): + print(f"{cnt_msg} [SKIPPED] {node_name:50} => Already enabled") + elif not is_all: + print(f"{cnt_msg} [SKIPPED] {node_name:50} => Not installed") + + +def disable_node(node_name, is_all=False, cnt_msg=''): + if node_name == 'ComfyUI-Manager': + return + + node_path, node_item = cm_ctx.lookup_node_path(node_name, robust=True) + + if os.path.exists(node_path): + current_name = node_path + new_name = node_path + '.disabled' + os.rename(current_name, new_name) + print(f"{cnt_msg} [DISABLED] {node_name:50}") + elif os.path.exists(node_path + '.disabled'): + print(f"{cnt_msg} [ SKIPPED] {node_name:50} => Already disabled") + elif not is_all: + print(f"{cnt_msg} [ SKIPPED] {node_name:50} => Not installed") + + +def show_list(kind, simple=False): + for k, v in cm_ctx.get_custom_node_map().items(): + if v[1]: + continue + + node_path = os.path.join(custom_nodes_path, k) + + states = set() + if os.path.exists(node_path): + prefix = '[ ENABLED ] ' + states.add('installed') + states.add('enabled') + states.add('all') + elif os.path.exists(node_path + '.disabled'): + prefix = '[ DISABLED ] ' + states.add('installed') + states.add('disabled') + states.add('all') + else: + prefix = '[ NOT INSTALLED ] ' + states.add('not-installed') + states.add('all') + + if kind in states: + if simple: + print(f"{k:50}") + else: + short_id = v[0].get('id', "") + print(f"{prefix} {k:50} {short_id:20} (author: {v[0]['author']})") + + # unregistered nodes + candidates = os.listdir(os.path.realpath(custom_nodes_path)) + + for k in candidates: + fullpath = os.path.join(custom_nodes_path, k) + + if os.path.isfile(fullpath): + continue + + if k in ['__pycache__']: + continue + + states = set() + if k.endswith('.disabled'): + prefix = '[ DISABLED ] ' + states.add('installed') + states.add('disabled') + states.add('all') + k = k[:-9] + else: + prefix = '[ ENABLED ] ' + states.add('installed') + states.add('enabled') + states.add('all') + + if k not in cm_ctx.get_custom_node_map(): + if kind in states: + if simple: + print(f"{k:50}") + else: + print(f"{prefix} {k:50} {'':20} (author: N/A)") + + +def show_snapshot(simple_mode=False): + json_obj = core.get_current_snapshot() + + if simple_mode: + print(f"[{json_obj['comfyui']}] comfyui") + for k, v in json_obj['git_custom_nodes'].items(): + print(f"[{v['hash']}] {k}") + for v in json_obj['file_custom_nodes']: + print(f"[ N/A ] {v['filename']}") + + else: + formatted_json = json.dumps(json_obj, ensure_ascii=False, indent=4) + print(formatted_json) + + +def show_snapshot_list(simple_mode=False): + snapshot_path = os.path.join(comfyui_manager_path, 'snapshots') + + files = os.listdir(snapshot_path) + json_files = [x for x in files if x.endswith('.json')] + for x in sorted(json_files): + print(x) + + +def cancel(): + if os.path.exists(script_path): + os.remove(script_path) + + if os.path.exists(restore_snapshot_path): + os.remove(restore_snapshot_path) + + +def auto_save_snapshot(): + path = core.save_snapshot_with_postfix('cli-autosave') + print(f"Current snapshot is saved as `{path}`") + + +def for_each_nodes(nodes, act, allow_all=True): + is_all = False + if allow_all and 'all' in nodes: + is_all = True + nodes = [x for x in cm_ctx.get_custom_node_map().keys() if os.path.exists(os.path.join(custom_nodes_path, x)) or os.path.exists(os.path.join(custom_nodes_path, x) + '.disabled')] + + nodes = [x for x in nodes if x.lower() not in ['comfy', 'comfyui', 'all']] + + total = len(nodes) + i = 1 + for x in nodes: + try: + act(x, is_all=is_all, cnt_msg=f'{i}/{total}') + except Exception as e: + print(f"ERROR: {e}") + traceback.print_exc() + i += 1 + + +app = typer.Typer() + + +@app.command(help="Display help for commands") +def help(ctx: typer.Context): + print(ctx.find_root().get_help()) + ctx.exit(0) + + +@app.command(help="Install custom nodes") +def install( + nodes: List[str] = typer.Argument( + ..., help="List of custom nodes to install" + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + cm_ctx.set_channel_mode(channel, mode) + for_each_nodes(nodes, act=install_node) + + +@app.command(help="Reinstall custom nodes") +def reinstall( + nodes: List[str] = typer.Argument( + ..., help="List of custom nodes to reinstall" + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + cm_ctx.set_channel_mode(channel, mode) + for_each_nodes(nodes, act=reinstall_node) + + +@app.command(help="Uninstall custom nodes") +def uninstall( + nodes: List[str] = typer.Argument( + ..., help="List of custom nodes to uninstall" + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + cm_ctx.set_channel_mode(channel, mode) + for_each_nodes(nodes, act=uninstall_node) + + +@app.command(help="Disable custom nodes") +def update( + nodes: List[str] = typer.Argument( + ..., + help="[all|List of custom nodes to update]" + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + cm_ctx.set_channel_mode(channel, mode) + + if 'all' in nodes: + auto_save_snapshot() + + for x in nodes: + if x.lower() in ['comfyui', 'comfy', 'all']: + update_comfyui() + break + + update_parallel(nodes) + + +@app.command(help="Disable custom nodes") +def disable( + nodes: List[str] = typer.Argument( + ..., + help="[all|List of custom nodes to disable]" + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + cm_ctx.set_channel_mode(channel, mode) + + if 'all' in nodes: + auto_save_snapshot() + + for_each_nodes(nodes, disable_node, allow_all=True) + + +@app.command(help="Enable custom nodes") +def enable( + nodes: List[str] = typer.Argument( + ..., + help="[all|List of custom nodes to enable]" + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + cm_ctx.set_channel_mode(channel, mode) + + if 'all' in nodes: + auto_save_snapshot() + + for_each_nodes(nodes, enable_node, allow_all=True) + + +@app.command(help="Fix dependencies of custom nodes") +def fix( + nodes: List[str] = typer.Argument( + ..., + help="[all|List of custom nodes to fix]" + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + cm_ctx.set_channel_mode(channel, mode) + + if 'all' in nodes: + auto_save_snapshot() + + for_each_nodes(nodes, fix_node, allow_all=True) + + +@app.command("show", help="Show node list (simple mode)") +def show( + arg: str = typer.Argument( + help="[installed|enabled|not-installed|disabled|all|snapshot|snapshot-list]" + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + valid_commands = [ + "installed", + "enabled", + "not-installed", + "disabled", + "all", + "snapshot", + "snapshot-list", + ] + if arg not in valid_commands: + typer.echo(f"Invalid command: `show {arg}`", err=True) + exit(1) + + cm_ctx.set_channel_mode(channel, mode) + if arg == 'snapshot': + show_snapshot() + elif arg == 'snapshot-list': + show_snapshot_list() + else: + show_list(arg) + + +@app.command("simple-show", help="Show node list (simple mode)") +def simple_show( + arg: str = typer.Argument( + help="[installed|enabled|not-installed|disabled|all|snapshot|snapshot-list]" + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + valid_commands = [ + "installed", + "enabled", + "not-installed", + "disabled", + "all", + "snapshot", + "snapshot-list", + ] + if arg not in valid_commands: + typer.echo(f"[bold red]Invalid command: `show {arg}`[/bold red]", err=True) + exit(1) + + cm_ctx.set_channel_mode(channel, mode) + if arg == 'snapshot': + show_snapshot(True) + elif arg == 'snapshot-list': + show_snapshot_list(True) + else: + show_list(arg, True) + + +@app.command('cli-only-mode', help="Set whether to use ComfyUI-Manager in CLI-only mode.") +def cli_only_mode( + mode: str = typer.Argument( + ..., help="[enable|disable]" + )): + cli_mode_flag = os.path.join(os.path.dirname(__file__), '.enable-cli-only-mode') + if mode.lower() == 'enable': + with open(cli_mode_flag, 'w') as file: + pass + print(f"\nINFO: `cli-only-mode` is enabled\n") + elif mode.lower() == 'disable': + if os.path.exists(cli_mode_flag): + os.remove(cli_mode_flag) + print(f"\nINFO: `cli-only-mode` is disabled\n") + else: + print(f"\n[bold red]Invalid value for cli-only-mode: {mode}[/bold red]\n") + exit(1) + + +@app.command( + "deps-in-workflow", help="Generate dependencies file from workflow (.json/.png)" +) +def deps_in_workflow( + workflow: Annotated[ + str, typer.Option(show_default=False, help="Workflow file (.json/.png)") + ], + output: Annotated[ + str, typer.Option(show_default=False, help="Output file (.json)") + ], + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + cm_ctx.set_channel_mode(channel, mode) + + input_path = workflow + output_path = output + + if not os.path.exists(input_path): + print(f"[bold red]File not found: {input_path}[/bold red]") + exit(1) + + used_exts, unknown_nodes = asyncio.run(core.extract_nodes_from_workflow(input_path, mode=cm_ctx.mode, channel_url=cm_ctx.channel)) + + custom_nodes = {} + for x in used_exts: + custom_nodes[x] = {'state': core.simple_check_custom_node(x), + 'hash': '-' + } + + res = { + 'custom_nodes': custom_nodes, + 'unknown_nodes': list(unknown_nodes) + } + + with open(output_path, "w", encoding='utf-8') as output_file: + json.dump(res, output_file, indent=4) + + print(f"Workflow dependencies are being saved into {output_path}.") + + +@app.command("save-snapshot", help="Save a snapshot of the current ComfyUI environment. If output path isn't provided. Save to ComfyUI-Manager/snapshots path.") +def save_snapshot( + output: Annotated[ + str, + typer.Option( + show_default=False, help="Specify the output file path. (.json/.yaml)" + ), + ] = None, +): + path = core.save_snapshot_with_postfix('snapshot', output) + print(f"Current snapshot is saved as `{path}`") + + +@app.command("restore-snapshot", help="Restore snapshot from snapshot file") +def restore_snapshot( + snapshot_name: str, + pip_non_url: Optional[bool] = typer.Option( + default=None, + show_default=False, + is_flag=True, + help="Restore for pip packages registered on PyPI.", + ), + pip_non_local_url: Optional[bool] = typer.Option( + default=None, + show_default=False, + is_flag=True, + help="Restore for pip packages registered at web URLs.", + ), + pip_local_url: Optional[bool] = typer.Option( + default=None, + show_default=False, + is_flag=True, + help="Restore for pip packages specified by local paths.", + ), +): + extras = [] + if pip_non_url: + extras.append('--pip-non-url') + + if pip_non_local_url: + extras.append('--pip-non-local-url') + + if pip_local_url: + extras.append('--pip-local-url') + + print(f"PIPs restore mode: {extras}") + + if os.path.exists(snapshot_name): + snapshot_path = os.path.abspath(snapshot_name) + else: + snapshot_path = os.path.join(core.comfyui_manager_path, 'snapshots', snapshot_name) + if not os.path.exists(snapshot_path): + print(f"[bold red]ERROR: `{snapshot_path}` is not exists.[/bold red]") + exit(1) + + try: + cloned_repos = [] + checkout_repos = [] + skipped_repos = [] + enabled_repos = [] + disabled_repos = [] + is_failed = False + + def extract_infos(msg): + nonlocal is_failed + + for x in msg: + if x.startswith("CLONE: "): + cloned_repos.append(x[7:]) + elif x.startswith("CHECKOUT: "): + checkout_repos.append(x[10:]) + elif x.startswith("SKIPPED: "): + skipped_repos.append(x[9:]) + elif x.startswith("ENABLE: "): + enabled_repos.append(x[8:]) + elif x.startswith("DISABLE: "): + disabled_repos.append(x[9:]) + elif 'APPLY SNAPSHOT: False' in x: + is_failed = True + + print(f"Restore snapshot.") + cmd_str = [sys.executable, git_script_path, '--apply-snapshot', snapshot_path] + extras + output = subprocess.check_output(cmd_str, cwd=custom_nodes_path, text=True) + msg_lines = output.split('\n') + extract_infos(msg_lines) + + for url in cloned_repos: + cm_ctx.post_install(url) + + # print summary + for x in cloned_repos: + print(f"[ INSTALLED ] {x}") + for x in checkout_repos: + print(f"[ CHECKOUT ] {x}") + for x in enabled_repos: + print(f"[ ENABLED ] {x}") + for x in disabled_repos: + print(f"[ DISABLED ] {x}") + + if is_failed: + print(output) + print("[bold red]ERROR: Failed to restore snapshot.[/bold red]") + + except Exception: + print("[bold red]ERROR: Failed to restore snapshot.[/bold red]") + traceback.print_exc() + raise typer.Exit(code=1) + + +@app.command( + "restore-dependencies", help="Restore dependencies from whole installed custom nodes." +) +def restore_dependencies(): + node_paths = [os.path.join(custom_nodes_path, name) for name in os.listdir(custom_nodes_path) + if os.path.isdir(os.path.join(custom_nodes_path, name)) and not name.endswith('.disabled')] + + total = len(node_paths) + i = 1 + for x in node_paths: + print(f"----------------------------------------------------------------------------------------------------") + print(f"Restoring [{i}/{total}]: {x}") + cm_ctx.post_install(x) + i += 1 + + +@app.command( + "post-install", help="Install dependencies and execute installation script" +) +def post_install( + path: str = typer.Argument( + help="path to custom node", + )): + path = os.path.expanduser(path) + cm_ctx.post_install(path) + + +@app.command( + "install-deps", + help="Install dependencies from dependencies file(.json) or workflow(.png/.json)", +) +def install_deps( + deps: str = typer.Argument( + help="Dependency spec file (.json)", + ), + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + ), +): + cm_ctx.set_channel_mode(channel, mode) + auto_save_snapshot() + + if not os.path.exists(deps): + print(f"[bold red]File not found: {deps}[/bold red]") + exit(1) + else: + with open(deps, 'r', encoding="UTF-8", errors="ignore") as json_file: + try: + json_obj = json.load(json_file) + except: + print(f"[bold red]Invalid json file: {deps}[/bold red]") + exit(1) + + for k in json_obj['custom_nodes'].keys(): + state = core.simple_check_custom_node(k) + if state == 'installed': + continue + elif state == 'not-installed': + core.gitclone_install([k], instant_execution=True) + else: # disabled + core.gitclone_set_active([k], False) + + print("Dependency installation and activation complete.") + + +@app.command(help="Clear reserved startup action in ComfyUI-Manager") +def clear(): + cancel() + + +@app.command("export-custom-node-ids", help="Export custom node ids") +def export_custom_node_ids( + path: str, + channel: Annotated[ + str, + typer.Option( + show_default=False, + help="Specify the operation mode" + ), + ] = None, + mode: str = typer.Option( + None, + help="[remote|local|cache]" + )): + cm_ctx.set_channel_mode(channel, mode) + + with open(path, "w", encoding='utf-8') as output_file: + for x in cm_ctx.get_custom_node_map().keys(): + print(x, file=output_file) + + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(app()) + +print(f"") diff --git a/custom_nodes/ComfyUI-Manager/custom-node-list.json b/custom_nodes/ComfyUI-Manager/custom-node-list.json new file mode 100644 index 000000000..e81a89263 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/custom-node-list.json @@ -0,0 +1,11693 @@ +{ + "custom_nodes": [ + { + "author": "Dr.Lt.Data", + "title": "ComfyUI-Manager", + "id": "manager", + "reference": "https://github.com/ltdrdata/ComfyUI-Manager", + "files": [ + "https://github.com/ltdrdata/ComfyUI-Manager" + ], + "install_type": "git-clone", + "description": "ComfyUI-Manager itself is also a custom node." + }, + { + "author": "Dr.Lt.Data", + "title": "ComfyUI Impact Pack", + "id": "impact", + "reference": "https://github.com/ltdrdata/ComfyUI-Impact-Pack", + "files": [ + "https://github.com/ltdrdata/ComfyUI-Impact-Pack" + ], + "pip": ["ultralytics"], + "install_type": "git-clone", + "description": "This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler.", + "preemptions":["SAMLoader"] + }, + { + "author": "Dr.Lt.Data", + "title": "ComfyUI Inspire Pack", + "id": "inspire", + "reference": "https://github.com/ltdrdata/ComfyUI-Inspire-Pack", + "nodename_pattern": "Inspire$", + "files": [ + "https://github.com/ltdrdata/ComfyUI-Inspire-Pack" + ], + "install_type": "git-clone", + "description": "This extension provides various nodes to support Lora Block Weight and the Impact Pack. Provides many easily applicable regional features and applications for Variation Seed." + }, + { + "author": "comfyanonymous", + "title": "ComfyUI_experiments", + "id": "comfy-exp", + "reference": "https://github.com/comfyanonymous/ComfyUI_experiments", + "files": [ + "https://github.com/comfyanonymous/ComfyUI_experiments" + ], + "install_type": "git-clone", + "description": "Nodes: ModelSamplerTonemapNoiseTest, TonemapNoiseWithRescaleCFG, ReferenceOnlySimple, RescaleClassifierFreeGuidanceTest, ModelMergeBlockNumber, ModelMergeSDXL, ModelMergeSDXLTransformers, ModelMergeSDXLDetailedTransformers." + }, + { + "author": "comfyanonymous", + "title": "TensorRT Node for ComfyUI", + "id": "tensorrt", + "reference": "https://github.com/comfyanonymous/ComfyUI_TensorRT", + "files": [ + "https://github.com/comfyanonymous/ComfyUI_TensorRT" + ], + "install_type": "git-clone", + "description": "This node enables the best performance on NVIDIA RTX™ Graphics Cards (GPUs) for Stable Diffusion by leveraging NVIDIA TensorRT." + }, + { + "author": "Stability-AI", + "title": "Stability API nodes for ComfyUI", + "id": "sai-api", + "reference": "https://github.com/Stability-AI/ComfyUI-SAI_API", + "files": [ + "https://github.com/Stability-AI/ComfyUI-SAI_API" + ], + "install_type": "git-clone", + "description": "Nodes:Stability SD3, Stability Outpainting, Stability Search and Replace, Stability Image Core, Stability Inpainting, Stability Remove Background, Stability Creative Upscale.\nAdd API key to environment variable 'SAI_API_KEY'\nAlternatively you can write your API key to file 'sai_platform_key.txt'\nYou can also use and/or override the above by entering your API key in the 'api_key_override' field of each node." + }, + { + "author": "Stability-AI", + "title": "stability-ComfyUI-nodes", + "id": "sai-nodes", + "reference": "https://github.com/Stability-AI/stability-ComfyUI-nodes", + "files": [ + "https://github.com/Stability-AI/stability-ComfyUI-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: ColorBlend, ControlLoraSave, GetImageSize. NOTE: Control-LoRA recolor example uses these nodes." + }, + { + "author": "Fannovel16", + "title": "ComfyUI's ControlNet Auxiliary Preprocessors", + "id": "cnet-aux", + "reference": "https://github.com/Fannovel16/comfyui_controlnet_aux", + "files": [ + "https://github.com/Fannovel16/comfyui_controlnet_aux" + ], + "preemptions":[ + "AIO_Preprocessor", + "AnimalPosePreprocessor", + "AnimeFace_SemSegPreprocessor", + "AnimeLineArtPreprocessor", + "BAE-NormalMapPreprocessor", + "BinaryPreprocessor", + "CannyEdgePreprocessor", + "ColorPreprocessor", + "DSINE-NormalMapPreprocessor", + "DWPreprocessor", + "DensePosePreprocessor", + "DepthAnythingPreprocessor", + "DiffusionEdge_Preprocessor", + "FacialPartColoringFromPoseKps", + "FakeScribblePreprocessor", + "HEDPreprocessor", + "HintImageEnchance", + "ImageGenResolutionFromImage", + "ImageGenResolutionFromLatent", + "ImageIntensityDetector", + "ImageLuminanceDetector", + "InpaintPreprocessor", + "LeReS-DepthMapPreprocessor", + "LineArtPreprocessor", + "LineartStandardPreprocessor", + "M-LSDPreprocessor", + "Manga2Anime_LineArt_Preprocessor", + "MaskOptFlow", + "MediaPipe-FaceMeshPreprocessor", + "MeshGraphormer-DepthMapPreprocessor", + "MiDaS-DepthMapPreprocessor", + "MiDaS-NormalMapPreprocessor", + "OneFormer-ADE20K-SemSegPreprocessor", + "OneFormer-COCO-SemSegPreprocessor", + "OpenposePreprocessor", + "PiDiNetPreprocessor", + "PixelPerfectResolution", + "SAMPreprocessor", + "SavePoseKpsAsJsonFile", + "ScribblePreprocessor", + "Scribble_XDoG_Preprocessor", + "SemSegPreprocessor", + "ShufflePreprocessor", + "TEEDPreprocessor", + "TilePreprocessor", + "UniFormer-SemSegPreprocessor", + "Unimatch_OptFlowPreprocessor", + "Zoe-DepthMapPreprocessor", + "Zoe_DepthAnythingPreprocessor"], + "install_type": "git-clone", + "description": "This is a rework of comfyui_controlnet_preprocessors based on ControlNet auxiliary models by 🤗. I think the old repo isn't good enough to maintain. All old workflow will still be work with this repo but the version option won't do anything. Almost all v1 preprocessors are replaced by v1.1 except those doesn't appear in v1.1. [w/NOTE: Please refrain from using the controlnet preprocessor alongside this installation, as it may lead to conflicts and prevent proper recognition.]" + }, + { + "author": "Fannovel16", + "title": "ComfyUI Frame Interpolation", + "id": "frame-interpolation", + "reference": "https://github.com/Fannovel16/ComfyUI-Frame-Interpolation", + "files": [ + "https://github.com/Fannovel16/ComfyUI-Frame-Interpolation" + ], + "install_type": "git-clone", + "description": "Nodes: KSampler Gradually Adding More Denoise (efficient)" + }, + { + "author": "Fannovel16", + "title": "ComfyUI Loopchain", + "id": "loopchain", + "reference": "https://github.com/Fannovel16/ComfyUI-Loopchain", + "files": [ + "https://github.com/Fannovel16/ComfyUI-Loopchain" + ], + "install_type": "git-clone", + "description": "A collection of nodes which can be useful for animation in ComfyUI. The main focus of this extension is implementing a mechanism called loopchain. A loopchain in this case is the chain of nodes only executed repeatly in the workflow. If a node chain contains a loop node from this extension, it will become a loop chain." + }, + { + "author": "Fannovel16", + "title": "ComfyUI MotionDiff", + "id": "motiondiff", + "reference": "https://github.com/Fannovel16/ComfyUI-MotionDiff", + "files": [ + "https://github.com/Fannovel16/ComfyUI-MotionDiff" + ], + "install_type": "git-clone", + "description": "Implementation of MDM, MotionDiffuse and ReMoDiffuse into ComfyUI." + }, + { + "author": "Fannovel16", + "title": "ComfyUI-Video-Matting", + "id": "video-matting", + "reference": "https://github.com/Fannovel16/ComfyUI-Video-Matting", + "files": [ + "https://github.com/Fannovel16/ComfyUI-Video-Matting" + ], + "install_type": "git-clone", + "description": "A minimalistic implementation of [a/Robust Video Matting (RVM)](https://github.com/PeterL1n/RobustVideoMatting/) in ComfyUI" + }, + { + "author": "Fannovel16", + "title": "ComfyUI-MagickWand", + "id": "magicwand", + "reference": "https://github.com/Fannovel16/ComfyUI-MagickWand", + "files": [ + "https://github.com/Fannovel16/ComfyUI-MagickWand" + ], + "install_type": "git-clone", + "description": "Proper implementation of ImageMagick - the famous software suite for editing and manipulating digital images to ComfyUI using [a/wandpy](https://github.com/emcconville/wand).\nNOTE: You need to install ImageMagick, manually." + }, + { + "author": "time-river", + "title": "CLIPSeg", + "id": "clipseg", + "reference": "https://github.com/time-river/ComfyUI-CLIPSeg", + "files": [ + "https://github.com/time-river/ComfyUI-CLIPSeg/raw/main/custom_nodes/clipseg.py" + ], + "install_type": "copy", + "description": "The CLIPSeg node generates a binary mask for a given input image and text prompt.\nNOTE:This custom node is a forked custom node with hotfixes applied from the [a/original repository](https://github.com/biegert/ComfyUI-CLIPSeg), which is no longer maintained." + }, + { + "author": "BlenderNeko", + "title": "ComfyUI Cutoff", + "id": "cutoff", + "reference": "https://github.com/BlenderNeko/ComfyUI_Cutoff", + "files": [ + "https://github.com/BlenderNeko/ComfyUI_Cutoff" + ], + "install_type": "git-clone", + "description": "These custom nodes provides features that allow for better control over the effects of the text prompt." + }, + { + "author": "BlenderNeko", + "title": "Advanced CLIP Text Encode", + "id": "adv-encode", + "reference": "https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb", + "files": [ + "https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb" + ], + "install_type": "git-clone", + "description": "Advanced CLIP Text Encode (if you need A1111 like prompt. you need this. But Cutoff node includes this feature, already.)" + }, + { + "author": "BlenderNeko", + "title": "ComfyUI Noise", + "id": "comfy-noise", + "reference": "https://github.com/BlenderNeko/ComfyUI_Noise", + "files": [ + "https://github.com/BlenderNeko/ComfyUI_Noise" + ], + "install_type": "git-clone", + "description": "This extension contains 6 nodes for ComfyUI that allows for more control and flexibility over the noise." + }, + { + "author": "BlenderNeko", + "title": "Tiled sampling for ComfyUI", + "id": "tiled-sampling", + "reference": "https://github.com/BlenderNeko/ComfyUI_TiledKSampler", + "files": [ + "https://github.com/BlenderNeko/ComfyUI_TiledKSampler" + ], + "install_type": "git-clone", + "description": "This extension contains a tiled sampler for ComfyUI. It allows for denoising larger images by splitting it up into smaller tiles and denoising these. It tries to minimize any seams for showing up in the end result by gradually denoising all tiles one step at the time and randomizing tile positions for every step." + }, + { + "author": "BlenderNeko", + "title": "SeeCoder [WIP]", + "id": "seecoder", + "reference": "https://github.com/BlenderNeko/ComfyUI_SeeCoder", + "files": [ + "https://github.com/BlenderNeko/ComfyUI_SeeCoder" + ], + "install_type": "git-clone", + "description": "It provides the capability to generate CLIP from an image input, unlike unCLIP, which works in all models. (To use this extension, you need to download the required model file from **Install Models**)" + }, + { + "author": "jags111", + "title": "Efficiency Nodes for ComfyUI Version 2.0+", + "id": "eff-nodes", + "reference": "https://github.com/jags111/efficiency-nodes-comfyui", + "files": [ + "https://github.com/jags111/efficiency-nodes-comfyui" + ], + "install_type": "git-clone", + "description": "A collection of ComfyUI custom nodes to help streamline workflows and reduce total node count.[w/NOTE: This node is originally created by LucianoCirino, but the [a/original repository](https://github.com/LucianoCirino/efficiency-nodes-comfyui) is no longer maintained and has been forked by a new maintainer. To use the forked version, you should uninstall the original version and **REINSTALL** this one.]" + }, + { + "author": "jags111", + "title": "Jags_VectorMagic", + "id": "vectormagic", + "reference": "https://github.com/jags111/ComfyUI_Jags_VectorMagic", + "files": [ + "https://github.com/jags111/ComfyUI_Jags_VectorMagic" + ], + "install_type": "git-clone", + "description": "a collection of nodes to explore Vector and image manipulation" + }, + { + "author": "jags111", + "title": "Jags_Audiotools", + "id": "audiotools", + "reference": "https://github.com/jags111/ComfyUI_Jags_Audiotools", + "files": [ + "https://github.com/jags111/ComfyUI_Jags_Audiotools" + ], + "install_type": "git-clone", + "description": "This extension offers various audio generation tools" + }, + { + "author": "Derfuu", + "title": "Derfuu_ComfyUI_ModdedNodes", + "id": "derfuu", + "reference": "https://github.com/Derfuu/Derfuu_ComfyUI_ModdedNodes", + "nodename_pattern": "^DF_", + "files": [ + "https://github.com/Derfuu/Derfuu_ComfyUI_ModdedNodes" + ], + "install_type": "git-clone", + "description": "Automate calculation depending on image sizes or something you want." + }, + { + "author": "paulo-coronado", + "title": "comfy_clip_blip_node", + "id": "blip", + "reference": "https://github.com/paulo-coronado/comfy_clip_blip_node", + "files": [ + "https://github.com/paulo-coronado/comfy_clip_blip_node" + ], + "install_type": "git-clone", + "apt_dependency": [ + "rustc", + "cargo" + ], + "description": "CLIPTextEncodeBLIP: This custom node provides a CLIP Encoder that is capable of receiving images as input." + }, + { + "author": "WASasquatch", + "title": "WAS Node Suite", + "id": "was", + "reference": "https://github.com/WASasquatch/was-node-suite-comfyui", + "pip": ["numba"], + "files": [ + "https://github.com/WASasquatch/was-node-suite-comfyui" + ], + "install_type": "git-clone", + "description": "A node suite for ComfyUI with many new nodes, such as image processing, text processing, and more." + }, + { + "author": "WASasquatch", + "title": "ComfyUI Preset Merger", + "id": "preset-merger", + "reference": "https://github.com/WASasquatch/ComfyUI_Preset_Merger", + "files": [ + "https://github.com/WASasquatch/ComfyUI_Preset_Merger" + ], + "install_type": "git-clone", + "description": "Nodes: ModelMergeByPreset. Merge checkpoint models by preset" + }, + { + "author": "WASasquatch", + "title": "PPF_Noise_ComfyUI", + "id": "ppf", + "reference": "https://github.com/WASasquatch/PPF_Noise_ComfyUI", + "files": [ + "https://github.com/WASasquatch/PPF_Noise_ComfyUI" + ], + "install_type": "git-clone", + "description": "Nodes: WAS_PFN_Latent. Perlin Power Fractal Noisey Latents" + }, + { + "author": "WASasquatch", + "title": "Power Noise Suite for ComfyUI", + "id": "power-noise", + "reference": "https://github.com/WASasquatch/PowerNoiseSuite", + "files": [ + "https://github.com/WASasquatch/PowerNoiseSuite" + ], + "install_type": "git-clone", + "description": "Power Noise Suite contains nodes centered around latent noise input, and diffusion, as well as latent adjustments." + }, + { + "author": "WASasquatch", + "title": "FreeU_Advanced", + "id": "freeu-adv", + "reference": "https://github.com/WASasquatch/FreeU_Advanced", + "files": [ + "https://github.com/WASasquatch/FreeU_Advanced" + ], + "install_type": "git-clone", + "description": "This custom node provides advanced settings for FreeU." + }, + { + "author": "WASasquatch", + "title": "ASTERR", + "id": "asterr", + "reference": "https://github.com/WASasquatch/ASTERR", + "files": [ + "https://github.com/WASasquatch/ASTERR" + ], + "install_type": "git-clone", + "description": "Abstract Syntax Trees Evaluated Restricted Run (ASTERR) is a Python Script executor for ComfyUI. [w/Warning:ASTERR runs Python Code from a Web Interface! It is highly recommended to run this in a closed-off environment, as it could have potential security risks.]" + }, + { + "author": "WASasquatch", + "title": "WAS_Extras", + "id": "was-extras", + "reference": "https://github.com/WASasquatch/WAS_Extras", + "files": [ + "https://github.com/WASasquatch/WAS_Extras" + ], + "install_type": "git-clone", + "description": "Nodes:Conditioning (Blend), Inpainting VAE Encode (WAS), VividSharpen. Experimental nodes, or other random extra helper nodes." + }, + { + "author": "SaltAI", + "title": "SaltAI-Open-Resources", + "id": "saltai-open-resource", + "reference": "https://github.com/get-salt-AI/SaltAI", + "pip": ["numba"], + "files": [ + "https://github.com/get-salt-AI/SaltAI" + ], + "install_type": "git-clone", + "description": "This repository is a collection of open-source nodes and workflows for ComfyUI, a dev tool that allows users to create node-based workflows often powered by various AI models to do pretty much anything.\nOur mission is to seamlessly connect people and organizations with the world’s foremost AI innovations, anywhere, anytime. Our vision is to foster a flourishing AI ecosystem where the world’s best developers can build and share their work, thereby redefining how software is made, pushing innovation forward, and ensuring as many people as possible can benefit from the positive promise of AI technologies.\nWe believe that ComfyUI is a powerful tool that can help us achieve our mission and vision, by enabling anyone to explore the possibilities and limitations of AI models in a visual and interactive way, without coding if desired.\nWe hope that by sharing our nodes and workflows, we can inspire and empower more people to create amazing AI-powered content with ComfyUI." + }, + { + "author": "SaltAI", + "title": "SaltAI_LlamaIndex", + "id": "saltai-llamaindex", + "reference": "https://github.com/get-salt-AI/SaltAI_LlamaIndex", + "files": [ + "https://github.com/get-salt-AI/SaltAI_LlamaIndex" + ], + "install_type": "git-clone", + "description": "An implementation of the RAG LlamaIndex with Agents from AutoGen" + }, + { + "author": "SaltAI", + "title": "SaltAI Language Toolkit", + "id": "saltai-langtool", + "reference": "https://github.com/get-salt-AI/SaltAI_Language_Toolkit", + "files": [ + "https://github.com/get-salt-AI/SaltAI_Language_Toolkit" + ], + "install_type": "git-clone", + "description": "The project integrates the Retrieval Augmented Generation (RAG) tool [a/Llama-Index](https://www.llamaindex.ai/), [a/Microsoft's AutoGen](https://microsoft.github.io/autogen/), and [a/LlaVA-Next](https://github.com/LLaVA-VL/LLaVA-NeXT) with ComfyUI's adaptable node interface, enhancing the functionality and user experience of the platform." + }, + { + "author": "omar92", + "title": "Quality of life Suit:V2", + "id": "qol", + "reference": "https://github.com/omar92/ComfyUI-QualityOfLifeSuit_Omar92", + "files": [ + "https://github.com/omar92/ComfyUI-QualityOfLifeSuit_Omar92" + ], + "install_type": "git-clone", + "description": "openAI suite, String suite, Latent Tools, Image Tools: These custom nodes provide expanded functionality for image and string processing, latent processing, as well as the ability to interface with models such as ChatGPT/DallE-2.\nNOTE: Currently, this extension does not support the new OpenAI API, leading to compatibility issues." + }, + { + "author": "lilly1987", + "title": "simple wildcard for ComfyUI", + "id": "simle-wildcard", + "reference": "https://github.com/lilly1987/ComfyUI_node_Lilly", + "files": [ + "https://github.com/lilly1987/ComfyUI_node_Lilly" + ], + "install_type": "git-clone", + "description": "These custom nodes provides a feature to insert arbitrary inputs through wildcards in the prompt. Additionally, this tool provides features that help simplify workflows, such as VAELoaderDecoder and SimplerSample." + }, + { + "author": "sylym", + "title": "Vid2vid", + "id": "vid2vid", + "reference": "https://github.com/sylym/comfy_vid2vid", + "files": [ + "https://github.com/sylym/comfy_vid2vid" + ], + "install_type": "git-clone", + "description": "A node suite for ComfyUI that allows you to load image sequence and generate new image sequence with different styles or content." + }, + { + "author": "EllangoK", + "title": "ComfyUI-post-processing-nodes", + "id": "post-processing", + "reference": "https://github.com/EllangoK/ComfyUI-post-processing-nodes", + "files": [ + "https://github.com/EllangoK/ComfyUI-post-processing-nodes" + ], + "install_type": "git-clone", + "description": "A collection of post processing nodes for ComfyUI, simply download this repo and drag." + }, + { + "author": "LEv145", + "title": "ImagesGrid", + "id": "imagesgrid", + "reference": "https://github.com/LEv145/images-grid-comfy-plugin", + "files": [ + "https://github.com/LEv145/images-grid-comfy-plugin" + ], + "install_type": "git-clone", + "description": "This tool provides a viewer node that allows for checking multiple outputs in a grid, similar to the X/Y Plot extension." + }, + { + "author": "diontimmer", + "title": "ComfyUI-Vextra-Nodes", + "id": "vextra", + "reference": "https://github.com/diontimmer/ComfyUI-Vextra-Nodes", + "files": [ + "https://github.com/diontimmer/ComfyUI-Vextra-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Pixel Sort, Swap Color Mode, Solid Color, Glitch This, Add Text To Image, Play Sound, Prettify Prompt, Generate Noise, Flatten Colors" + }, + { + "author": "CYBERLOOM-INC", + "title": "ComfyUI-nodes-hnmr", + "id": "hnmr", + "reference": "https://github.com/CYBERLOOM-INC/ComfyUI-nodes-hnmr", + "files": [ + "https://github.com/CYBERLOOM-INC/ComfyUI-nodes-hnmr" + ], + "install_type": "git-clone", + "description": "Provide various custom nodes for Latent, Sampling, Model, Loader, Image, Text. This is the fixed version of the original [a/ComfyUI-nodes-hnmr](https://github.com/hnmr293/ComfyUI-nodes-hnmr) by hnmr293." + }, + { + "author": "BadCafeCode", + "title": "Masquerade Nodes", + "id": "masquerade", + "reference": "https://github.com/BadCafeCode/masquerade-nodes-comfyui", + "files": [ + "https://github.com/BadCafeCode/masquerade-nodes-comfyui" + ], + "install_type": "git-clone", + "description": "This is a low-dependency node pack primarily dealing with masks. The author recommends using Impact-Pack instead (unless you specifically have trouble installing dependencies)." + }, + { + "author": "guoyk93", + "title": "y.k.'s ComfyUI node suite", + "id": "yks", + "reference": "https://github.com/guoyk93/yk-node-suite-comfyui", + "files": [ + "https://github.com/guoyk93/yk-node-suite-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes: YKImagePadForOutpaint, YKMaskToImage" + }, + { + "author": "Jcd1230", + "title": "Rembg Background Removal Node for ComfyUI", + "id": "rembg", + "reference": "https://github.com/Jcd1230/rembg-comfyui-node", + "files": [ + "https://github.com/Jcd1230/rembg-comfyui-node" + ], + "install_type": "git-clone", + "description": "Nodes: Image Remove Background (rembg)" + }, + { + "author": "YinBailiang", + "title": "MergeBlockWeighted_fo_ComfyUI", + "id": "mbw", + "reference": "https://github.com/YinBailiang/MergeBlockWeighted_fo_ComfyUI", + "files": [ + "https://github.com/YinBailiang/MergeBlockWeighted_fo_ComfyUI" + ], + "install_type": "git-clone", + "description": "Nodes: MergeBlockWeighted" + }, + { + "author": "trojblue", + "title": "trNodes", + "id": "trnodes", + "reference": "https://github.com/trojblue/trNodes", + "files": [ + "https://github.com/trojblue/trNodes" + ], + "install_type": "git-clone", + "description": "Nodes: image_layering, color_correction, model_router" + }, + { + "author": "szhublox", + "title": "Auto-MBW", + "id": "auto-mbw", + "reference": "https://github.com/szhublox/ambw_comfyui", + "files": [ + "https://github.com/szhublox/ambw_comfyui" + ], + "install_type": "git-clone", + "description": "Auto-MBW for ComfyUI loosely based on sdweb-auto-MBW. Nodes: auto merge block weighted" + }, + { + "author": "city96", + "title": "ComfyUI_NetDist", + "id": "netdist", + "reference": "https://github.com/city96/ComfyUI_NetDist", + "files": [ + "https://github.com/city96/ComfyUI_NetDist" + ], + "install_type": "git-clone", + "description": "Run ComfyUI workflows on multiple local GPUs/networked machines. Nodes: Remote images, Local Remote control" + }, + { + "author": "city96", + "title": "Latent-Interposer", + "id": "latent-interposer", + "reference": "https://github.com/city96/SD-Latent-Interposer", + "files": [ + "https://github.com/city96/SD-Latent-Interposer" + ], + "install_type": "git-clone", + "description": "Custom node to convert the lantents between SDXL and SD v1.5 directly without the VAE decoding/encoding step." + }, + { + "author": "city96", + "title": "SD-Advanced-Noise", + "id": "adv-noise", + "reference": "https://github.com/city96/SD-Advanced-Noise", + "files": [ + "https://github.com/city96/SD-Advanced-Noise" + ], + "install_type": "git-clone", + "description": "Nodes: LatentGaussianNoise, MathEncode. An experimental custom node that generates latent noise directly by utilizing the linear characteristics of the latent space." + }, + { + "author": "city96", + "title": "SD-Latent-Upscaler", + "id": "latent-upscaler", + "reference": "https://github.com/city96/SD-Latent-Upscaler", + "files": [ + "https://github.com/city96/SD-Latent-Upscaler" + ], + "pip": ["huggingface-hub"], + "install_type": "git-clone", + "description": "Upscaling stable diffusion latents using a small neural network." + }, + { + "author": "city96", + "title": "ComfyUI_DiT [WIP]", + "id": "dit", + "reference": "https://github.com/city96/ComfyUI_DiT", + "files": [ + "https://github.com/city96/ComfyUI_DiT" + ], + "pip": ["huggingface-hub"], + "install_type": "git-clone", + "description": "Testbed for [a/DiT(Scalable Diffusion Models with Transformers)](https://github.com/facebookresearch/DiT). [w/None of this code is stable, expect breaking changes if for some reason you want to use this.]" + }, + { + "author": "city96", + "title": "ComfyUI_ColorMod", + "id": "colormod", + "reference": "https://github.com/city96/ComfyUI_ColorMod", + "files": [ + "https://github.com/city96/ComfyUI_ColorMod" + ], + "install_type": "git-clone", + "description": "This extension currently has two sets of nodes - one set for editing the contrast/color of images and another set for saving images as 16 bit PNG files." + }, + { + "author": "city96", + "title": "Extra Models for ComfyUI", + "id": "extramodels", + "reference": "https://github.com/city96/ComfyUI_ExtraModels", + "files": [ + "https://github.com/city96/ComfyUI_ExtraModels" + ], + "install_type": "git-clone", + "description": "This extension aims to add support for various random image diffusion models to ComfyUI." + }, + { + "author": "SLAPaper", + "title": "ComfyUI-Image-Selector", + "id": "image-selector", + "reference": "https://github.com/SLAPaper/ComfyUI-Image-Selector", + "files": [ + "https://github.com/SLAPaper/ComfyUI-Image-Selector" + ], + "install_type": "git-clone", + "description": "A custom node for ComfyUI, which can select one or some of images from a batch." + }, + { + "author": "SLAPaper", + "title": "ComfyUI DPM++ 2M Alt Sampler", + "id": "dpmpp2m-alt", + "reference": "https://github.com/SLAPaper/ComfyUI-dpmpp_2m_alt-Sampler", + "files": [ + "https://github.com/SLAPaper/ComfyUI-dpmpp_2m_alt-Sampler" + ], + "install_type": "git-clone", + "description": "the sampler introduced by [a/hallatore](https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/8457)\ncode extracted from [a/smZNodes](https://github.com/shiimizu/ComfyUI_smZNodes)" + }, + { + "author": "flyingshutter", + "title": "As_ComfyUI_CustomNodes", + "reference": "https://github.com/flyingshutter/As_ComfyUI_CustomNodes", + "files": [ + "https://github.com/flyingshutter/As_ComfyUI_CustomNodes" + ], + "install_type": "git-clone", + "description": "Manipulation nodes for Image, Latent" + }, + { + "author": "Zuellni", + "title": "Zuellni/ComfyUI-Custom-Nodes", + "reference": "https://github.com/Zuellni/ComfyUI-Custom-Nodes", + "files": [ + "https://github.com/Zuellni/ComfyUI-Custom-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes: DeepFloyd, Filter, Select, Save, Decode, Encode, Repeat, Noise, Noise" + }, + { + "author": "Zuellni", + "title": "ComfyUI-ExLlama", + "id": "exllama", + "reference": "https://github.com/Zuellni/ComfyUI-ExLlama", + "files": [ + "https://github.com/Zuellni/ComfyUI-ExLlama" + ], + "pip": ["sentencepiece", "https://github.com/jllllll/exllama/releases/download/0.0.17/exllama-0.0.17+cu118-cp310-cp310-win_amd64.whl"], + "install_type": "git-clone", + "description": "Nodes: ExLlama Loader, ExLlama Generator.\nUsed to load 4-bit GPTQ Llama/2 models. You can find a lot of them over at [a/https://huggingface.co/TheBloke](https://huggingface.co/TheBloke)[w/NOTE: You need to manually install a pip package that suits your system. For example. If your system is 'Python3.10 + Windows + CUDA 11.8' then you need to install 'exllama-0.0.17+cu118-cp310-cp310-win_amd64.whl'. Available package files are [a/here](https://github.com/jllllll/exllama/releases)]" + }, + { + "author": "Zuellni", + "title": "ComfyUI ExLlamaV2 Nodes", + "id": "exllamav2", + "reference": "https://github.com/Zuellni/ComfyUI-ExLlama-Nodes", + "files": [ + "https://github.com/Zuellni/ComfyUI-ExLlama-Nodes" + ], + "install_type": "git-clone", + "description": "A simple local text generator for ComfyUI utilizing [a/ExLlamaV2](https://github.com/turboderp/exllamav2).\n[w/NOTE:Manual package installation is required.]" + }, + { + "author": "Zuellni", + "title": "ComfyUI PickScore Nodes", + "id": "pickscore", + "reference": "https://github.com/Zuellni/ComfyUI-PickScore-Nodes", + "files": [ + "https://github.com/Zuellni/ComfyUI-PickScore-Nodes" + ], + "install_type": "git-clone", + "description": "Image scoring nodes for ComfyUI using PickScore with a batch of images to predict which ones fit a given prompt the best." + }, + { + "author": "AlekPet", + "title": "AlekPet/ComfyUI_Custom_Nodes_AlekPet", + "id": "alekpet", + "reference": "https://github.com/AlekPet/ComfyUI_Custom_Nodes_AlekPet", + "files": [ + "https://github.com/AlekPet/ComfyUI_Custom_Nodes_AlekPet" + ], + "install_type": "git-clone", + "description": "Nodes: PoseNode, PainterNode, TranslateTextNode, TranslateCLIPTextEncodeNode, DeepTranslatorTextNode, DeepTranslatorCLIPTextEncodeNode, ArgosTranslateTextNode, ArgosTranslateCLIPTextEncodeNode, PreviewTextNode.\n\nNOTE: Due to the dynamic nature of node name definitions, ComfyUI-Manager cannot recognize the node list from this extension. The Missing nodes and Badge features are not available for this extension." + }, + { + "author": "pythongosssss", + "title": "ComfyUI WD 1.4 Tagger", + "id": "wd14", + "reference": "https://github.com/pythongosssss/ComfyUI-WD14-Tagger", + "files": [ + "https://github.com/pythongosssss/ComfyUI-WD14-Tagger" + ], + "install_type": "git-clone", + "description": "A ComfyUI extension allowing the interrogation of booru tags from images." + }, + { + "author": "pythongosssss", + "title": "pythongosssss/ComfyUI-Custom-Scripts", + "id": "pygos-script", + "reference": "https://github.com/pythongosssss/ComfyUI-Custom-Scripts", + "files": [ + "https://github.com/pythongosssss/ComfyUI-Custom-Scripts" + ], + "install_type": "git-clone", + "description": "This extension provides: Auto Arrange Graph, Workflow SVG, Favicon Status, Image Feed, Latent Upscale By, Lock Nodes & Groups, Lora Subfolders, Preset Text, Show Text, Touch Support, Link Render Mode, Locking, Node Finder, Quick Nodes, Show Image On Menu, Show Text, Workflow Managements, Custom Widget Default Values" + }, + { + "author": "strimmlarn", + "title": "ComfyUI_Strimmlarns_aesthetic_score", + "id": "aesthetic-score", + "reference": "https://github.com/strimmlarn/ComfyUI_Strimmlarns_aesthetic_score", + "js_path": "strimmlarn", + "files": [ + "https://github.com/strimmlarn/ComfyUI_Strimmlarns_aesthetic_score" + ], + "install_type": "git-clone", + "description": "Nodes: CalculateAestheticScore, LoadAesteticModel, AesthetlcScoreSorter, ScoreToNumber" + }, + { + "author": "TinyTerra", + "title": "ComfyUI_tinyterraNodes", + "id": "ttn", + "reference": "https://github.com/TinyTerra/ComfyUI_tinyterraNodes", + "files": [ + "https://github.com/TinyTerra/ComfyUI_tinyterraNodes" + ], + "install_type": "git-clone", + "nodename_pattern": "^ttN ", + "description": "This extension offers various pipe nodes, extensive XYZ plotting, fullscreen image viewer based on node history, dynamic widgets, interface customization, and more." + }, + { + "author": "Jordach", + "title": "comfy-plasma", + "id": "plasma", + "reference": "https://github.com/Jordach/comfy-plasma", + "files": [ + "https://github.com/Jordach/comfy-plasma" + ], + "install_type": "git-clone", + "description": "Nodes: Plasma Noise, Random Noise, Greyscale Noise, Pink Noise, Brown Noise, Plasma KSampler" + }, + { + "author": "bvhari", + "title": "ImageProcessing", + "id": "imageprocessing", + "reference": "https://github.com/bvhari/ComfyUI_ImageProcessing", + "files": [ + "https://github.com/bvhari/ComfyUI_ImageProcessing" + ], + "install_type": "git-clone", + "description": "ComfyUI custom nodes to apply various image processing techniques." + }, + { + "author": "bvhari", + "title": "ComfyUI_PerpWeight", + "id": "perpweight", + "reference": "https://github.com/bvhari/ComfyUI_PerpWeight", + "files": [ + "https://github.com/bvhari/ComfyUI_PerpWeight" + ], + "install_type": "git-clone", + "description": "A novel weighting scheme for token vectors from CLIP. Allows a wider range of values for the weight. Inspired by Perp-Neg." + }, + { + "author": "bvhari", + "title": "ComfyUI_SUNoise", + "id": "sunoise", + "reference": "https://github.com/bvhari/ComfyUI_SUNoise", + "files": [ + "https://github.com/bvhari/ComfyUI_SUNoise" + ], + "install_type": "git-clone", + "description": "Scaled Uniform Noise for Ancestral and Stochastic samplers" + }, + { + "author": "ssitu", + "title": "UltimateSDUpscale", + "id": "usdu", + "reference": "https://github.com/ssitu/ComfyUI_UltimateSDUpscale", + "files": [ + "https://github.com/ssitu/ComfyUI_UltimateSDUpscale" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes for the Ultimate Stable Diffusion Upscale script by Coyote-A." + }, + { + "author": "ssitu", + "title": "Restart Sampling", + "id": "restart-sampling", + "reference": "https://github.com/ssitu/ComfyUI_restart_sampling", + "files": [ + "https://github.com/ssitu/ComfyUI_restart_sampling" + ], + "install_type": "git-clone", + "description": "Unofficial ComfyUI nodes for restart sampling based on the paper 'Restart Sampling for Improving Generative Processes' ([a/paper](https://arxiv.org/abs/2306.14878), [a/repo](https://github.com/Newbeeer/diffusion_restart_sampling))" + }, + { + "author": "ssitu", + "title": "ComfyUI roop", + "id": "roop", + "reference": "https://github.com/ssitu/ComfyUI_roop", + "files": [ + "https://github.com/ssitu/ComfyUI_roop" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes for the roop A1111 webui script." + }, + { + "author": "ssitu", + "title": "ComfyUI fabric", + "id": "fabric", + "reference": "https://github.com/ssitu/ComfyUI_fabric", + "files": [ + "https://github.com/ssitu/ComfyUI_fabric" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes based on the paper [a/FABRIC: Personalizing Diffusion Models with Iterative Feedback](https://arxiv.org/abs/2307.10159) (Feedback via Attention-Based Reference Image Conditioning)" + }, + { + "author": "space-nuko", + "title": "Disco Diffusion", + "id": "disco", + "reference": "https://github.com/space-nuko/ComfyUI-Disco-Diffusion", + "files": [ + "https://github.com/space-nuko/ComfyUI-Disco-Diffusion" + ], + "install_type": "git-clone", + "description": "Modularized version of Disco Diffusion for use with ComfyUI." + }, + { + "author": "space-nuko", + "title": "OpenPose Editor", + "id": "openpose-editor", + "reference": "https://github.com/space-nuko/ComfyUI-OpenPose-Editor", + "files": [ + "https://github.com/space-nuko/ComfyUI-OpenPose-Editor" + ], + "install_type": "git-clone", + "description": "A port of the openpose-editor extension for stable-diffusion-webui. NOTE: Requires [a/this ComfyUI patch](https://github.com/comfyanonymous/ComfyUI/pull/711) to work correctly" + }, + { + "author": "space-nuko", + "title": "nui suite", + "id": "nui", + "reference": "https://github.com/space-nuko/nui-suite", + "files": [ + "https://github.com/space-nuko/nui-suite" + ], + "install_type": "git-clone", + "description": "NODES: Dynamic Prompts Text Encode, Feeling Lucky Text Encode, Output String" + }, + { + "author": "Nourepide", + "title": "Allor Plugin", + "id": "allor", + "reference": "https://github.com/Nourepide/ComfyUI-Allor", + "files": [ + "https://github.com/Nourepide/ComfyUI-Allor" + ], + "install_type": "git-clone", + "description": "Allor is a plugin for ComfyUI with an emphasis on transparency and performance." + }, + { + "author": "melMass", + "title": "MTB Nodes", + "id": "mtb", + "reference": "https://github.com/melMass/comfy_mtb", + "files": [ + "https://github.com/melMass/comfy_mtb" + ], + "nodename_pattern": "\\(mtb\\)$", + "install_type": "git-clone", + "description": "NODES: Face Swap, Film Interpolation, Latent Lerp, Int To Number, Bounding Box, Crop, Uncrop, ImageBlur, Denoise, ImageCompare, RGV to HSV, HSV to RGB, Color Correct, Modulo, Deglaze Image, Smart Step, ..." + }, + { + "author": "xXAdonesXx", + "title": "NodeGPT", + "id": "nodegpt", + "reference": "https://github.com/xXAdonesXx/NodeGPT", + "files": [ + "https://github.com/xXAdonesXx/NodeGPT" + ], + "install_type": "git-clone", + "description": "Implementation of AutoGen inside ComfyUI. This repository is under development, and not everything is functioning correctly yet." + }, + { + "author": "Suzie1", + "title": "Comfyroll Studio", + "id": "comfyroll", + "reference": "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes", + "files": [ + "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes" + ], + "install_type": "git-clone", + "description": "Custom nodes for SDXL and SD1.5 including Multi-ControlNet, LoRA, Aspect Ratio, Process Switches, and many more nodes. NOTE: Maintainer is changed to Suzie1 from RockOfFire. [w/Using an outdated version has resulted in reported issues with updates not being applied. Trying to reinstall the software is advised.]" + }, + { + "author": "bmad4ever", + "title": "ComfyUI-Bmad-DirtyUndoRedo", + "reference": "https://github.com/bmad4ever/ComfyUI-Bmad-DirtyUndoRedo", + "files": [ + "https://github.com/bmad4ever/ComfyUI-Bmad-DirtyUndoRedo" + ], + "install_type": "git-clone", + "description": "ComfyUI extension that adds undo (and redo) functionality." + }, + { + "author": "bmad4ever", + "title": "Bmad Nodes", + "id": "bmad", + "reference": "https://github.com/bmad4ever/comfyui_bmad_nodes", + "files": [ + "https://github.com/bmad4ever/comfyui_bmad_nodes" + ], + "install_type": "git-clone", + "description": "This custom node offers the following functionalities: API support for setting up API requests, computer vision primarily for masking or collages, and general utility to streamline workflow setup or implement essential missing features." + }, + { + "author": "bmad4ever", + "title": "comfyui_ab_sampler", + "id": "ab-sampler", + "reference": "https://github.com/bmad4ever/comfyui_ab_samplercustom", + "files": [ + "https://github.com/bmad4ever/comfyui_ab_samplercustom" + ], + "install_type": "git-clone", + "description": "Experimental sampler node. Sampling alternates between A and B inputs until only one remains, starting with A. B steps run over a 2x2 grid, where 3/4's of the grid are copies of the original input latent. When the optional mask is used, the region outside the defined roi is copied from the original latent at the end of every step." + }, + { + "author": "bmad4ever", + "title": "Lists Cartesian Product", + "reference": "https://github.com/bmad4ever/comfyui_lists_cartesian_product", + "files": [ + "https://github.com/bmad4ever/comfyui_lists_cartesian_product" + ], + "install_type": "git-clone", + "description": "Given a set of lists, the node adjusts them so that when used as input to another node all the possible argument permutations are computed." + }, + { + "author": "bmad4ever", + "title": "comfyui_wfc_like", + "id": "wfc", + "reference": "https://github.com/bmad4ever/comfyui_wfc_like", + "files": [ + "https://github.com/bmad4ever/comfyui_wfc_like" + ], + "install_type": "git-clone", + "description": "An 'opinionated' Wave Function Collapse implementation with a set of nodes for comfyui" + }, + { + "author": "bmad4ever", + "title": "comfyui_quilting", + "id": "quilting", + "reference": "https://github.com/bmad4ever/comfyui_quilting", + "files": [ + "https://github.com/bmad4ever/comfyui_quilting" + ], + "install_type": "git-clone", + "description": "image and latent quilting nodes for comfyui" + }, + { + "author": "FizzleDorf", + "title": "FizzNodes", + "id": "fizz", + "reference": "https://github.com/FizzleDorf/ComfyUI_FizzNodes", + "files": [ + "https://github.com/FizzleDorf/ComfyUI_FizzNodes" + ], + "install_type": "git-clone", + "description": "Scheduled prompts, scheduled float/int values and wave function nodes for animations and utility. compatable with [a/framesync](https://www.framesync.xyz/) and [a/keyframe-string-generator](https://www.chigozie.co.uk/keyframe-string-generator/) for audio synced animations in Comfyui." + }, + { + "author": "FizzleDorf", + "title": "ComfyUI-AIT", + "id": "ait", + "reference": "https://github.com/FizzleDorf/ComfyUI-AIT", + "files": [ + "https://github.com/FizzleDorf/ComfyUI-AIT" + ], + "install_type": "git-clone", + "description": "A ComfyUI implementation of Facebook Meta's [a/AITemplate](https://github.com/facebookincubator/AITemplate) repo for faster inference using cpp/cuda. This new repo is behind the old version but is a much more stable foundation to keep AIT online. Please be patient as the repo will eventually include the same features as before.\nNOTE: You can find the old AIT extension in the legacy channel." + }, + { + "author": "filipemeneses", + "title": "Pixelization", + "id": "pixelization", + "reference": "https://github.com/filipemeneses/comfy_pixelization", + "files": [ + "https://github.com/filipemeneses/comfy_pixelization" + ], + "install_type": "git-clone", + "description": "ComfyUI node that pixelizes images." + }, + { + "author": "shiimizu", + "title": "smZNodes", + "id": "smz", + "reference": "https://github.com/shiimizu/ComfyUI_smZNodes", + "files": [ + "https://github.com/shiimizu/ComfyUI_smZNodes" + ], + "install_type": "git-clone", + "description": "NODES: CLIP Text Encode++. Achieve identical embeddings from stable-diffusion-webui for ComfyUI." + }, + { + "author": "shiimizu", + "title": "Tiled Diffusion & VAE for ComfyUI", + "id": "tiled-diffusion", + "reference": "https://github.com/shiimizu/ComfyUI-TiledDiffusion", + "files": [ + "https://github.com/shiimizu/ComfyUI-TiledDiffusion" + ], + "install_type": "git-clone", + "description": "The extension enables large image drawing & upscaling with limited VRAM via the following techniques:\n1.Two SOTA diffusion tiling algorithms: [a/Mixture of Diffusers](https://github.com/albarji/mixture-of-diffusers) and [a/MultiDiffusion](https://github.com/omerbt/MultiDiffusion)\n2.pkuliyi2015's Tiled VAE algorithm." + }, + { + "author": "ZaneA", + "title": "ImageReward", + "reference": "https://github.com/ZaneA/ComfyUI-ImageReward", + "files": [ + "https://github.com/ZaneA/ComfyUI-ImageReward" + ], + "install_type": "git-clone", + "description": "NODES: ImageRewardLoader, ImageRewardScore" + }, + { + "author": "SeargeDP", + "title": "SeargeSDXL", + "id": "searge", + "reference": "https://github.com/SeargeDP/SeargeSDXL", + "files": [ + "https://github.com/SeargeDP/SeargeSDXL" + ], + "install_type": "git-clone", + "description": "Custom nodes for easier use of SDXL in ComfyUI including an img2img workflow that utilizes both the base and refiner checkpoints." + }, + { + "author": "cubiq", + "title": "Simple Math", + "id": "simplemath", + "reference": "https://github.com/cubiq/ComfyUI_SimpleMath", + "files": [ + "https://github.com/cubiq/ComfyUI_SimpleMath" + ], + "install_type": "git-clone", + "description": "custom node for ComfyUI to perform simple math operations" + }, + { + "author": "cubiq", + "title": "ComfyUI_IPAdapter_plus", + "id": "ipadapter", + "reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus", + "files": [ + "https://github.com/cubiq/ComfyUI_IPAdapter_plus" + ], + "pip": ["insightface"], + "install_type": "git-clone", + "description": "ComfyUI reference implementation for IPAdapter models. The code is mostly taken from the original IPAdapter repository and laksjdjf's implementation, all credit goes to them. I just made the extension closer to ComfyUI philosophy." + }, + { + "author": "cubiq", + "title": "ComfyUI InstantID (Native Support)", + "id": "instantid", + "reference": "https://github.com/cubiq/ComfyUI_InstantID", + "files": [ + "https://github.com/cubiq/ComfyUI_InstantID" + ], + "install_type": "git-clone", + "description": "Native [a/InstantID](https://github.com/InstantID/InstantID) support for ComfyUI.\nThis extension differs from the many already available as it doesn't use diffusers but instead implements InstantID natively and it fully integrates with ComfyUI.\nPlease note this still could be considered beta stage, looking forward to your feedback." + }, + { + "author": "cubiq", + "title": "Face Analysis for ComfyUI", + "id": "faceanalysis", + "reference": "https://github.com/cubiq/ComfyUI_FaceAnalysis", + "files": [ + "https://github.com/cubiq/ComfyUI_FaceAnalysis" + ], + "install_type": "git-clone", + "description": "This extension uses [a/DLib](http://dlib.net/) to calculate the Euclidean and Cosine distance between two faces.\nNOTE: Install the Shape Predictor, Face Recognition model from the Install models menu." + }, + { + "author": "cubiq", + "title": "PuLID_ComfyUI", + "id": "pulid", + "reference": "https://github.com/cubiq/PuLID_ComfyUI", + "files": [ + "https://github.com/cubiq/PuLID_ComfyUI" + ], + "install_type": "git-clone", + "description": "[a/PuLID](https://github.com/ToTheBeginning/PuLID) ComfyUI native implementation." + }, + { + "author": "shockz0rz", + "title": "InterpolateEverything", + "id": "interpolate-everything", + "reference": "https://github.com/shockz0rz/ComfyUI_InterpolateEverything", + "files": [ + "https://github.com/shockz0rz/ComfyUI_InterpolateEverything" + ], + "install_type": "git-clone", + "description": "Nodes: Interpolate Poses, Interpolate Lineart, ... Custom nodes for interpolating between, well, everything in the Stable Diffusion ComfyUI." + }, + { + "author": "shockz0rz", + "title": "comfy-easy-grids", + "id": "easy-grids", + "reference": "https://github.com/shockz0rz/comfy-easy-grids", + "files": [ + "https://github.com/shockz0rz/comfy-easy-grids" + ], + "install_type": "git-clone", + "description": "A set of custom nodes for creating image grids, sequences, and batches in ComfyUI." + }, + { + "author": "yolanother", + "title": "Comfy UI Prompt Agent", + "id": "prompt-agent", + "reference": "https://github.com/yolanother/DTAIComfyPromptAgent", + "files": [ + "https://github.com/yolanother/DTAIComfyPromptAgent" + ], + "install_type": "git-clone", + "description": "Nodes: Prompt Agent, Prompt Agent (String). This script provides a prompt agent node for the Comfy UI stable diffusion client." + }, + { + "author": "yolanother", + "title": "Image to Text Node", + "id": "dta-img2txt", + "reference": "https://github.com/yolanother/DTAIImageToTextNode", + "files": [ + "https://github.com/yolanother/DTAIImageToTextNode" + ], + "install_type": "git-clone", + "description": "Nodes: Image URL to Text, Image to Text." + }, + { + "author": "yolanother", + "title": "Comfy UI Online Loaders", + "id": "dta-loader", + "reference": "https://github.com/yolanother/DTAIComfyLoaders", + "files": [ + "https://github.com/yolanother/DTAIComfyLoaders" + ], + "install_type": "git-clone", + "description": "Nodes: Submit Image (Parameters), Submit Image. A collection of loaders that use a shared common online data source rather than relying on the files to be present locally." + }, + { + "author": "yolanother", + "title": "Comfy AI DoubTech.ai Image Sumission Node", + "id": "dta-submit", + "reference": "https://github.com/yolanother/DTAIComfyImageSubmit", + "files": [ + "https://github.com/yolanother/DTAIComfyImageSubmit" + ], + "install_type": "git-clone", + "description": "A ComfyAI submit node to upload images to DoubTech.ai" + }, + { + "author": "yolanother", + "title": "Comfy UI QR Codes", + "id": "dta-qr", + "reference": "https://github.com/yolanother/DTAIComfyQRCodes", + "files": [ + "https://github.com/yolanother/DTAIComfyQRCodes" + ], + "install_type": "git-clone", + "description": "This extension introduces QR code nodes for the Comfy UI stable diffusion client. NOTE: ComfyUI qrcode extension required." + }, + { + "author": "yolanother", + "title": "Variables for Comfy UI", + "id": "dta-var", + "reference": "https://github.com/yolanother/DTAIComfyVariables", + "files": [ + "https://github.com/yolanother/DTAIComfyVariables" + ], + "install_type": "git-clone", + "description": "Nodes: String, Int, Float, Short String, CLIP Text Encode (With Variables), String Format, Short String Format. This extension introduces quality of life improvements by providing variable nodes and shared global variables." + }, + { + "author": "sipherxyz", + "title": "comfyui-art-venture", + "id": "artventure", + "reference": "https://github.com/sipherxyz/comfyui-art-venture", + "files": [ + "https://github.com/sipherxyz/comfyui-art-venture" + ], + "install_type": "git-clone", + "description": "Nodes: ImagesConcat, LoadImageFromUrl, AV_UploadImage" + }, + { + "author": "SOELexicon", + "title": "LexMSDBNodes", + "id": "lexmsdb", + "reference": "https://github.com/SOELexicon/ComfyUI-LexMSDBNodes", + "files": [ + "https://github.com/SOELexicon/ComfyUI-LexMSDBNodes" + ], + "install_type": "git-clone", + "description": "Nodes: MSSqlTableNode, MSSqlSelectNode. This extension provides custom nodes to interact with MSSQL." + }, + { + "author": "pants007", + "title": "pants", + "reference": "https://github.com/pants007/comfy-pants", + "files": [ + "https://github.com/pants007/comfy-pants" + ], + "install_type": "git-clone", + "description": "Nodes: Make Square Node, Interrogate Node, TextEncodeAIO" + }, + { + "author": "evanspearman", + "title": "ComfyMath", + "id": "comfymath", + "reference": "https://github.com/evanspearman/ComfyMath", + "files": [ + "https://github.com/evanspearman/ComfyMath" + ], + "install_type": "git-clone", + "description": "Provides Math Nodes for ComfyUI. Boolean Logic, Integer Arithmetic, Floating Point Arithmetic and Functions, Vec2, Vec3, and Vec4 Arithmetic and Functions" + }, + { + "author": "civitai", + "title": "comfy-nodes", + "id": "civitai", + "reference": "https://github.com/civitai/comfy-nodes", + "files": [ + "https://github.com/civitai/comfy-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: CivitAI_Loaders. Load Checkpoints, and LORA models directly from CivitAI API." + }, + { + "author": "andersxa", + "title": "CLIP Directional Prompt Attention", + "id": "prompt-attention", + "reference": "https://github.com/andersxa/comfyui-PromptAttention", + "files": [ + "https://github.com/andersxa/comfyui-PromptAttention" + ], + "pip": ["scikit-learn", "matplotlib"], + "install_type": "git-clone", + "description": "Nodes: CLIP Directional Prompt Attention Encode. Direction prompt attention tries to solve the problem of contextual words (or parts of the prompt) having an effect on much later or irrelevant parts of the prompt." + }, + { + "author": "ArtVentureX", + "title": "AnimateDiff", + "reference": "https://github.com/ArtVentureX/comfyui-animatediff", + "pip": ["flash_attn"], + "files": [ + "https://github.com/ArtVentureX/comfyui-animatediff" + ], + "install_type": "git-clone", + "description": "AnimateDiff integration for ComfyUI, adapts from sd-webui-animatediff.\n[w/You only need to download one of [a/mm_sd_v14.ckpt](https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v14.ckpt) | [a/mm_sd_v15.ckpt](https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v15.ckpt). Put the model weights under %%ComfyUI/custom_nodes/comfyui-animatediff/models%%. DO NOT change model filename.]" + }, + { + "author": "twri", + "title": "SDXL Prompt Styler", + "id": "twri-styler", + "reference": "https://github.com/twri/sdxl_prompt_styler", + "files": [ + "https://github.com/twri/sdxl_prompt_styler" + ], + "install_type": "git-clone", + "description": "SDXL Prompt Styler is a node that enables you to style prompts based on predefined templates stored in a JSON file." + }, + { + "author": "wolfden", + "title": "SDXL Prompt Styler (customized version by wolfden)", + "id": "wolfden-styler", + "reference": "https://github.com/wolfden/ComfyUi_PromptStylers", + "files": [ + "https://github.com/wolfden/ComfyUi_PromptStylers" + ], + "install_type": "git-clone", + "description": "These custom nodes provide a variety of customized prompt stylers based on [a/twri/SDXL Prompt Styler](https://github.com/twri/sdxl_prompt_styler)." + }, + { + "author": "wolfden", + "title": "ComfyUi_String_Function_Tree", + "id": "str-func-tree", + "reference": "https://github.com/wolfden/ComfyUi_String_Function_Tree", + "files": [ + "https://github.com/wolfden/ComfyUi_String_Function_Tree" + ], + "install_type": "git-clone", + "description": "This custom node provides the capability to manipulate multiple string inputs." + }, + { + "author": "daxthin", + "title": "DZ-FaceDetailer", + "id": "dz-facedetailer", + "reference": "https://github.com/daxthin/DZ-FaceDetailer", + "files": [ + "https://github.com/daxthin/DZ-FaceDetailer" + ], + "install_type": "git-clone", + "description": "Face Detailer is a custom node for the 'ComfyUI' framework inspired by !After Detailer extension from auto1111, it allows you to detect faces using Mediapipe and YOLOv8n to create masks for the detected faces." + }, + { + "author": "asagi4", + "title": "ComfyUI prompt control", + "id": "prompt-control", + "reference": "https://github.com/asagi4/comfyui-prompt-control", + "files": [ + "https://github.com/asagi4/comfyui-prompt-control" + ], + "install_type": "git-clone", + "description": "Nodes for convenient prompt editing. The aim is to make basic generations in ComfyUI completely prompt-controllable." + }, + { + "author": "asagi4", + "title": "ComfyUI-CADS", + "id": "cads", + "reference": "https://github.com/asagi4/ComfyUI-CADS", + "files": [ + "https://github.com/asagi4/ComfyUI-CADS" + ], + "install_type": "git-clone", + "description": "Attempts to implement [a/CADS](https://arxiv.org/abs/2310.17347) for ComfyUI. Credit also to the [a/A1111 implementation](https://github.com/v0xie/sd-webui-cads/tree/main) that I used as a reference." + }, + { + "author": "asagi4", + "title": "asagi4/comfyui-utility-nodes", + "id": "asagi-nodes", + "reference": "https://github.com/asagi4/comfyui-utility-nodes", + "files": [ + "https://github.com/asagi4/comfyui-utility-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:MUJinjaRender, MUSimpleWildcard" + }, + { + "author": "asagi4", + "title": "Adaptive Guidance for ComfyUI", + "id": "asagi-nodes", + "reference": "https://github.com/asagi4/ComfyUI-Adaptive-Guidance", + "files": [ + "https://github.com/asagi4/ComfyUI-Adaptive-Guidance" + ], + "install_type": "git-clone", + "description": "An implementation of adaptive guidance for ComfyUI\nSee [a/https://bcv-uniandes.github.io/adaptiveguidance-wp](https://bcv-uniandes.github.io/adaptiveguidance-wp)" + }, + { + "author": "jamesWalker55", + "title": "ComfyUI - P2LDGAN Node", + "id": "p2ldgan", + "reference": "https://github.com/jamesWalker55/comfyui-p2ldgan", + "files": [ + "https://github.com/jamesWalker55/comfyui-p2ldgan" + ], + "install_type": "git-clone", + "description": "Nodes: P2LDGAN. This integrates P2LDGAN into ComfyUI. P2LDGAN extracts lineart from input images.\n[w/To use this extension, you need to download the [a/p2ldgan model](https://drive.google.com/file/d/1To4V_Btc3QhCLBWZ0PdSNgC1cbm3isHP) and save it in the %%ComfyUI/custom_nodes/comfyui-p2ldgan/checkpoints%% directory.]" + }, + { + "author": "jamesWalker55", + "title": "Various ComfyUI Nodes by Type", + "id": "jameswalker-nodes", + "reference": "https://github.com/jamesWalker55/comfyui-various", + "files": [ + "https://github.com/jamesWalker55/comfyui-various" + ], + "nodename_pattern": "^JW", + "install_type": "git-clone", + "description": "Nodes: JWInteger, JWFloat, JWString, JWImageLoadRGB, JWImageResize, ..." + }, + { + "author": "adieyal", + "title": "DynamicPrompts Custom Nodes", + "id": "dynamicprompt", + "reference": "https://github.com/adieyal/comfyui-dynamicprompts", + "files": [ + "https://github.com/adieyal/comfyui-dynamicprompts" + ], + "install_type": "git-clone", + "description": "Nodes: Random Prompts, Combinatorial Prompts, I'm Feeling Lucky, Magic Prompt, Jinja2 Templates. ComfyUI-DynamicPrompts is a custom nodes library that integrates into your existing ComfyUI Library. It provides nodes that enable the use of Dynamic Prompts in your ComfyUI." + }, + { + "author": "mihaiiancu", + "title": "mihaiiancu/Inpaint", + "id": "inpaint", + "reference": "https://github.com/mihaiiancu/ComfyUI_Inpaint", + "files": [ + "https://github.com/mihaiiancu/ComfyUI_Inpaint" + ], + "install_type": "git-clone", + "description": "Nodes: InpaintMediapipe. This node provides a simple interface to inpaint." + }, + { + "author": "kwaroran", + "title": "abg-comfyui", + "id": "abg", + "reference": "https://github.com/kwaroran/abg-comfyui", + "files": [ + "https://github.com/kwaroran/abg-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes: Remove Image Background (abg). A Anime Background Remover node for comfyui, based on this hf space, works same as AGB extention in automatic1111." + }, + { + "author": "bash-j", + "title": "Mikey Nodes", + "id": "mikey", + "reference": "https://github.com/bash-j/mikey_nodes", + "files": [ + "https://github.com/bash-j/mikey_nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Prompt With Style, Prompt With SDXL, Resize Image for SDXL, Save Image With Prompt Data, HaldCLUT, Empty Latent Ratio Select/Custom SDXL" + }, + { + "author": "failfa.st", + "title": "failfast-comfyui-extensions", + "id": "failfast", + "reference": "https://github.com/failfa-st/failfast-comfyui-extensions", + "files": [ + "https://github.com/failfa-st/failfast-comfyui-extensions" + ], + "install_type": "git-clone", + "description": "node color customization, custom colors, dot reroutes, link rendering options, straight lines, group freezing, node pinning, automated arrangement of nodes, copy image\nNOTE: This repo is identical to 'blibla-comfyui-extensions'." + }, + { + "author": "Pfaeff", + "title": "pfaeff-comfyui", + "id": "pfaeff", + "reference": "https://github.com/Pfaeff/pfaeff-comfyui", + "files": [ + "https://github.com/Pfaeff/pfaeff-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes: AstropulsePixelDetector, BackgroundRemover, ImagePadForBetterOutpaint, InpaintingPipelineLoader, Inpainting, ..." + }, + { + "author": "wallish77", + "title": "wlsh_nodes", + "id": "wlsh", + "reference": "https://github.com/wallish77/wlsh_nodes", + "files": [ + "https://github.com/wallish77/wlsh_nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Checkpoint Loader with Name, Save Prompt Info, Outpaint to Image, CLIP Positive-Negative, SDXL Quick Empty Latent, Empty Latent by Ratio, Time String, SDXL Steps, SDXL Resolutions ..." + }, + { + "author": "Kosinkadink", + "title": "ComfyUI-Advanced-ControlNet", + "id": "adv-cnet", + "reference": "https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet", + "files": [ + "https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet" + ], + "install_type": "git-clone", + "description": "Nodes: ControlNetLoaderAdvanced, DiffControlNetLoaderAdvanced, ScaledSoftControlNetWeights, SoftControlNetWeights, CustomControlNetWeights, SoftT2IAdapterWeights, CustomT2IAdapterWeights" + }, + { + "author": "Kosinkadink", + "title": "AnimateDiff Evolved", + "id": "ad-evolved", + "reference": "https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved", + "files": [ + "https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved" + ], + "install_type": "git-clone", + "description": "A forked repository that actively maintains [a/AnimateDiff](https://github.com/ArtVentureX/comfyui-animatediff), created by ArtVentureX.\n\nImproved AnimateDiff integration for ComfyUI, adapts from sd-webui-animatediff.\n[w/Download one or more motion models from [a/Original Models](https://huggingface.co/guoyww/animatediff/tree/main) | [a/Finetuned Models](https://huggingface.co/manshoety/AD_Stabilized_Motion/tree/main). See README for additional model links and usage. Put the model weights under %%ComfyUI/custom_nodes/ComfyUI-AnimateDiff-Evolved/models%%. You are free to rename the models, but keeping original names will ease use when sharing your workflow.]" + }, + { + "author": "Kosinkadink", + "title": "ComfyUI-VideoHelperSuite", + "id": "vhs", + "reference": "https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite", + "files": [ + "https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite" + ], + "install_type": "git-clone", + "description": "Nodes: VHS_VideoCombine. Nodes related to video workflows" + }, + { + "author": "Gourieff", + "title": "ReActor Node for ComfyUI", + "id": "reactor", + "reference": "https://github.com/Gourieff/comfyui-reactor-node", + "files": [ + "https://github.com/Gourieff/comfyui-reactor-node" + ], + "install_type": "git-clone", + "description": "The Fast and Simple 'roop-like' Face Swap Extension Node for ComfyUI, based on ReActor (ex Roop-GE) SD-WebUI Face Swap Extension" + }, + { + "author": "Gourieff", + "title": "ComfyUI-FutureWarningIgnore", + "id": "futureignore", + "reference": "https://github.com/Gourieff/ComfyUI-FutureWarningIgnore", + "files": [ + "https://github.com/Gourieff/ComfyUI-FutureWarningIgnore/raw/main/0_FutureWarningIgnore.py" + ], + "install_type": "copy", + "description": "This extension collapses 'future warning' messages in your Console" + }, + { + "author": "imb101", + "title": "FaceSwap", + "id": "faceswap", + "reference": "https://github.com/imb101/ComfyUI-FaceSwap", + "files": [ + "https://github.com/imb101/ComfyUI-FaceSwap" + ], + "install_type": "git-clone", + "description": "Nodes:FaceSwapNode. Very basic custom node to enable face swapping in ComfyUI. (roop)" + }, + { + "author": "Chaoses-Ib", + "title": "ComfyUI_Ib_CustomNodes","id": "ib-nodes", + "reference": "https://github.com/Chaoses-Ib/ComfyUI_Ib_CustomNodes", + "files": [ + "https://github.com/Chaoses-Ib/ComfyUI_Ib_CustomNodes" + ], + "install_type": "git-clone", + "description": "Nodes: LoadImageFromPath. Load Image From Path loads the image from the source path and does not have such problems." + }, + { + "author": "AIrjen", + "title": "One Button Prompt", + "id": "1button", + "reference": "https://github.com/AIrjen/OneButtonPrompt", + "files": [ + "https://github.com/AIrjen/OneButtonPrompt" + ], + "install_type": "git-clone", + "description": "One Button Prompt has a prompt generation node for beginners who have problems writing a good prompt, or advanced users who want to get inspired. It generates an entire prompt from scratch. It is random, but controlled. You simply load up the script and press generate, and let it surprise you." + }, + { + "author": "coreyryanhanson", + "title": "ComfyQR", + "id": "comfyqr", + "reference": "https://github.com/coreyryanhanson/ComfyQR", + "files": [ + "https://github.com/coreyryanhanson/ComfyQR" + ], + "install_type": "git-clone", + "description": "QR generation within ComfyUI. Contains nodes suitable for workflows from generating basic QR images to techniques with advanced QR masking." + }, + { + "author": "coreyryanhanson", + "title": "ComfyQR-scanning-nodes", + "id": "comfyqr-scanning", + "reference": "https://github.com/coreyryanhanson/ComfyQR-scanning-nodes", + "files": [ + "https://github.com/coreyryanhanson/ComfyQR-scanning-nodes" + ], + "install_type": "git-clone", + "description": "A set of ComfyUI nodes to quickly test generated QR codes for scannability. A companion project to ComfyQR." + }, + { + "author": "dimtoneff", + "title": "ComfyUI PixelArt Detector", + "id": "pixelart-detector", + "reference": "https://github.com/dimtoneff/ComfyUI-PixelArt-Detector", + "files": [ + "https://github.com/dimtoneff/ComfyUI-PixelArt-Detector" + ], + "install_type": "git-clone", + "description": "This node manipulates the pixel art image in ways that it should look pixel perfect (downscales, changes palette, upscales etc.)." + }, + { + "author": "dimtoneff", + "title": "Eagle PNGInfo", + "id": "eaglepnginfo", + "reference": "https://github.com/hylarucoder/ComfyUI-Eagle-PNGInfo", + "files": [ + "https://github.com/hylarucoder/ComfyUI-Eagle-PNGInfo" + ], + "install_type": "git-clone", + "description": "Nodes: EagleImageNode" + }, + { + "author": "theUpsider", + "title": "Styles CSV Loader Extension for ComfyUI", + "id": "styles-csv-loader", + "reference": "https://github.com/theUpsider/ComfyUI-Styles_CSV_Loader", + "files": [ + "https://github.com/theUpsider/ComfyUI-Styles_CSV_Loader" + ], + "install_type": "git-clone", + "description": "This extension allows users to load styles from a CSV file, primarily for migration purposes from the automatic1111 Stable Diffusion web UI." + }, + { + "author": "theUpsider", + "title": "ComfyUI-Logic", + "id": "comfy-logic", + "reference": "https://github.com/theUpsider/ComfyUI-Logic", + "files": [ + "https://github.com/theUpsider/ComfyUI-Logic" + ], + "install_type": "git-clone", + "description": "An extension to ComfyUI that introduces logic nodes and conditional rendering capabilities." + }, + { + "author": "M1kep", + "title": "Comfy_KepListStuff", + "id": "keplist", + "reference": "https://github.com/M1kep/Comfy_KepListStuff", + "files": [ + "https://github.com/M1kep/Comfy_KepListStuff" + ], + "install_type": "git-clone", + "description": "Nodes: Range(Step), Range(Num Steps), List Length, Image Overlay, Stack Images, Empty Images, Join Image Lists, Join Float Lists. This extension provides various list manipulation nodes" + }, + { + "author": "M1kep", + "title": "ComfyLiterals", + "id": "comfyliterals", + "reference": "https://github.com/M1kep/ComfyLiterals", + "files": [ + "https://github.com/M1kep/ComfyLiterals" + ], + "install_type": "git-clone", + "description": "Nodes: Int, Float, String, Operation, Checkpoint" + }, + { + "author": "M1kep", + "title": "KepPromptLang", + "id": "kepprompt", + "reference": "https://github.com/M1kep/KepPromptLang", + "files": [ + "https://github.com/M1kep/KepPromptLang" + ], + "install_type": "git-clone", + "description": "Nodes: Build Gif, Special CLIP Loader. It offers various manipulation capabilities for the internal operations of the prompt." + }, + { + "author": "M1kep", + "title": "Comfy_KepMatteAnything", + "id": "kepmatte", + "reference": "https://github.com/M1kep/Comfy_KepMatteAnything", + "files": [ + "https://github.com/M1kep/Comfy_KepMatteAnything" + ], + "install_type": "git-clone", + "description": "This extension provides a custom node that allows the use of [a/Matte Anything](https://github.com/hustvl/Matte-Anything) in ComfyUI." + }, + { + "author": "M1kep", + "title": "Comfy_KepKitchenSink", + "id": "kepkitchen", + "reference": "https://github.com/M1kep/Comfy_KepKitchenSink", + "files": [ + "https://github.com/M1kep/Comfy_KepKitchenSink" + ], + "install_type": "git-clone", + "description": "Nodes: KepRotateImage" + }, + { + "author": "M1kep", + "title": "ComfyUI-OtherVAEs", + "id": "kep-othervae", + "reference": "https://github.com/M1kep/ComfyUI-OtherVAEs", + "files": [ + "https://github.com/M1kep/ComfyUI-OtherVAEs" + ], + "install_type": "git-clone", + "description": "Nodes: TAESD VAE Decode" + }, + { + "author": "M1kep", + "title": "ComfyUI-KepOpenAI", + "id": "kep-openai", + "reference": "https://github.com/M1kep/ComfyUI-KepOpenAI", + "files": [ + "https://github.com/M1kep/ComfyUI-KepOpenAI" + ], + "install_type": "git-clone", + "description": "ComfyUI-KepOpenAI is a user-friendly node that serves as an interface to the GPT-4 with Vision (GPT-4V) API. This integration facilitates the processing of images coupled with text prompts, leveraging the capabilities of the OpenAI API to generate text completions that are contextually relevant to the provided inputs." + }, + { + "author": "uarefans", + "title": "ComfyUI-Fans", + "id": "fans", + "reference": "https://github.com/uarefans/ComfyUI-Fans", + "files": [ + "https://github.com/uarefans/ComfyUI-Fans" + ], + "install_type": "git-clone", + "description": "Nodes: Fans Styler (Max 10 Style), Fans Text Concat (Until 10 text)." + }, + { + "author": "NicholasMcCarthy", + "title": "ComfyUI_TravelSuite", + "id": "travel", + "reference": "https://github.com/NicholasMcCarthy/ComfyUI_TravelSuite", + "files": [ + "https://github.com/NicholasMcCarthy/ComfyUI_TravelSuite" + ], + "install_type": "git-clone", + "description": "ComfyUI custom nodes to apply various latent travel techniques." + }, + { + "author": "ManglerFTW", + "title": "ComfyI2I", + "id": "comfyi2i", + "reference": "https://github.com/ManglerFTW/ComfyI2I", + "files": [ + "https://github.com/ManglerFTW/ComfyI2I" + ], + "install_type": "git-clone", + "description": "A set of custom nodes to perform image 2 image functions in ComfyUI." + }, + { + "author": "mpiquero7164", + "title": "SaveImgPrompt", + "id": "save-imgprompt", + "reference": "https://github.com/mpiquero7164/ComfyUI-SaveImgPrompt", + "files": [ + "https://github.com/mpiquero7164/ComfyUI-SaveImgPrompt" + ], + "install_type": "git-clone", + "description": "Save a png or jpeg and option to save prompt/workflow in a text or json file for each image in Comfy + Workflow loading." + }, + { + "author": "m-sokes", + "title": "ComfyUI Sokes Nodes", + "id": "sokes", + "reference": "https://github.com/m-sokes/ComfyUI-Sokes-Nodes", + "files": [ + "https://github.com/m-sokes/ComfyUI-Sokes-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Empty Latent Randomizer (9 Inputs)" + }, + { + "author": "Extraltodeus", + "title": "noise latent perlinpinpin", + "id": "perlipinpin", + "reference": "https://github.com/Extraltodeus/noise_latent_perlinpinpin", + "files": [ + "https://github.com/Extraltodeus/noise_latent_perlinpinpin" + ], + "install_type": "git-clone", + "description": "Nodes: NoisyLatentPerlin. This allows to create latent spaces filled with perlin-based noise that can actually be used by the samplers." + }, + { + "author": "Extraltodeus", + "title": "LoadLoraWithTags", + "reference": "https://github.com/Extraltodeus/LoadLoraWithTags", + "files": [ + "https://github.com/Extraltodeus/LoadLoraWithTags" + ], + "install_type": "git-clone", + "description": "Nodes:LoadLoraWithTags. Save/Load trigger words for loras from a json and auto fetch them on civitai if they are missing." + }, + { + "author": "Extraltodeus", + "title": "sigmas_tools_and_the_golden_scheduler", + "id": "sigmas-tools", + "reference": "https://github.com/Extraltodeus/sigmas_tools_and_the_golden_scheduler", + "files": [ + "https://github.com/Extraltodeus/sigmas_tools_and_the_golden_scheduler" + ], + "install_type": "git-clone", + "description": "A few nodes to mix sigmas and a custom scheduler that uses phi, then one using eval() to be able to schedule with custom formulas." + }, + { + "author": "Extraltodeus", + "title": "ComfyUI-AutomaticCFG", + "id": "autocfg", + "reference": "https://github.com/Extraltodeus/ComfyUI-AutomaticCFG", + "files": [ + "https://github.com/Extraltodeus/ComfyUI-AutomaticCFG" + ], + "install_type": "git-clone", + "description": "My own version 'from scratch' of a self-rescaling CFG. It isn't much but it's honest work.\nTLDR: set your CFG at 8 to try it. No burned images and artifacts anymore. CFG is also a bit more sensitive because it's a proportion around 8. Low scale like 4 also gives really nice results since your CFG is not the CFG anymore. Also in general even with relatively low settings it seems to improve the quality." + }, + { + "author": "Extraltodeus", + "title": "Vector_Sculptor_ComfyUI", + "id": "vector-sculptor", + "reference": "https://github.com/Extraltodeus/Vector_Sculptor_ComfyUI", + "files": [ + "https://github.com/Extraltodeus/Vector_Sculptor_ComfyUI" + ], + "install_type": "git-clone", + "description": "The main node makes your conditioning go towards similar concepts so to enrich your composition or further away so to make it more precise. It gathers similar pre-cond vectors for as long as the cosine similarity score diminishes. If it climbs back it stops. This allows to set a relative direction to similar concepts.\nThere are examples at the end but [a/you can also check this imgur album](https://imgur.com/a/WvPd81Y) which demonstrates the capability of improving variety." + }, + { + "author": "Extraltodeus", + "title": "Stable-Diffusion-temperature-settings", + "id": "sd-temperature", + "reference": "https://github.com/Extraltodeus/Stable-Diffusion-temperature-settings", + "files": [ + "https://github.com/Extraltodeus/Stable-Diffusion-temperature-settings" + ], + "install_type": "git-clone", + "description": "Provides the ability to set the temperature for both UNET and CLIP. For ComfyUI." + }, + { + "author": "Extraltodeus", + "title": "Uncond-Zero-for-ComfyUI", + "id": "uncond-zero", + "reference": "https://github.com/Extraltodeus/Uncond-Zero-for-ComfyUI", + "files": [ + "https://github.com/Extraltodeus/Uncond-Zero-for-ComfyUI" + ], + "install_type": "git-clone", + "description": "Allows to sample without generating any uncond with Stable Diffusion!" + }, + { + "author": "Extraltodeus", + "title": "pre_cfg_comfy_nodes_for_ComfyUI", + "id": "precfg", + "reference": "https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI", + "files": [ + "https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI" + ], + "install_type": "git-clone", + "description": "A set of nodes to prepare the noise predictions before the CFG function" + }, + { + "author": "JPS", + "title": "JPS Custom Nodes for ComfyUI", + "id": "jps-nodes", + "reference": "https://github.com/JPS-GER/ComfyUI_JPS-Nodes", + "files": [ + "https://github.com/JPS-GER/ComfyUI_JPS-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Various nodes to handle SDXL Resolutions, SDXL Basic Settings, IP Adapter Settings, Revision Settings, SDXL Prompt Styler, Crop Image to Square, Crop Image to Target Size, Get Date-Time String, Resolution Multiply, Largest Integer, 5-to-1 Switches for Integer, Images, Latents, Conditioning, Model, VAE, ControlNet" + }, + { + "author": "hustille", + "title": "hus' utils for ComfyUI", + "id": "husutil", + "reference": "https://github.com/hustille/ComfyUI_hus_utils", + "files": [ + "https://github.com/hustille/ComfyUI_hus_utils" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes primarily for seed and filename generation" + }, + { + "author": "hustille", + "title": "ComfyUI_Fooocus_KSampler", + "id": "fooocus-ksampler", + "reference": "https://github.com/hustille/ComfyUI_Fooocus_KSampler", + "files": [ + "https://github.com/hustille/ComfyUI_Fooocus_KSampler" + ], + "install_type": "git-clone", + "description": "Nodes: KSampler With Refiner (Fooocus). The KSampler from [a/Fooocus](https://github.com/lllyasviel/Fooocus) as a ComfyUI node [w/NOTE: This patches basic ComfyUI behaviour - don't use together with other samplers. Or perhaps do? Other samplers might profit from those changes ... ymmv.]" + }, + { + "author": "badjeff", + "title": "LoRA Tag Loader for ComfyUI", + "id": "lora-tag-loader", + "reference": "https://github.com/badjeff/comfyui_lora_tag_loader", + "files": [ + "https://github.com/badjeff/comfyui_lora_tag_loader" + ], + "install_type": "git-clone", + "description": "A ComfyUI custom node to read LoRA tag(s) from text and load it into checkpoint model." + }, + { + "author": "rgthree", + "title": "rgthree's ComfyUI Nodes", + "id": "rgthree", + "reference": "https://github.com/rgthree/rgthree-comfy", + "files": [ + "https://github.com/rgthree/rgthree-comfy" + ], + "nodename_pattern": " \\(rgthree\\)$", + "install_type": "git-clone", + "description": "Nodes: Seed, Reroute, Context, Lora Loader Stack, Context Switch, Fast Muter. These custom nodes helps organize the building of complex workflows." + }, + { + "author": "AIGODLIKE", + "title": "AIGODLIKE-COMFYUI-TRANSLATION", + "id": "translation", + "reference": "https://github.com/AIGODLIKE/AIGODLIKE-COMFYUI-TRANSLATION", + "files": [ + "https://github.com/AIGODLIKE/AIGODLIKE-COMFYUI-TRANSLATION" + ], + "install_type": "git-clone", + "description": "It provides language settings. (Contribution from users of various languages is needed due to the support for each language.)" + }, + { + "author": "AIGODLIKE", + "title": "AIGODLIKE-ComfyUI-Studio", + "id": "comfy-studio", + "reference": "https://github.com/AIGODLIKE/AIGODLIKE-ComfyUI-Studio", + "files": [ + "https://github.com/AIGODLIKE/AIGODLIKE-ComfyUI-Studio" + ], + "install_type": "git-clone", + "description": "Improve the interactive experience of using ComfyUI, such as making the loading of ComfyUI models more intuitive and making it easier to create model thumbnails" + }, + { + "author": "AIGODLIKE", + "title": "ComfyUI-CUP", + "id": "comfycup", + "reference": "https://github.com/AIGODLIKE/ComfyUI-CUP", + "files": [ + "https://github.com/AIGODLIKE/ComfyUI-CUP" + ], + "install_type": "git-clone", + "description": "Bridge between ComfyUI and blender's ComfyUI-BlenderAI-node addon." + }, + { + "author": "AIGODLIKE", + "title": "ComfyUI-ToonCrafter", + "id": "tooncrafter", + "reference": "https://github.com/AIGODLIKE/ComfyUI-ToonCrafter", + "files": [ + "https://github.com/AIGODLIKE/ComfyUI-ToonCrafter" + ], + "install_type": "git-clone", + "description": "This project is used to enable [a/ToonCrafter](https://github.com/ToonCrafter/ToonCrafter) to be used in ComfyUI.\nYou can use it to achieve generative keyframe animation\nAnd use it in Blender for animation rendering and prediction" + }, + { + "author": "syllebra", + "title": "BilboX's ComfyUI Custom Nodes", + "id": "bilbox", + "reference": "https://github.com/syllebra/bilbox-comfyui", + "files": [ + "https://github.com/syllebra/bilbox-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes: BilboX's PromptGeek Photo Prompt. This provides a convenient way to compose photorealistic prompts into ComfyUI." + }, + { + "author": "Girish Gopaul", + "title": "Save Image with Generation Metadata", + "id": "image-saver", + "reference": "https://github.com/giriss/comfy-image-saver", + "files": [ + "https://github.com/giriss/comfy-image-saver" + ], + "install_type": "git-clone", + "description": "All the tools you need to save images with their generation metadata on ComfyUI. Compatible with Civitai & Prompthero geninfo auto-detection. Works with png, jpeg and webp." + }, + { + "author": "shingo1228", + "title": "ComfyUI-send-Eagle(slim)", + "id": "send-eagle", + "reference": "https://github.com/shingo1228/ComfyUI-send-eagle-slim", + "files": [ + "https://github.com/shingo1228/ComfyUI-send-eagle-slim" + ], + "install_type": "git-clone", + "description": "Nodes:Send Webp Image to Eagle. This is an extension node for ComfyUI that allows you to send generated images in webp format to Eagle. This extension node is a re-implementation of the Eagle linkage functions of the previous ComfyUI-send-Eagle node, focusing on the functions required for this node." + }, + { + "author": "shingo1228", + "title": "ComfyUI-SDXL-EmptyLatentImage", + "id": "sdxl-emptylatent", + "reference": "https://github.com/shingo1228/ComfyUI-SDXL-EmptyLatentImage", + "files": [ + "https://github.com/shingo1228/ComfyUI-SDXL-EmptyLatentImage" + ], + "install_type": "git-clone", + "description": "Nodes:SDXL Empty Latent Image. An extension node for ComfyUI that allows you to select a resolution from the pre-defined json files and output a Latent Image." + }, + { + "author": "laksjdjf", + "title": "pfg-ComfyUI", + "id": "pfg", + "reference": "https://github.com/laksjdjf/pfg-ComfyUI", + "files": [ + "https://github.com/laksjdjf/pfg-ComfyUI" + ], + "install_type": "git-clone", + "description": "ComfyUI version of https://github.com/laksjdjf/pfg-webui. (To use this extension, you need to download the required model file from **Install Models**)" + }, + { + "author": "laksjdjf", + "title": "cgem156-ComfyUI🍌", + "id": "cgem156", + "reference": "https://github.com/laksjdjf/cgem156-ComfyUI", + "files": [ + "https://github.com/laksjdjf/cgem156-ComfyUI" + ], + "install_type": "git-clone", + "description": "The custom nodes of laksjdjf have been integrated into the node pack of cgem156🍌.\nNOTE:This includes the attention couple feature." + }, + { + "author": "laksjdjf", + "title": "cd-tuner_negpip-ComfyUI", + "id": "cdtuner", + "reference": "https://github.com/laksjdjf/cd-tuner_negpip-ComfyUI", + "files": [ + "https://github.com/laksjdjf/cd-tuner_negpip-ComfyUI" + ], + "install_type": "git-clone", + "description": "Nodes:Apply CDTuner, Apply Negapip. This extension provides the [a/CD(Color/Detail) Tuner](https://github.com/hako-mikan/sd-webui-cd-tuner) and the [a/Negative Prompt in the Prompt](https://github.com/hako-mikan/sd-webui-negpip) features." + }, + { + "author": "laksjdjf", + "title": "LCMSampler-ComfyUI", + "id": "lcm-sampler", + "reference": "https://github.com/laksjdjf/LCMSampler-ComfyUI", + "files": [ + "https://github.com/laksjdjf/LCMSampler-ComfyUI" + ], + "install_type": "git-clone", + "description": "This extension node is intended for the use of LCM conversion for SSD-1B-anime. It does not guarantee operation with the original LCM (as it cannot load weights in the current version). To take advantage of fast generation with LCM, a node for using TAESD as a decoder is also provided. This is inspired by ComfyUI-OtherVAEs." + }, + { + "author": "laksjdjf", + "title": "LoRTnoC-ComfyUI", + "id": "lortnoc", + "reference": "https://github.com/laksjdjf/LoRTnoC-ComfyUI", + "files": [ + "https://github.com/laksjdjf/LoRTnoC-ComfyUI" + ], + "install_type": "git-clone", + "description": "This is a repository for using LoRTnoC (LoRA with hint block of ControlNet) on ComfyUI.\nNOTE:Please place the model file in the same location as controlnet. (Is this too arbitrary?)" + }, + { + "author": "laksjdjf", + "title": "Batch-Condition-ComfyUI", + "id": "batch-condition", + "reference": "https://github.com/laksjdjf/Batch-Condition-ComfyUI", + "files": [ + "https://github.com/laksjdjf/Batch-Condition-ComfyUI" + ], + "install_type": "git-clone", + "description": "Nodes:CLIP Text Encode (Batch), String Input, Batch String" + }, + { + "author": "alsritter", + "title": "asymmetric-tiling-comfyui", + "id": "asymmetric", + "reference": "https://github.com/alsritter/asymmetric-tiling-comfyui", + "files": [ + "https://github.com/alsritter/asymmetric-tiling-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:Asymmetric_Tiling_KSampler. " + }, + { + "author": "meap158", + "title": "GPU temperature protection", + "id": "gputemp", + "reference": "https://github.com/meap158/ComfyUI-GPU-temperature-protection", + "files": [ + "https://github.com/meap158/ComfyUI-GPU-temperature-protection" + ], + "install_type": "git-clone", + "description": "Pause image generation when GPU temperature exceeds threshold." + }, + { + "author": "meap158", + "title": "ComfyUI-Prompt-Expansion", + "id": "promtp-expansion", + "reference": "https://github.com/meap158/ComfyUI-Prompt-Expansion", + "files": [ + "https://github.com/meap158/ComfyUI-Prompt-Expansion" + ], + "install_type": "git-clone", + "description": "Dynamic prompt expansion, powered by GPT-2 locally on your device." + }, + { + "author": "meap158", + "title": "ComfyUI-Background-Replacement", + "id": "bg-replacement", + "reference": "https://github.com/meap158/ComfyUI-Background-Replacement", + "files": [ + "https://github.com/meap158/ComfyUI-Background-Replacement" + ], + "install_type": "git-clone", + "description": "Instantly replace your image's background." + }, + { + "author": "TeaCrab", + "title": "ComfyUI-TeaNodes", + "id": "teanodes", + "reference": "https://github.com/TeaCrab/ComfyUI-TeaNodes", + "files": [ + "https://github.com/TeaCrab/ComfyUI-TeaNodes" + ], + "install_type": "git-clone", + "description": "Nodes:TC_EqualizeCLAHE, TC_SizeApproximation, TC_ImageResize, TC_ImageScale, TC_ColorFill." + }, + { + "author": "nagolinc", + "title": "ComfyUI_FastVAEDecorder_SDXL", + "reference": "https://github.com/nagolinc/ComfyUI_FastVAEDecorder_SDXL", + "files": [ + "https://github.com/nagolinc/ComfyUI_FastVAEDecorder_SDXL" + ], + "install_type": "git-clone", + "description": "Based off of: [a/Birch-san/diffusers-play/approx_vae](https://github.com/Birch-san/diffusers-play/tree/main/approx_vae). This ComfyUI node allows you to quickly preview SDXL 1.0 latents." + }, + { + "author": "nagolinc", + "title": "comfyui_openai_node", + "reference": "https://github.com/nagolinc/comfyui_openai_node", + "files": [ + "https://github.com/nagolinc/comfyui_openai_node" + ], + "install_type": "git-clone", + "description": "This provides a single node openai > Open AI query node\nthat takes a system prompt and user message and sends them to chatGPT 3.5\nNote, you MUST have an OPEN AI API key stored in the environment variable OPENAI_API_KEY in order for this to work." + }, + { + "author": "bradsec", + "title": "ResolutionSelector for ComfyUI", + "id": "resolution-selector", + "reference": "https://github.com/bradsec/ComfyUI_ResolutionSelector", + "files": [ + "https://github.com/bradsec/ComfyUI_ResolutionSelector" + ], + "install_type": "git-clone", + "description": "A custom node for Stable Diffusion ComfyUI to enable easy selection of image resolutions for SDXL SD15 SD21" + }, + { + "author": "bradsec", + "title": "ComfyUI_StringTools", + "id": "stringtools", + "reference": "https://github.com/bradsec/ComfyUI_StringTools", + "files": [ + "https://github.com/bradsec/ComfyUI_StringTools" + ], + "install_type": "git-clone", + "description": "Some simple string tools to modify text and strings in ComfyUI." + }, + { + "author": "kohya-ss", + "title": "ControlNet-LLLite-ComfyUI", + "id": "lllite", + "reference": "https://github.com/kohya-ss/ControlNet-LLLite-ComfyUI", + "files": [ + "https://github.com/kohya-ss/ControlNet-LLLite-ComfyUI" + ], + "install_type": "git-clone", + "description": "Nodes: LLLiteLoader" + }, + { + "author": "jjkramhoeft", + "title": "ComfyUI-Jjk-Nodes", + "id": "jjk", + "reference": "https://github.com/jjkramhoeft/ComfyUI-Jjk-Nodes", + "files": [ + "https://github.com/jjkramhoeft/ComfyUI-Jjk-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes: SDXLRecommendedImageSize, JjkText, JjkShowText, JjkConcat. A set of custom nodes for ComfyUI - focused on text and parameter utility" + }, + { + "author": "dagthomas", + "title": "SDXL Auto Prompter", + "id": "autoprompt", + "reference": "https://github.com/dagthomas/comfyui_dagthomas", + "files": [ + "https://github.com/dagthomas/comfyui_dagthomas" + ], + "install_type": "git-clone", + "description": "Easy prompting for generation of endless random art pieces and photographs!" + }, + { + "author": "marhensa", + "title": "Recommended Resolution Calculator", + "id": "resoultion-calc", + "reference": "https://github.com/marhensa/sdxl-recommended-res-calc", + "files": [ + "https://github.com/marhensa/sdxl-recommended-res-calc" + ], + "install_type": "git-clone", + "description": "Input your desired output final resolution, it will automaticaly set the initial recommended SDXL ratio/size and its Upscale Factor to reach that output final resolution, also there's an option for 2x/4x reverse Upscale Factor. These all to avoid using bad/arbitary initial ratio/resolution." + }, + { + "author": "Nuked", + "title": "ComfyUI-N-Nodes", + "id": "nnodes", + "reference": "https://github.com/Nuked88/ComfyUI-N-Nodes", + "files": [ + "https://github.com/Nuked88/ComfyUI-N-Nodes" + ], + "install_type": "git-clone", + "description": "A suite of custom nodes for ConfyUI that includes GPT text-prompt generation, LoadVideo,SaveVideo,LoadFramesFromFolder and FrameInterpolator" + }, + { + "author": "Nuked", + "title": "ComfyUI-N-Sidebar", + "id": "nsidebar", + "reference": "https://github.com/Nuked88/ComfyUI-N-Sidebar", + "files": [ + "https://github.com/Nuked88/ComfyUI-N-Sidebar" + ], + "install_type": "git-clone", + "description": "A simple sidebar for ComfyUI." + }, + { + "author": "richinsley", + "title": "Comfy-LFO", + "id": "lfo", + "reference": "https://github.com/richinsley/Comfy-LFO", + "files": [ + "https://github.com/richinsley/Comfy-LFO" + ], + "install_type": "git-clone", + "description": "Nodes:LFO_Triangle, LFO_Sine, SawtoothNode, SquareNode, PulseNode. ComfyUI custom nodes to create Low Frequency Oscillators." + }, + { + "author": "Beinsezii", + "title": "bsz-cui-extras", + "id": "bsz", + "reference": "https://github.com/Beinsezii/bsz-cui-extras", + "files": [ + "https://github.com/Beinsezii/bsz-cui-extras" + ], + "install_type": "git-clone", + "description": "This contains all-in-one 'principled' nodes for T2I, I2I, refining, and scaling. Additionally it has many tools for directly manipulating the color of latents, high res fix math, and scripted image post-processing." + }, + { + "author": "youyegit", + "title": "tdxh_node_comfyui", + "id": "tdxh", + "reference": "https://github.com/youyegit/tdxh_node_comfyui", + "files": [ + "https://github.com/youyegit/tdxh_node_comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:TdxhImageToSize, TdxhImageToSizeAdvanced, TdxhLoraLoader, TdxhIntInput, TdxhFloatInput, TdxhStringInput. Some nodes for stable diffusion comfyui. Sometimes it helps conveniently to use less nodes for doing the same things." + }, + { + "author": "Sxela", + "title": "ComfyWarp", + "id": "warp", + "reference": "https://github.com/Sxela/ComfyWarp", + "files": [ + "https://github.com/Sxela/ComfyWarp" + ], + "install_type": "git-clone", + "description": "Nodes:LoadFrameSequence, LoadFrame" + }, + { + "author": "skfoo", + "title": "ComfyUI-Coziness", + "id": "coziness", + "reference": "https://github.com/skfoo/ComfyUI-Coziness", + "files": [ + "https://github.com/skfoo/ComfyUI-Coziness" + ], + "install_type": "git-clone", + "description": "Nodes:MultiLora Loader, Lora Text Extractor. Provides a node for assisting in loading loras through text." + }, + { + "author": "YOUR-WORST-TACO", + "title": "ComfyUI-TacoNodes", + "id": "taco", + "reference": "https://github.com/YOUR-WORST-TACO/ComfyUI-TacoNodes", + "files": [ + "https://github.com/YOUR-WORST-TACO/ComfyUI-TacoNodes" + ], + "install_type": "git-clone", + "description": "Nodes:TacoLatent, TacoAnimatedLoader, TacoImg2ImgAnimatedLoader, TacoGifMaker." + }, + { + "author": "Lerc", + "title": "Canvas Tab", + "id": "canvastab", + "reference": "https://github.com/Lerc/canvas_tab", + "files": [ + "https://github.com/Lerc/canvas_tab" + ], + "install_type": "git-clone", + "description": "This extension provides a full page image editor with mask support. There are two nodes, one to receive images from the editor and one to send images to the editor." + }, + { + "author": "Ttl", + "title": "ComfyUI Neural Network Latent Upscale", + "id": "nnlatent", + "reference": "https://github.com/Ttl/ComfyUi_NNLatentUpscale", + "files": [ + "https://github.com/Ttl/ComfyUi_NNLatentUpscale" + ], + "install_type": "git-clone", + "preemptions": ["NNLatentUpscale"], + "description": "Nodes:NNLatentUpscale, A custom ComfyUI node designed for rapid latent upscaling using a compact neural network, eliminating the need for VAE-based decoding and encoding." + }, + { + "author": "spro", + "title": "Latent Mirror node for ComfyUI", + "id": "latentmirror", + "reference": "https://github.com/spro/comfyui-mirror", + "files": [ + "https://github.com/spro/comfyui-mirror" + ], + "install_type": "git-clone", + "description": "Nodes: Latent Mirror. Node to mirror a latent along the Y (vertical / left to right) or X (horizontal / top to bottom) axis." + }, + { + "author": "Tropfchen", + "title": "Embedding Picker", + "id": "embedding-picker", + "reference": "https://github.com/Tropfchen/ComfyUI-Embedding_Picker", + "files": [ + "https://github.com/Tropfchen/ComfyUI-Embedding_Picker" + ], + "install_type": "git-clone", + "description": "Tired of forgetting and misspelling often weird names of embeddings you use? Or perhaps you use only one, cause you forgot you have tens of them installed?" + }, + { + "author": "Acly", + "title": "ComfyUI Nodes for External Tooling", + "id": "external-tooling", + "reference": "https://github.com/Acly/comfyui-tooling-nodes", + "files": [ + "https://github.com/Acly/comfyui-tooling-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Load Image (Base64), Load Mask (Base64), Send Image (WebSocket), Crop Image, Apply Mask to Image. Provides nodes geared towards using ComfyUI as a backend for external tools.\nNOTE: This extension is necessary when using an external tool like [comfyui-capture-inference](https://github.com/minux302/comfyui-capture-inference)." + }, + { + "author": "Acly", + "title": "ComfyUI Inpaint Nodes", + "id": "inpaint-nodes", + "reference": "https://github.com/Acly/comfyui-inpaint-nodes", + "files": [ + "https://github.com/Acly/comfyui-inpaint-nodes" + ], + "install_type": "git-clone", + "description": "Experimental nodes for better inpainting with ComfyUI. Adds two nodes which allow using [a/Fooocus](https://github.com/Acly/comfyui-inpaint-nodes) inpaint model. It's a small and flexible patch which can be applied to any SDXL checkpoint and will transform it into an inpaint model. This model can then be used like other inpaint models, and provides the same benefits. [a/Read more](https://github.com/lllyasviel/Fooocus/discussions/414)" + }, + { + "author": "picturesonpictures", + "title": "comfy_PoP", + "id": "pop", + "reference": "https://github.com/picturesonpictures/comfy_PoP", + "files": ["https://github.com/picturesonpictures/comfy_PoP"], + "install_type": "git-clone", + "description": "A collection of custom nodes for ComfyUI. Includes a quick canny edge detection node with unconventional settings, simple LoRA stack nodes for workflow efficiency, and a customizable aspect ratio node." + }, + { + "author": "Dream Project", + "title": "Dream Project Animation Nodes", + "id": "dream-anime", + "reference": "https://github.com/alt-key-project/comfyui-dream-project", + "files": [ + "https://github.com/alt-key-project/comfyui-dream-project" + ], + "install_type": "git-clone", + "description": "This extension offers various nodes that are useful for Deforum-like animations in ComfyUI." + }, + { + "author": "Dream Project", + "title": "Dream Video Batches", + "id": "dream-video", + "reference": "https://github.com/alt-key-project/comfyui-dream-video-batches", + "files": [ + "https://github.com/alt-key-project/comfyui-dream-video-batches" + ], + "install_type": "git-clone", + "description": "Provide utilities for batch based video generation workflows (s.a. AnimateDiff and Stable Video Diffusion)." + }, + { + "author": "seanlynch", + "title": "ComfyUI Optical Flow", + "id": "optical-flow", + "reference": "https://github.com/seanlynch/comfyui-optical-flow", + "files": [ + "https://github.com/seanlynch/comfyui-optical-flow" + ], + "install_type": "git-clone", + "description": "This package contains three nodes to help you compute optical flow between pairs of images, usually adjacent frames in a video, visualize the flow, and apply the flow to another image of the same dimensions. Most of the code is from Deforum, so this is released under the same license (MIT)." + }, + { + "author": "ealkanat", + "title": "ComfyUI Easy Padding", + "id": "easy-padding", + "reference": "https://github.com/ealkanat/comfyui_easy_padding", + "files": [ + "https://github.com/ealkanat/comfyui_easy_padding" + ], + "install_type": "git-clone", + "description": "ComfyUI Easy Padding is a simple custom ComfyUI node that helps you to add padding to images on ComfyUI." + }, + { + "author": "ArtBot2023", + "title": "Character Face Swap", + "id": "char-faceswap", + "reference": "https://github.com/ArtBot2023/CharacterFaceSwap", + "files": [ + "https://github.com/ArtBot2023/CharacterFaceSwap" + ], + "install_type": "git-clone", + "description": "Character face swap with LoRA and embeddings." + }, + { + "author": "mav-rik", + "title": "Facerestore CF (Code Former)", + "id": "face-cf", + "reference": "https://github.com/mav-rik/facerestore_cf", + "files": [ + "https://github.com/mav-rik/facerestore_cf" + ], + "install_type": "git-clone", + "description": "This is a copy of [a/facerestore custom node](https://civitai.com/models/24690/comfyui-facerestore-node) with a bit of a change to support CodeFormer Fidelity parameter. These ComfyUI nodes can be used to restore faces in images similar to the face restore option in AUTOMATIC1111 webui.\nNOTE: To use this node, you need to download the face restoration model and face detection model from the 'Install models' menu." + }, + { + "author": "braintacles", + "title": "braintacles-nodes", + "id": "braintacles", + "reference": "https://github.com/braintacles/braintacles-comfyui-nodes", + "files": [ + "https://github.com/braintacles/braintacles-comfyui-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: CLIPTextEncodeSDXL-Multi-IO, CLIPTextEncodeSDXL-Pipe, Empty Latent Image from Aspect-Ratio, Random Find and Replace." + }, + { + "author": "hayden-fr", + "title": "ComfyUI-Model-Manager", + "id": "modelmanager", + "reference": "https://github.com/hayden-fr/ComfyUI-Model-Manager", + "files": [ + "https://github.com/hayden-fr/ComfyUI-Model-Manager" + ], + "install_type": "git-clone", + "description": "Manage models: browsing, download and delete." + }, + { + "author": "hayden-fr", + "title": "ComfyUI-Image-Browsing", + "id": "image-browsing", + "reference": "https://github.com/hayden-fr/ComfyUI-Image-Browsing", + "files": [ + "https://github.com/hayden-fr/ComfyUI-Image-Browsing" + ], + "install_type": "git-clone", + "description": "Image Browsing: browsing, download and delete." + }, + { + "author": "ali1234", + "title": "comfyui-job-iterator", + "id": "job-iterator", + "reference": "https://github.com/ali1234/comfyui-job-iterator", + "files": [ + "https://github.com/ali1234/comfyui-job-iterator" + ], + "install_type": "git-clone", + "description": "Implements iteration over sequences within a single workflow run. [w/NOTE: This node replaces the execution of ComfyUI for iterative processing functionality.]" + }, + { + "author": "jmkl", + "title": "ComfyUI Ricing", + "id": "ricing", + "reference": "https://github.com/jmkl/ComfyUI-ricing", + "files": [ + "https://github.com/jmkl/ComfyUI-ricing" + ], + "install_type": "git-clone", + "description": "ComfyUI custom user.css and some script stuff. mainly for web interface." + }, + { + "author": "budihartono", + "title": "Otonx's Custom Nodes", + "id": "otonx", + "reference": "https://github.com/budihartono/comfyui_otonx_nodes", + "files": [ + "https://github.com/budihartono/comfyui_otonx_nodes" + ], + "install_type": "git-clone", + "description": "Nodes: OTX Multiple Values, OTX KSampler Feeder. This extension provides custom nodes for ComfyUI created for personal projects. Made available for reference. Nodes may be updated or changed intermittently or not at all. Review & test before use." + }, + { + "author": "ramyma", + "title": "A8R8 ComfyUI Nodes", + "id": "a8r8", + "reference": "https://github.com/ramyma/A8R8_ComfyUI_nodes", + "files": [ + "https://github.com/ramyma/A8R8_ComfyUI_nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Base64Image Input Node, Base64Image Output Node. [a/A8R8](https://github.com/ramyma/a8r8) supporting nodes to integrate with ComfyUI" + }, + { + "author": "spinagon", + "title": "Seamless tiling Node for ComfyUI", + "id": "seamless", + "reference": "https://github.com/spinagon/ComfyUI-seamless-tiling", + "files": [ + "https://github.com/spinagon/ComfyUI-seamless-tiling" + ], + "install_type": "git-clone", + "description": "Node for generating almost seamless textures, based on similar setting from A1111." + }, + { + "author": "BiffMunky", + "title": "Endless ️🌊✨ Nodes", + "id": "endless", + "reference": "https://github.com/tusharbhutt/Endless-Nodes", + "files": [ + "https://github.com/tusharbhutt/Endless-Nodes" + ], + "install_type": "git-clone", + "description": "A small set of nodes I created for various numerical and text inputs. Features image saver with ability to have JSON saved to separate folder, parameter collection nodes, two aesthetic scoring models, switches for text and numbers, and conversion of string to numeric and vice versa." + }, + { + "author": "spacepxl", + "title": "ComfyUI-HQ-Image-Save", + "id": "hq-image-save", + "reference": "https://github.com/spacepxl/ComfyUI-HQ-Image-Save", + "files": [ + "https://github.com/spacepxl/ComfyUI-HQ-Image-Save" + ], + "install_type": "git-clone", + "description": "Add Image Save nodes for TIFF 16 bit and EXR 32 bit formats. Probably only useful if you're applying a LUT or other color corrections, and care about preserving as much color accuracy as possible." + }, + { + "author": "spacepxl", + "title": "ComfyUI-Image-Filters", + "id": "image-fitlers", + "reference": "https://github.com/spacepxl/ComfyUI-Image-Filters", + "files": [ + "https://github.com/spacepxl/ComfyUI-Image-Filters" + ], + "install_type": "git-clone", + "description": "Image and matte filtering nodes for ComfyUI `image/filters/*`" + }, + { + "author": "spacepxl", + "title": "ComfyUI-RAVE", + "id": "rave", + "reference": "https://github.com/spacepxl/ComfyUI-RAVE", + "files": [ + "https://github.com/spacepxl/ComfyUI-RAVE" + ], + "install_type": "git-clone", + "description": "Unofficial ComfyUI implementation of [a/RAVE](https://rave-video.github.io/)" + }, + { + "author": "spacepxl", + "title": "ComfyUI-StyleGan", + "id": "stylegan", + "reference": "https://github.com/spacepxl/ComfyUI-StyleGan", + "files": [ + "https://github.com/spacepxl/ComfyUI-StyleGan" + ], + "install_type": "git-clone", + "description": "Basic support for StyleGAN2 and StyleGAN3 models." + }, + { + "author": "spacepxl", + "title": "ComfyUI-Florence-2", + "id": "florence2-spacepxl", + "reference": "https://github.com/spacepxl/ComfyUI-Florence-2", + "files": [ + "https://github.com/spacepxl/ComfyUI-Florence-2" + ], + "install_type": "git-clone", + "description": "[a/https://huggingface.co/microsoft/Florence-2-large-ft](https://huggingface.co/microsoft/Florence-2-large-ft)\nLarge or base model, support for captioning and bbox task modes, more coming soon." + }, + { + "author": "PTA", + "title": "auto nodes layout", + "id": "autolayout", + "reference": "https://github.com/phineas-pta/comfyui-auto-nodes-layout", + "files": [ + "https://github.com/phineas-pta/comfyui-auto-nodes-layout" + ], + "install_type": "git-clone", + "description": "A ComfyUI extension to apply better nodes layout algorithm to ComfyUI workflow (mostly for visualization purpose)" + }, + { + "author": "receyuki", + "title": "SD Prompt Reader", + "id": "sdpromptreader", + "reference": "https://github.com/receyuki/comfyui-prompt-reader-node", + "files": [ + "https://github.com/receyuki/comfyui-prompt-reader-node" + ], + "install_type": "git-clone", + "description": "The ultimate solution for managing image metadata and multi-tool compatibility. ComfyUI node version of the SD Prompt Reader." + }, + { + "author": "rklaffehn", + "title": "rk-comfy-nodes", + "id": "rknodes", + "reference": "https://github.com/rklaffehn/rk-comfy-nodes", + "files": [ + "https://github.com/rklaffehn/rk-comfy-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: RK_CivitAIMetaChecker, RK_CivitAIAddHashes." + }, + { + "author": "cubiq", + "title": "ComfyUI Essentials", + "id": "essentials", + "reference": "https://github.com/cubiq/ComfyUI_essentials", + "files": [ + "https://github.com/cubiq/ComfyUI_essentials" + ], + "install_type": "git-clone", + "description": "Essential nodes that are weirdly missing from ComfyUI core. With few exceptions they are new features and not commodities. I hope this will be just a temporary repository until the nodes get included into ComfyUI." + }, + { + "author": "Clybius", + "title": "ComfyUI-Latent-Modifiers", + "id": "latent-modifier", + "reference": "https://github.com/Clybius/ComfyUI-Latent-Modifiers", + "files": [ + "https://github.com/Clybius/ComfyUI-Latent-Modifiers" + ], + "install_type": "git-clone", + "description": "Nodes: Latent Diffusion Mega Modifier. ComfyUI nodes which modify the latent during the diffusion process. (Sharpness, Tonemap, Rescale, Extra Noise)" + }, + { + "author": "Clybius", + "title": "ComfyUI Extra Samplers", + "id": "extra-samplers", + "reference": "https://github.com/Clybius/ComfyUI-Extra-Samplers", + "files": [ + "https://github.com/Clybius/ComfyUI-Extra-Samplers" + ], + "install_type": "git-clone", + "description": "Nodes: SamplerCustomNoise, SamplerCustomNoiseDuo, SamplerCustomModelMixtureDuo, SamplerRES_Momentumized, SamplerDPMPP_DualSDE_Momentumized, SamplerCLYB_4M_SDE_Momentumized, SamplerTTM, SamplerLCMCustom\nThis extension provides various custom samplers not offered by the default nodes in ComfyUI." + }, + { + "author": "mcmonkeyprojects", + "title": "Stable Diffusion Dynamic Thresholding (CFG Scale Fix)", + "id": "dynamic-thresholding", + "reference": "https://github.com/mcmonkeyprojects/sd-dynamic-thresholding", + "files": [ + "https://github.com/mcmonkeyprojects/sd-dynamic-thresholding" + ], + "install_type": "git-clone", + "description": "Extension for StableSwarmUI, ComfyUI, and AUTOMATIC1111 Stable Diffusion WebUI that enables a way to use higher CFG Scales without color issues. This works by clamping latents between steps." + }, + { + "author": "Tropfchen", + "title": "YARS: Yet Another Resolution Selector", + "id": "yars", + "reference": "https://github.com/Tropfchen/ComfyUI-yaResolutionSelector", + "files": [ + "https://github.com/Tropfchen/ComfyUI-yaResolutionSelector" + ], + "install_type": "git-clone", + "description": "A slightly different Resolution Selector node, allowing to freely change base resolution and aspect ratio, with options to maintain the pixel count or use the base resolution as the highest or lowest dimension." + }, + { + "author": "chrisgoringe", + "title": "Variation seeds", + "id": "variation-seed", + "reference": "https://github.com/chrisgoringe/cg-noise", + "files": [ + "https://github.com/chrisgoringe/cg-noise" + ], + "install_type": "git-clone", + "description": "Adds KSampler custom nodes with variation seed and variation strength." + }, + { + "author": "chrisgoringe", + "title": "Image chooser", + "id": "image-chooser", + "reference": "https://github.com/chrisgoringe/cg-image-picker", + "files": [ + "https://github.com/chrisgoringe/cg-image-picker" + ], + "install_type": "git-clone", + "description": "A custom node that pauses the flow while you choose which image (or latent) to pass on to the rest of the workflow." + }, + { + "author": "chrisgoringe", + "title": "Use Everywhere (UE Nodes)", + "id": "ue", + "reference": "https://github.com/chrisgoringe/cg-use-everywhere", + "files": [ + "https://github.com/chrisgoringe/cg-use-everywhere" + ], + "install_type": "git-clone", + "nodename_pattern": "(^(Prompts|Anything) Everywhere|Simple String)", + "description": "A set of nodes that allow data to be 'broadcast' to some or all unconnected inputs. Greatly reduces link spaghetti." + }, + { + "author": "chrisgoringe", + "title": "Prompt Info", + "id": "promptinfo", + "reference": "https://github.com/chrisgoringe/cg-prompt-info", + "files": [ + "https://github.com/chrisgoringe/cg-prompt-info" + ], + "install_type": "git-clone", + "description": "Prompt Info" + }, + { + "author": "TGu-97", + "title": "TGu Utilities", + "id": "tgu", + "reference": "https://github.com/TGu-97/ComfyUI-TGu-utils", + "files": [ + "https://github.com/TGu-97/ComfyUI-TGu-utils" + ], + "install_type": "git-clone", + "description": "Nodes: MPN Switch, MPN Reroute, PN Switch. This is a set of custom nodes for ComfyUI. Mainly focus on control switches." + }, + { + "author": "seanlynch", + "title": "SRL's nodes", + "id": "srl", + "reference": "https://github.com/seanlynch/srl-nodes", + "files": [ + "https://github.com/seanlynch/srl-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: SRL Conditional Interrupt, SRL Format String, SRL Eval, SRL Filter Image List. This is a collection of nodes I find useful. Note that at least one module allows execution of arbitrary code. Do not use any of these nodes on a system that allow untrusted users to control workflows or inputs.[w/WARNING: The custom nodes in this extension are vulnerable to **security risks** because they allow the execution of arbitrary code through the workflow]" + }, + { + "author": "alpertunga-bile", + "title": "prompt-generator", + "reference": "https://github.com/alpertunga-bile/prompt-generator-comfyui", + "files": [ + "https://github.com/alpertunga-bile/prompt-generator-comfyui" + ], + "install_type": "git-clone", + "description": "Custom AI prompt generator node for ComfyUI." + }, + { + "author": "kijai", + "title": "KJNodes for ComfyUI", + "id": "kjnodes", + "reference": "https://github.com/kijai/ComfyUI-KJNodes", + "files": [ + "https://github.com/kijai/ComfyUI-KJNodes" + ], + "install_type": "git-clone", + "description": "Various quality of life -nodes for ComfyUI, mostly just visual stuff to improve usability." + }, + { + "author": "kijai", + "title": "ComfyUI-CCSR", + "id": "ccsr", + "reference": "https://github.com/kijai/ComfyUI-CCSR", + "files": [ + "https://github.com/kijai/ComfyUI-CCSR" + ], + "install_type": "git-clone", + "description": "ComfyUI- CCSR upscaler node" + }, + { + "author": "kijai", + "title": "ComfyUI-SVD", + "id": "kijai-svd", + "reference": "https://github.com/kijai/ComfyUI-SVD", + "files": [ + "https://github.com/kijai/ComfyUI-SVD" + ], + "install_type": "git-clone", + "description": "Preliminary use of SVD in ComfyUI.\nNOTE: Quick Implementation, Unstable. See details on repositories." + }, + { + "author": "kijai", + "title": "Marigold depth estimation in ComfyUI", + "id": "marigold", + "reference": "https://github.com/kijai/ComfyUI-Marigold", + "files": [ + "https://github.com/kijai/ComfyUI-Marigold" + ], + "install_type": "git-clone", + "description": "This is a wrapper node for Marigold depth estimation: [https://github.com/prs-eth/Marigold](https://github.com/kijai/ComfyUI-Marigold). Currently using the same diffusers pipeline as in the original implementation, so in addition to the custom node, you need the model in diffusers format.\nNOTE: See details in repo to install." + }, + { + "author": "kijai", + "title": "Geowizard depth and normal estimation in ComfyUI", + "id": "geowizard", + "reference": "https://github.com/kijai/ComfyUI-Geowizard", + "files": [ + "https://github.com/kijai/ComfyUI-Geowizard" + ], + "install_type": "git-clone", + "description": "This is a diffusers (0.27.2) wrapper node for Geowizard: [https://github.com/fuxiao0719/GeoWizard]. The model is autodownloaded from Hugginface to ComfyUI/models/diffusers/geowizard" + }, + { + "author": "kijai", + "title": "ComfyUI-depth-fm", + "id": "depth-fm", + "reference": "https://github.com/kijai/ComfyUI-depth-fm", + "files": [ + "https://github.com/kijai/ComfyUI-depth-fm" + ], + "install_type": "git-clone", + "description": "Fast and accurate monocular depth estimation." + }, + { + "author": "kijai", + "title": "ComfyUI-DDColor", + "id": "ddcolor-kijai", + "reference": "https://github.com/kijai/ComfyUI-DDColor", + "files": [ + "https://github.com/kijai/ComfyUI-DDColor" + ], + "install_type": "git-clone", + "description": "Node to use [a/DDColor](https://github.com/piddnad/DDColor) in ComfyUI." + }, + { + "author": "kijai", + "title": "Animatediff MotionLoRA Trainer", + "id": "motionlora-trainer", + "reference": "https://github.com/kijai/ComfyUI-ADMotionDirector", + "files": [ + "https://github.com/kijai/ComfyUI-ADMotionDirector" + ], + "install_type": "git-clone", + "description": "This is a trainer for AnimateDiff MotionLoRAs, based on the implementation of MotionDirector by ExponentialML.\nNOTE:[a/ADMotionDirector](https://github.com/ExponentialML/AnimateDiff-MotionDirector)" + }, + { + "author": "kijai", + "title": "ComfyUI-moondream", + "id": "moondream", + "reference": "https://github.com/kijai/ComfyUI-moondream", + "files": [ + "https://github.com/kijai/ComfyUI-moondream" + ], + "install_type": "git-clone", + "description": "Moondream image to text query node with batch support" + }, + { + "author": "kijai", + "title": "ComfyUI-SUPIR", + "id": "supir", + "reference": "https://github.com/kijai/ComfyUI-SUPIR", + "files": [ + "https://github.com/kijai/ComfyUI-SUPIR" + ], + "install_type": "git-clone", + "description": "Wrapper nodes to use SUPIR upscaling process in ComfyUI" + }, + { + "author": "kijai", + "title": "ComfyUI-DynamiCrafterWrapper", + "id": "dynamicrafter-kijai", + "reference": "https://github.com/kijai/ComfyUI-DynamiCrafterWrapper", + "files": [ + "https://github.com/kijai/ComfyUI-DynamiCrafterWrapper" + ], + "install_type": "git-clone", + "description": "Wrapper nodes to use DynamiCrafter image2video and frame interpolation models in ComfyUI\nAnd this extension supports ToonCrafter as well" + }, + { + "author": "kijai", + "title": "ComfyUI-APISR", + "id": "apisr", + "reference": "https://github.com/kijai/ComfyUI-APISR-KJ", + "files": [ + "https://github.com/kijai/ComfyUI-APISR-KJ" + ], + "install_type": "git-clone", + "description": "Node to use [a/APISR](https://github.com/Kiteretsu77/APISR) upscale models in ComfyUI.[w/NOTE: repo name is changed from ComfyUI-APISR -> ComfyUI-APISR-KJ]" + }, + { + "author": "kijai", + "title": "DiffusionLight implementation for ComfyUI", + "id": "diffusionlight", + "reference": "https://github.com/kijai/ComfyUI-DiffusionLight", + "files": [ + "https://github.com/kijai/ComfyUI-DiffusionLight" + ], + "install_type": "git-clone", + "description": "This is simplified implementation of the [a/DiffusionLight](https://github.com/DiffusionLight/DiffusionLight) method of creating light probes. You will need the included LoRA, place it in ComfyUI/loras folder like usual, it's converted from the original diffusers one." + }, + { + "author": "kijai", + "title": "ComfyUI-ELLA-wrapper", + "reference": "https://github.com/kijai/ComfyUI-ELLA-wrapper", + "files": [ + "https://github.com/kijai/ComfyUI-ELLA-wrapper" + ], + "install_type": "git-clone", + "description": "ComfyUI wrapper nodes to use the Diffusers implementation of ELLA" + }, + { + "author": "kijai", + "title": "ComfyUI-LaVi-Bridge-Wrapper", + "reference": "https://github.com/kijai/ComfyUI-LaVi-Bridge-Wrapper", + "files": [ + "https://github.com/kijai/ComfyUI-LaVi-Bridge-Wrapper" + ], + "install_type": "git-clone", + "description": "ComfyUI wrapper node to test LaVi-Bridge using Diffusers" + }, + { + "author": "kijai", + "title": "ComfyUI-BrushNet-Wrapper", + "reference": "https://github.com/kijai/ComfyUI-BrushNet-Wrapper", + "files": [ + "https://github.com/kijai/ComfyUI-BrushNet-Wrapper" + ], + "install_type": "git-clone", + "description": "ComfyUI wrapper nodes to use the Diffusers implementation of BrushNet" + }, + { + "author": "kijai", + "title": "ComfyUI-IC-Light", + "id": "ic-light-kijai", + "reference": "https://github.com/kijai/ComfyUI-IC-Light", + "files": [ + "https://github.com/kijai/ComfyUI-IC-Light" + ], + "install_type": "git-clone", + "description": "ComfyUI native nodes for IC-Light" + }, + { + "author": "kijai", + "title": "ComfyUI-DepthAnythingV2", + "id": "depth-anything-v2", + "reference": "https://github.com/kijai/ComfyUI-DepthAnythingV2", + "files": [ + "https://github.com/kijai/ComfyUI-DepthAnythingV2" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes to use [a/DepthAnythingV2](https://depth-anything-v2.github.io/)\nNOTE:Models autodownload to ComfyUI/models/depthanything from [a/https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main](https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main)" + }, + { + "author": "kijai", + "title": "ComfyUI-Florence2", + "id": "florence2-kijai", + "reference": "https://github.com/kijai/ComfyUI-Florence2", + "files": [ + "https://github.com/kijai/ComfyUI-Florence2" + ], + "install_type": "git-clone", + "description": "Nodes to use Florence2 VLM for image vision tasks: object detection, captioning, segmentation and ocr" + }, + { + "author": "kijai", + "title": "ComfyUI-LuminaWrapper", + "id": "lumina", + "reference": "https://github.com/kijai/ComfyUI-LuminaWrapper", + "files": [ + "https://github.com/kijai/ComfyUI-LuminaWrapper" + ], + "install_type": "git-clone", + "description": "ComfyUI wrapper nodes for Lumina models" + }, + { + "author": "kijai", + "title": "ComfyUI-MimicMotionWrapper", + "id": "mimicmotion-kijai", + "reference": "https://github.com/kijai/ComfyUI-MimicMotionWrapper", + "files": [ + "https://github.com/kijai/ComfyUI-MimicMotionWrapper" + ], + "install_type": "git-clone", + "description": "Optimized wrapper nodes for MimicMotion: [a/https://github.com/tencent/MimicMotion](https://github.com/tencent/MimicMotion)" + }, + { + "author": "kijai", + "title": "ComfyUI-OpenDiTWrapper", + "id": "opendit-kijai", + "reference": "https://github.com/kijai/ComfyUI-OpenDiTWrapper", + "files": [ + "https://github.com/kijai/ComfyUI-OpenDiTWrapper" + ], + "install_type": "git-clone", + "description": "Wrapper nodes for OpenDiT: [a/OpenDiT](https://github.com/NUS-HPC-AI-Lab/OpenDiT/), supports Open-Sora t2i and i2i" + }, + { + "author": "kijai", + "title": "ComfyUI-LivePortraitKJ", + "id": "liveportrait-kijai", + "reference": "https://github.com/kijai/ComfyUI-LivePortraitKJ", + "files": [ + "https://github.com/kijai/ComfyUI-LivePortraitKJ" + ], + "install_type": "git-clone", + "description": "Nodes for [a/LivePortrait](https://github.com/KwaiVGI/LivePortrait), insightface is required" + }, + { + "author": "kijai", + "title": "ComfyUI-KwaiKolorsWrapper", + "id": "kwaikolors", + "reference": "https://github.com/kijai/ComfyUI-KwaiKolorsWrapper", + "files": [ + "https://github.com/kijai/ComfyUI-KwaiKolorsWrapper" + ], + "install_type": "git-clone", + "description": "Rudimentary wrapper that runs [a/Kwai-Kolors](https://huggingface.co/Kwai-Kolors/Kolors) text2image pipeline using diffusers." + }, + { + "author": "hhhzzyang", + "title": "Comfyui-Lama", + "id": "lama", + "reference": "https://github.com/hhhzzyang/Comfyui_Lama", + "files": [ + "https://github.com/hhhzzyang/Comfyui_Lama" + ], + "install_type": "git-clone", + "description": "Nodes: LamaaModelLoad, LamaApply, YamlConfigLoader. a costumer node is realized to remove anything/inpainting anything from a picture by mask inpainting.[w/WARN:This extension includes the entire model, which can result in a very long initial installation time, and there may be some compatibility issues with older dependencies and ComfyUI.]" + }, + { + "author": "audioscavenger", + "title": "Save Image Extended for ComfyUI", + "id": "save-image-extended", + "reference": "https://github.com/audioscavenger/save-image-extended-comfyui", + "files": [ + "https://github.com/audioscavenger/save-image-extended-comfyui" + ], + "install_type": "git-clone", + "description": "Upgrade the Save File node: customize subfolders, file names with checkpoint names, or any sampler attribute your want! [w/NOTE: This node is a fork from @thedyze, since the [a/original repository](https://github.com/thedyze/save-image-extended-comfyui) is no longer maintained. Simply *uninstall* the original version and **REINSTALL** this one.]" + }, + { + "author": "SOELexicon", + "title": "ComfyUI-LexTools", + "id": "lextools", + "reference": "https://github.com/SOELexicon/ComfyUI-LexTools", + "files": [ + "https://github.com/SOELexicon/ComfyUI-LexTools" + ], + "install_type": "git-clone", + "description": "ComfyUI-LexTools is a Python-based image processing and analysis toolkit that uses machine learning models for semantic image segmentation, image scoring, and image captioning." + }, + { + "author": "mikkel", + "title": "ComfyUI - Text Overlay Plugin", + "id": "textoverlay-mikkel", + "reference": "https://github.com/mikkel/ComfyUI-text-overlay", + "files": [ + "https://github.com/mikkel/ComfyUI-text-overlay" + ], + "install_type": "git-clone", + "description": "The ComfyUI Text Overlay Plugin provides functionalities for superimposing text on images. Users can select different font types, set text size, choose color, and adjust the text's position on the image." + }, + { + "author": "avatechai", + "title": "Avatar Graph", + "id": "avatar-graph", + "reference": "https://github.com/avatechai/avatar-graph-comfyui", + "files": [ + "https://github.com/avatechai/avatar-graph-comfyui" + ], + "install_type": "git-clone", + "description": "Include nodes for sam + bpy operation, that allows workflow creations for generative 2d character rig." + }, + { + "author": "TRI3D-LC", + "title": "tri3d-comfyui-nodes", + "id": "tri3d", + "reference": "https://github.com/TRI3D-LC/tri3d-comfyui-nodes", + "files": [ + "https://github.com/TRI3D-LC/tri3d-comfyui-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: tri3d-extract-hand, tri3d-fuzzification, tri3d-position-hands, tri3d-atr-parse." + }, + { + "author": "TRI3D-LC", + "title": "ComfyUI-MiroBoard", + "id": "miroboard", + "reference": "https://github.com/TRI3D-LC/ComfyUI-MiroBoard", + "files": [ + "https://github.com/TRI3D-LC/ComfyUI-MiroBoard" + ], + "install_type": "git-clone", + "description": "Nodes: add-image-miro-board." + }, + { + "author": "storyicon", + "title": "segment anything", + "id": "sam", + "reference": "https://github.com/storyicon/comfyui_segment_anything", + "files": [ + "https://github.com/storyicon/comfyui_segment_anything" + ], + "install_type": "git-clone", + "description": "Based on GroundingDino and SAM, use semantic strings to segment any element in an image. The comfyui version of sd-webui-segment-anything." + }, + { + "author": "storyicon", + "title": "ComfyUI MuseV Evolved", + "id": "musev-evolved", + "reference": "https://github.com/storyicon/comfyui_musev_evolved", + "files": [ + "https://github.com/storyicon/comfyui_musev_evolved" + ], + "install_type": "git-clone", + "description": "Nodes:MuseVImg2Vid (comfyui_musev_evolved)\nNOTE: Download [a/MuseV](https://huggingface.co/TMElyralab/MuseV) to ComfyUI/models/diffusers" + }, + { + "author": "a1lazydog", + "title": "ComfyUI-AudioScheduler", + "id": "audioscheduler", + "reference": "https://github.com/a1lazydog/ComfyUI-AudioScheduler", + "files": [ + "https://github.com/a1lazydog/ComfyUI-AudioScheduler" + ], + "install_type": "git-clone", + "description": "Load mp3 files and use the audio nodes to power animations and prompt scheduling. Use with FizzNodes." + }, + { + "author": "whatbirdisthat", + "title": "cyberdolphin", + "reference": "https://github.com/whatbirdisthat/cyberdolphin", + "files": [ + "https://github.com/whatbirdisthat/cyberdolphin" + ], + "install_type": "git-clone", + "description": "Cyberdolphin Suite of ComfyUI nodes for wiring up things." + }, + { + "author": "chrish-slingshot", + "title": "CrasH Utils", + "id": "crash", + "reference": "https://github.com/chrish-slingshot/CrasHUtils", + "files": [ + "https://github.com/chrish-slingshot/CrasHUtils" + ], + "install_type": "git-clone", + "description": "A mixture of effects and quality of life nodes. Nodes: ImageGlitcher (gives an image a cool glitchy effect), ColorStylizer (highlights a single color in an image), QueryLocalLLM (queries a local LLM API though oobabooga), SDXLReslution (resolution picker for the standard SDXL resolutions, the complete list), SDXLResolutionSplit (splits the SDXL resolution into width and height). " + }, + { + "author": "spinagon", + "title": "ComfyUI-seam-carving", + "id": "seamcarving", + "reference": "https://github.com/spinagon/ComfyUI-seam-carving", + "files": [ + "https://github.com/spinagon/ComfyUI-seam-carving" + ], + "install_type": "git-clone", + "description": "Nodes: Image Resize (seam carving). Seam carving (image resize) for ComfyUI. Based on [a/https://github.com/li-plus/seam-carving](https://github.com/li-plus/seam-carving). With seam carving algorithm, the image could be intelligently resized while keeping the important contents undistorted. The carving process could be further guided, so that an object could be removed from the image without apparent artifacts." + }, + { + "author": "YMC", + "title": "ymc-node-suite-comfyui", + "id": "ymc", + "reference": "https://github.com/YMC-GitHub/ymc-node-suite-comfyui", + "files": [ + "https://github.com/YMC-GitHub/ymc-node-suite-comfyui" + ], + "install_type": "git-clone", + "description": "ymc 's nodes for comfyui. This extension is composed of nodes that provide various utility features such as text, region, and I/O." + }, + { + "author": "chibiace", + "title": "ComfyUI-Chibi-Nodes", + "id": "chibi", + "reference": "https://github.com/chibiace/ComfyUI-Chibi-Nodes", + "files": [ + "https://github.com/chibiace/ComfyUI-Chibi-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Loader, Prompts, ImageTool, Wildcards, LoadEmbedding, ConditionText, SaveImages, ..." + }, + { + "author": "DigitalIO", + "title": "ComfyUI-stable-wildcards", + "id": "stable-wildcards", + "reference": "https://github.com/DigitalIO/ComfyUI-stable-wildcards", + "files": [ + "https://github.com/DigitalIO/ComfyUI-stable-wildcards" + ], + "install_type": "git-clone", + "description": "Wildcard implementation that can be reproduced with workflows." + }, + { + "author": "THtianhao", + "title": "ComfyUI-Portrait-Maker", + "id": "portrait-maker", + "reference": "https://github.com/THtianhao/ComfyUI-Portrait-Maker", + "files": [ + "https://github.com/THtianhao/ComfyUI-Portrait-Maker" + ], + "install_type": "git-clone", + "description": "Nodes:RetainFace, FaceFusion, RatioMerge2Image, MaskMerge2Image, ReplaceBoxImg, ExpandMaskBox, FaceSkin, SkinRetouching, PortraitEnhancement, ..." + }, + { + "author": "THtianhao", + "title": "ComfyUI-FaceChain", + "id": "facechain", + "reference": "https://github.com/THtianhao/ComfyUI-FaceChain", + "files": [ + "https://github.com/THtianhao/ComfyUI-FaceChain" + ], + "install_type": "git-clone", + "description": "The official ComfyUI version of facechain greatly improves the speed of reasoning and has great custom process controls." + }, + { + "author": "zer0TF", + "title": "Cute Comfy", + "id": "cutecomfy", + "reference": "https://github.com/zer0TF/cute-comfy", + "files": [ + "https://github.com/zer0TF/cute-comfy" + ], + "install_type": "git-clone", + "description": "Adds a configurable folder watcher that auto-converts Comfy metadata into a Civitai-friendly format for automatic resource tagging when you upload images. Oh, and it makes your UI awesome, too. 💜" + }, + { + "author": "chflame163", + "title": "ComfyUI_MSSpeech_TTS", + "id": "msspeech", + "reference": "https://github.com/chflame163/ComfyUI_MSSpeech_TTS", + "files": [ + "https://github.com/chflame163/ComfyUI_MSSpeech_TTS" + ], + "install_type": "git-clone", + "description": "A text-to-speech plugin used under ComfyUI. It utilizes the Microsoft Speech TTS interface to convert text content into MP3 format audio files." + }, + { + "author": "chflame163", + "title": "ComfyUI_WordCloud", + "id": "wordcloud", + "reference": "https://github.com/chflame163/ComfyUI_WordCloud", + "files": [ + "https://github.com/chflame163/ComfyUI_WordCloud" + ], + "install_type": "git-clone", + "description": "Nodes:Word Cloud, Load Text File" + }, + { + "author": "chflame163", + "title": "ComfyUI Layer Style", + "id": "layerstyle", + "reference": "https://github.com/chflame163/ComfyUI_LayerStyle", + "files": [ + "https://github.com/chflame163/ComfyUI_LayerStyle" + ], + "install_type": "git-clone", + "description": "A set of nodes for ComfyUI it generate image like Adobe Photoshop's Layer Style. the Drop Shadow is first completed node, and follow-up work is in progress." + }, + { + "author": "chflame163", + "title": "ComfyUI Face Similarity", + "id": "face-similarity", + "reference": "https://github.com/chflame163/ComfyUI_FaceSimilarity", + "files": [ + "https://github.com/chflame163/ComfyUI_FaceSimilarity" + ], + "install_type": "git-clone", + "description": "A custom node for ComfyUI. It compare two images to rate facial similarity." + }, + { + "author": "drustan-hawk", + "title": "primitive-types", + "reference": "https://github.com/drustan-hawk/primitive-types", + "files": [ + "https://github.com/drustan-hawk/primitive-types" + ], + "install_type": "git-clone", + "description": "Small collection of typed primitive nodes." + }, + { + "author": "shadowcz007", + "title": "comfyui-mixlab-nodes", + "id": "mixlab", + "reference": "https://github.com/shadowcz007/comfyui-mixlab-nodes", + "files": [ + "https://github.com/shadowcz007/comfyui-mixlab-nodes" + ], + "install_type": "git-clone", + "description": "3D, ScreenShareNode & FloatingVideoNode, SpeechRecognition & SpeechSynthesis, GPT, LoadImagesFromLocal, Layers, Other Nodes, ..." + }, + { + "author": "shadowcz007", + "title": "comfyui-ultralytics-yolo", + "id": "yolo", + "reference": "https://github.com/shadowcz007/comfyui-ultralytics-yolo", + "files": [ + "https://github.com/shadowcz007/comfyui-ultralytics-yolo" + ], + "install_type": "git-clone", + "description": "Nodes:Detect By Label." + }, + { + "author": "shadowcz007", + "title": "Consistency Decoder", + "id": "consistency-decoder", + "reference": "https://github.com/shadowcz007/comfyui-consistency-decoder", + "files": [ + "https://github.com/shadowcz007/comfyui-consistency-decoder" + ], + "install_type": "git-clone", + "description": "[a/openai Consistency Decoder](https://github.com/openai/consistencydecoder). After downloading the [a/OpenAI VAE model](https://openaipublic.azureedge.net/diff-vae/c9cebd3132dd9c42936d803e33424145a748843c8f716c0814838bdc8a2fe7cb/decoder.pt), place it in the `model/vae` directory for use." + }, + { + "author": "shadowcz007", + "title": "comfyui-Image-reward", + "reference": "https://github.com/shadowcz007/comfyui-Image-reward", + "files": [ + "https://github.com/shadowcz007/comfyui-Image-reward" + ], + "install_type": "git-clone", + "description": "[a/ImageReward](https://github.com/THUDM/ImageReward): Human preference learning in text-to-image generation. This is a [a/paper](https://arxiv.org/abs/2304.05977) from NeurIPS 2023" + }, + { + "author": "shadowcz007", + "title": "comfyui-sound-lab", + "id": "soundlab", + "reference": "https://github.com/shadowcz007/comfyui-sound-lab", + "files": [ + "https://github.com/shadowcz007/comfyui-sound-lab" + ], + "install_type": "git-clone", + "description": "Nodes:Music Gen, Audio Play, Stable Audio" + }, + { + "author": "shadowcz007", + "title": "comfyui-edit-mask", + "id": "edit-mask", + "reference": "https://github.com/shadowcz007/comfyui-edit-mask", + "files": [ + "https://github.com/shadowcz007/comfyui-edit-mask" + ], + "install_type": "git-clone", + "description": "Nodes:Edit Mask" + }, + { + "author": "shadowcz007", + "title": "comfyui-liveportrait", + "id": "liveportrait", + "reference": "https://github.com/shadowcz007/comfyui-liveportrait", + "files": [ + "https://github.com/shadowcz007/comfyui-liveportrait" + ], + "install_type": "git-clone", + "description": "The ComfyUI version of [a/LivePortrait](https://github.com/KwaiVGI/LivePortrait)." + }, + { + "author": "ostris", + "title": "Ostris Nodes ComfyUI", + "id": "ostris", + "reference": "https://github.com/ostris/ostris_nodes_comfyui", + "files": [ + "https://github.com/ostris/ostris_nodes_comfyui" + ], + "install_type": "git-clone", + "nodename_pattern": "- Ostris$", + "description": "This is a collection of custom nodes for ComfyUI that I made for some QOL. I will be adding much more advanced ones in the future once I get more familiar with the API." + }, + { + "author": "0xbitches", + "title": "Latent Consistency Model for ComfyUI", + "id": "lcm", + "reference": "https://github.com/0xbitches/ComfyUI-LCM", + "files": [ + "https://github.com/0xbitches/ComfyUI-LCM" + ], + "install_type": "git-clone", + "description": "This custom node implements a Latent Consistency Model sampler in ComfyUI. (LCM)" + }, + { + "author": "aszc-dev", + "title": "Core ML Suite for ComfyUI", + "id": "coreml", + "reference": "https://github.com/aszc-dev/ComfyUI-CoreMLSuite", + "files": [ + "https://github.com/aszc-dev/ComfyUI-CoreMLSuite" + ], + "install_type": "git-clone", + "description": "This extension contains a set of custom nodes for ComfyUI that allow you to use Core ML models in your ComfyUI workflows. The models can be obtained here, or you can convert your own models using coremltools. The main motivation behind using Core ML models in ComfyUI is to allow you to utilize the ANE (Apple Neural Engine) on Apple Silicon (M1/M2) machines to improve performance." + }, + { + "author": "taabata", + "title": "Syrian Falcon Nodes", + "id": "syrian", + "reference": "https://github.com/taabata/Comfy_Syrian_Falcon_Nodes", + "files": [ + "https://github.com/taabata/Comfy_Syrian_Falcon_Nodes/raw/main/SyrianFalconNodes.py" + ], + "install_type": "copy", + "description": "Nodes:Prompt editing, Word as Image" + }, + { + "author": "taabata", + "title": "LCM_Inpaint-Outpaint_Comfy", + "id": "lcm-inpaint-outpaint", + "reference": "https://github.com/taabata/LCM_Inpaint-Outpaint_Comfy", + "files": [ + "https://github.com/taabata/LCM_Inpaint-Outpaint_Comfy" + ], + "install_type": "git-clone", + "description": "ComfyUI custom nodes for inpainting/outpainting using the new latent consistency model (LCM)" + }, + { + "author": "noxinias", + "title": "ComfyUI_NoxinNodes", + "id": "noxin", + "reference": "https://github.com/noxinias/ComfyUI_NoxinNodes", + "files": [ + "https://github.com/noxinias/ComfyUI_NoxinNodes" + ], + "install_type": "git-clone", + "description": "Nodes: Noxin Complete Chime, Noxin Scaled Resolutions, Load from Noxin Prompt Library, Save to Noxin Prompt Library" + }, + { + "author": "apesplat", + "title": "ezXY scripts and nodes", + "id": "ezxy", + "reference": "https://github.com/GMapeSplat/ComfyUI_ezXY", + "files": [ + "https://github.com/GMapeSplat/ComfyUI_ezXY" + ], + "install_type": "git-clone", + "description": "Extensions/Patches: Enables linking float and integer inputs and ouputs. Values are automatically cast to the correct type and clamped to the correct range. Works with both builtin and custom nodes.[w/NOTE: This repo patches ComfyUI's validate_inputs and map_node_over_list functions while running. May break depending on your version of ComfyUI. Can be deactivated in config.yaml.]Nodes: A collection of nodes for facilitating the generation of XY plots. Capable of plotting changes over most primitive values." + }, + { + "author": "kinfolk0117", + "title": "SimpleTiles", + "id": "simpletiles", + "reference": "https://github.com/kinfolk0117/ComfyUI_SimpleTiles", + "files": [ + "https://github.com/kinfolk0117/ComfyUI_SimpleTiles" + ], + "install_type": "git-clone", + "description": "Nodes:TileSplit, TileMerge." + }, + { + "author": "kinfolk0117", + "title": "ComfyUI_GradientDeepShrink", + "id": "deepshrink", + "reference": "https://github.com/kinfolk0117/ComfyUI_GradientDeepShrink", + "files": [ + "https://github.com/kinfolk0117/ComfyUI_GradientDeepShrink" + ], + "install_type": "git-clone", + "description": "Nodes:GradientPatchModelAddDownscale (Kohya Deep Shrink)." + }, + { + "author": "kinfolk0117", + "title": "ComfyUI_Pilgram", + "id": "pilgram", + "reference": "https://github.com/kinfolk0117/ComfyUI_Pilgram", + "files": [ + "https://github.com/kinfolk0117/ComfyUI_Pilgram" + ], + "install_type": "git-clone", + "description": "Use [a/Pilgram2](https://github.com/mgineer85/pilgram2) filters in ComfyUI" + }, + { + "author": "Fictiverse", + "title": "ComfyUI Fictiverse Nodes", + "id": "fictverse", + "reference": "https://github.com/Fictiverse/ComfyUI_Fictiverse", + "files": [ + "https://github.com/Fictiverse/ComfyUI_Fictiverse" + ], + "install_type": "git-clone", + "description": "Nodes:Color correction." + }, + { + "author": "idrirap", + "title": "ComfyUI-Lora-Auto-Trigger-Words", + "id": "lora-auto-trigger", + "reference": "https://github.com/idrirap/ComfyUI-Lora-Auto-Trigger-Words", + "files": [ + "https://github.com/idrirap/ComfyUI-Lora-Auto-Trigger-Words" + ], + "install_type": "git-clone", + "description": "This project is a fork of [a/https://github.com/Extraltodeus/LoadLoraWithTags](https://github.com/Extraltodeus/LoadLoraWithTags) The aim of these custom nodes is to get an easy access to the tags used to trigger a lora." + }, + { + "author": "aianimation55", + "title": "Comfy UI FatLabels", + "id": "fatlab", + "reference": "https://github.com/aianimation55/ComfyUI-FatLabels", + "files": [ + "https://github.com/aianimation55/ComfyUI-FatLabels" + ], + "install_type": "git-clone", + "description": "It's a super simple custom node for Comfy UI, to generate text, with a font size option. Useful for bigger labelling of nodes, helpful for wider screen captures or tutorials. Plus you can of course use the text within your generations." + }, + { + "author": "noEmbryo", + "title": "noEmbryo nodes", + "id": "noembryo", + "reference": "https://github.com/noembryo/ComfyUI-noEmbryo", + "files": [ + "https://github.com/noembryo/ComfyUI-noEmbryo" + ], + "install_type": "git-clone", + "description": "PromptTermList (1-6): are some nodes that help with the creation of Prompts inside ComfyUI. Resolution Scale outputs image dimensions using a scale factor. Regex Text Chopper outputs the chopped parts of a text using RegEx." + }, + { + "author": "mikkel", + "title": "ComfyUI - Mask Bounding Box", + "id": "mask-bbox", + "reference": "https://github.com/mikkel/comfyui-mask-boundingbox", + "files": [ + "https://github.com/mikkel/comfyui-mask-boundingbox" + ], + "install_type": "git-clone", + "description": "The ComfyUI Mask Bounding Box Plugin provides functionalities for selecting a specific size mask from an image. Can be combined with ClipSEG to replace any aspect of an SDXL image with an SD1.5 output." + }, + { + "author": "ParmanBabra", + "title": "ComfyUI-Malefish-Custom-Scripts", + "id": "malefish", + "reference": "https://github.com/ParmanBabra/ComfyUI-Malefish-Custom-Scripts", + "files": [ + "https://github.com/ParmanBabra/ComfyUI-Malefish-Custom-Scripts" + ], + "install_type": "git-clone", + "description": "Nodes:Multi Lora Loader, Random (Prompt), Combine (Prompt), CSV Prompts Loader" + }, + { + "author": "IAmMatan.com", + "title": "ComfyUI Serving toolkit", + "id": "serving-toolkit", + "reference": "https://github.com/matan1905/ComfyUI-Serving-Toolkit", + "files": [ + "https://github.com/matan1905/ComfyUI-Serving-Toolkit" + ], + "install_type": "git-clone", + "description": "This extension adds nodes that allow you to easily serve your workflow (for example using a discord bot) " + }, + { + "author": "PCMonsterx", + "title": "ComfyUI-CSV-Loader", + "id": "csv-loader", + "reference": "https://github.com/PCMonsterx/ComfyUI-CSV-Loader", + "files": [ + "https://github.com/PCMonsterx/ComfyUI-CSV-Loader" + ], + "install_type": "git-clone", + "description": "CSV Loader for prompt building within ComfyUI interface. Allows access to positive/negative prompts associated with a name. Selections are being pulled from CSV files." + }, + { + "author": "Trung0246", + "title": "ComfyUI-0246", + "id": "0246", + "reference": "https://github.com/Trung0246/ComfyUI-0246", + "files": [ + "https://github.com/Trung0246/ComfyUI-0246" + ], + "install_type": "git-clone", + "description": "Random nodes for ComfyUI I made to solve my struggle with ComfyUI (ex: pipe, process). Have varying quality." + }, + { + "author": "fexli", + "title": "fexli-util-node-comfyui", + "id": "fexli", + "reference": "https://github.com/fexli/fexli-util-node-comfyui", + "files": [ + "https://github.com/fexli/fexli-util-node-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:FEImagePadForOutpaint, FEColorOut, FEColor2Image, FERandomizedColor2Image" + }, + { + "author": "AbyssYuan0", + "title": "ComfyUI_BadgerTools", + "id": "badger", + "reference": "https://github.com/AbyssYuan0/ComfyUI_BadgerTools", + "files": [ + "https://github.com/AbyssYuan0/ComfyUI_BadgerTools" + ], + "install_type": "git-clone", + "description": "Nodes:ImageOverlap-badger, FloatToInt-badger, IntToString-badger, FloatToString-badger, ImageNormalization-badger, ImageScaleToSide-badger, NovelToFizz-badger." + }, + { + "author": "palant", + "title": "Image Resize for ComfyUI", + "id": "image-resize", + "reference": "https://github.com/palant/image-resize-comfyui", + "files": [ + "https://github.com/palant/image-resize-comfyui" + ], + "install_type": "git-clone", + "description": "This custom node provides various tools for resizing images. The goal is resizing without distorting proportions, yet without having to perform any calculations with the size of the original image. If a mask is present, it is resized and modified along with the image." + }, + { + "author": "palant", + "title": "Integrated Nodes for ComfyUI", + "reference": "https://github.com/palant/integrated-nodes-comfyui", + "files": [ + "https://github.com/palant/integrated-nodes-comfyui" + ], + "install_type": "git-clone", + "description": "This tool will turn entire workflows or parts of them into single integrated nodes. In a way, it is similar to the Node Templates functionality but hides the inner structure. This is useful if all you want is to reuse and quickly configure a bunch of nodes without caring how they are interconnected." + }, + { + "author": "palant", + "title": "Extended Save Image for ComfyUI", + "reference": "https://github.com/palant/extended-saveimage-comfyui", + "files": [ + "https://github.com/palant/extended-saveimage-comfyui" + ], + "install_type": "git-clone", + "description": "This custom node is largely identical to the usual Save Image but allows saving images also in JPEG and WEBP formats, the latter with both lossless and lossy compression. Metadata is embedded in the images as usual, and the resulting images can be used to load a workflow." + }, + { + "author": "whmc76", + "title": "ComfyUI-Openpose-Editor-Plus", + "id": "openpose-editor-plus", + "reference": "https://github.com/whmc76/ComfyUI-Openpose-Editor-Plus", + "files": [ + "https://github.com/whmc76/ComfyUI-Openpose-Editor-Plus" + ], + "install_type": "git-clone", + "description": "Nodes:Openpose Editor Plus" + }, + { + "author": "martijnat", + "title": "comfyui-previewlatent", + "reference": "https://github.com/martijnat/comfyui-previewlatent", + "files": [ + "https://github.com/martijnat/comfyui-previewlatent" + ], + "install_type": "git-clone", + "description": "a ComfyUI plugin for previewing latents without vae decoding. Useful for showing intermediate results and can be used a faster 'preview image' if you don't wan't to use vae decode." + }, + { + "author": "banodoco", + "title": "Steerable Motion", + "id": "steerable-motion", + "reference": "https://github.com/banodoco/steerable-motion", + "files": [ + "https://github.com/banodoco/steerable-motion" + ], + "install_type": "git-clone", + "description": "Steerable Motion is a ComfyUI node for batch creative interpolation. Our goal is to feature the best methods for steering motion with images as video models evolve." + }, + { + "author": "gemell1", + "title": "ComfyUI_GMIC", + "id": "gmic", + "reference": "https://github.com/gemell1/ComfyUI_GMIC", + "files": [ + "https://github.com/gemell1/ComfyUI_GMIC" + ], + "install_type": "git-clone", + "description": "Nodes:GMIC Image Processing." + }, + { + "author": "LonicaMewinsky", + "title": "ComfyBreakAnim", + "id": "breakanim", + "reference": "https://github.com/LonicaMewinsky/ComfyUI-MakeFrame", + "files": [ + "https://github.com/LonicaMewinsky/ComfyUI-MakeFrame" + ], + "install_type": "git-clone", + "description": "Nodes:BreakFrames, GetKeyFrames, MakeGrid." + }, + { + "author": "TheBarret", + "title": "ZSuite", + "id": "zsuite", + "reference": "https://github.com/TheBarret/ZSuite", + "files": [ + "https://github.com/TheBarret/ZSuite" + ], + "install_type": "git-clone", + "description": "Nodes:Prompter, RF Noise, SeedMod." + }, + { + "author": "romeobuilderotti", + "title": "ComfyUI PNG Metadata", + "id": "pngmeta", + "reference": "https://github.com/romeobuilderotti/ComfyUI-PNG-Metadata", + "files": [ + "https://github.com/romeobuilderotti/ComfyUI-PNG-Metadata" + ], + "install_type": "git-clone", + "description": "Add custom Metadata fields to your saved PNG files." + }, + { + "author": "ka-puna", + "title": "comfyui-yanc", + "id": "yanc", + "reference": "https://github.com/ka-puna/comfyui-yanc", + "files": [ + "https://github.com/ka-puna/comfyui-yanc" + ], + "install_type": "git-clone", + "description": "NOTE: Concatenate Strings, Format Datetime String, Integer Caster, Multiline String, Truncate String. Yet Another Node Collection, a repository of simple nodes for ComfyUI. This repository eases the addition or removal of custom nodes to itself." + }, + { + "author": "amorano", + "title": "Jovimetrix Composition Nodes", + "id": "jovimetrix", + "reference": "https://github.com/Amorano/Jovimetrix", + "files": [ + "https://github.com/Amorano/Jovimetrix" + ], + "nodename_pattern": " \\(JOV\\)$", + "install_type": "git-clone", + "description": "Webcam, MIDI, Spout and GLSL shader support. Animation via tick. Parameter manipulation with wave generator. Math operations, universal value converstion, shape mask generation, image channel ops, batch splitting/merging/randomizing, load image/video from URL, Dynamic bus routing, support for GIPHY, save output anywhere! flatten, crop, transform; check color blindness, make stereograms or stereoscopic images, and much more." + }, + { + "author": "Umikaze-job", + "title": "select_folder_path_easy", + "reference": "https://github.com/Umikaze-job/select_folder_path_easy", + "files": [ + "https://github.com/Umikaze-job/select_folder_path_easy" + ], + "install_type": "git-clone", + "description": "This extension simply connects the nodes and specifies the output path of the generated images to a manageable path." + }, + { + "author": "Niutonian", + "title": "ComfyUi-NoodleWebcam", + "id": "noodle-webcam", + "reference": "https://github.com/Niutonian/ComfyUi-NoodleWebcam", + "files": [ + "https://github.com/Niutonian/ComfyUi-NoodleWebcam" + ], + "install_type": "git-clone", + "description": "Nodes:Noodle webcam is a node that records frames and send them to your favourite node." + }, + { + "author": "Feidorian", + "title": "feidorian-ComfyNodes", + "id": "feidorian", + "reference": "https://github.com/Feidorian/feidorian-ComfyNodes", + "nodename_pattern": "^Feidorian_", + "files": [ + "https://github.com/Feidorian/feidorian-ComfyNodes" + ], + "install_type": "git-clone", + "description": "This extension provides various custom nodes. literals, loaders, logic, output, switches" + }, + { + "author": "wutipong", + "title": "ComfyUI-TextUtils", + "reference": "https://github.com/wutipong/ComfyUI-TextUtils", + "files": [ + "https://github.com/wutipong/ComfyUI-TextUtils" + ], + "install_type": "git-clone", + "description": "Nodes:Create N-Token String" + }, + { + "author": "natto-maki", + "title": "ComfyUI-NegiTools", + "id": "negitools", + "reference": "https://github.com/natto-maki/ComfyUI-NegiTools", + "files": [ + "https://github.com/natto-maki/ComfyUI-NegiTools" + ], + "install_type": "git-clone", + "description": "Nodes:OpenAI DALLe3, OpenAI Translate to English, String Function, Seed Generator" + }, + { + "author": "LonicaMewinsky", + "title": "ComfyUI-RawSaver", + "id": "rawsaver", + "reference": "https://github.com/LonicaMewinsky/ComfyUI-RawSaver", + "files": [ + "https://github.com/LonicaMewinsky/ComfyUI-RawSaver" + ], + "install_type": "git-clone", + "description": "Nodes:SaveTifImage. ComfyUI custom node for purpose of saving image as uint16 tif file." + }, + { + "author": "jojkaart", + "title": "ComfyUI-sampler-lcm-alternative", + "id": "lmc-alt", + "reference": "https://github.com/jojkaart/ComfyUI-sampler-lcm-alternative", + "files": [ + "https://github.com/jojkaart/ComfyUI-sampler-lcm-alternative" + ], + "install_type": "git-clone", + "description": "Nodes:LCMScheduler, SamplerLCMAlternative, SamplerLCMCycle. ComfyUI Custom Sampler nodes that add a new improved LCM sampler functions" + }, + { + "author": "GTSuya-Studio", + "title": "ComfyUI-GTSuya-Nodes", + "id": "gtsuya", + "reference": "https://github.com/GTSuya-Studio/ComfyUI-Gtsuya-Nodes", + "files": [ + "https://github.com/GTSuya-Studio/ComfyUI-Gtsuya-Nodes" + ], + "install_type": "git-clone", + "description": "ComfyUI-GTSuya-Nodes is a ComfyUI extension designed to add several wildcards supports into ComfyUI. Wildcards allow you to use __name__ syntax in your prompt to get a random line from a file named name.txt in a wildcards directory." + }, + { + "author": "oyvindg", + "title": "ComfyUI-TrollSuite", + "id": "troll", + "reference": "https://github.com/oyvindg/ComfyUI-TrollSuite", + "files": [ + "https://github.com/oyvindg/ComfyUI-TrollSuite" + ], + "install_type": "git-clone", + "description": "Nodes: BinaryImageMask, ImagePadding, LoadLastCreatedImage, RandomMask, TransparentImage." + }, + { + "author": "drago87", + "title": "ComfyUI_Dragos_Nodes", + "id": "dragos", + "reference": "https://github.com/drago87/ComfyUI_Dragos_Nodes", + "files": [ + "https://github.com/drago87/ComfyUI_Dragos_Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:File Padding, Image Info, VAE Loader With Name" + }, + { + "author": "ansonkao", + "title": "comfyui-geometry", + "id": "geometry", + "reference": "https://github.com/ansonkao/comfyui-geometry", + "files": [ + "https://github.com/ansonkao/comfyui-geometry" + ], + "install_type": "git-clone", + "description": "Nodes: Mask to Centroid, Mask to Eigenvector. A small collection of custom nodes for use with ComfyUI, for geometry calculations" + }, + { + "author": "bronkula", + "title": "comfyui-fitsize", + "id": "fitsize", + "reference": "https://github.com/bronkula/comfyui-fitsize", + "files": [ + "https://github.com/bronkula/comfyui-fitsize" + ], + "install_type": "git-clone", + "description": "Nodes:Fit Size From Int/Image/Resize, Load Image And Resize To Fit, Pick Image From Batch/List, Crop Image Into Even Pieces, Image Region To Mask... A simple set of nodes for making an image fit within a bounding box" + }, + { + "author": "toyxyz", + "title": "ComfyUI_toyxyz_test_nodes", + "id": "toyxyz", + "reference": "https://github.com/toyxyz/ComfyUI_toyxyz_test_nodes", + "files": [ + "https://github.com/toyxyz/ComfyUI_toyxyz_test_nodes" + ], + "install_type": "git-clone", + "description": "This node was created to send a webcam to ComfyUI in real time. This node is recommended for use with LCM." + }, + { + "author": "thecooltechguy", + "title": "ComfyUI Stable Video Diffusion", + "reference": "https://github.com/thecooltechguy/ComfyUI-Stable-Video-Diffusion", + "files": [ + "https://github.com/thecooltechguy/ComfyUI-Stable-Video-Diffusion" + ], + "install_type": "git-clone", + "description": "Easily use Stable Video Diffusion inside ComfyUI!" + }, + { + "author": "thecooltechguy", + "title": "ComfyUI-ComfyRun", + "reference": "https://github.com/thecooltechguy/ComfyUI-ComfyRun", + "files": [ + "https://github.com/thecooltechguy/ComfyUI-ComfyRun" + ], + "install_type": "git-clone", + "description": "The easiest way to run & share any ComfyUI workflow [a/https://comfyrun.com](https://comfyrun.com)" + }, + { + "author": "thecooltechguy", + "title": "ComfyUI-MagicAnimate", + "reference": "https://github.com/thecooltechguy/ComfyUI-MagicAnimate", + "files": [ + "https://github.com/thecooltechguy/ComfyUI-MagicAnimate" + ], + "install_type": "git-clone", + "description": "Easily use Magic Animate within ComfyUI!\n[w/WARN: This extension requires 15GB disk space.]" + }, + { + "author": "thecooltechguy", + "title": "ComfyUI-ComfyWorkflows", + "reference": "https://github.com/thecooltechguy/ComfyUI-ComfyWorkflows", + "files": [ + "https://github.com/thecooltechguy/ComfyUI-ComfyWorkflows" + ], + "install_type": "git-clone", + "description": "The best way to run, share, & discover thousands of ComfyUI workflows." + }, + { + "author": "Danand", + "title": "Comfy Couple", + "reference": "https://github.com/Danand/ComfyUI-ComfyCouple", + "files": [ + "https://github.com/Danand/ComfyUI-ComfyCouple" + ], + "install_type": "git-clone", + "description": " If you want to draw two different characters together without blending their features, so you could try to check out this custom node." + }, + { + "author": "42lux", + "title": "ComfyUI-safety-checker", + "reference": "https://github.com/42lux/ComfyUI-safety-checker", + "files": [ + "https://github.com/42lux/ComfyUI-safety-checker" + ], + "install_type": "git-clone", + "description": "A NSFW/Safety Checker Node for ComfyUI." + }, + { + "author": "sergekatzmann", + "title": "ComfyUI_Nimbus-Pack", + "reference": "https://github.com/sergekatzmann/ComfyUI_Nimbus-Pack", + "files": [ + "https://github.com/sergekatzmann/ComfyUI_Nimbus-Pack" + ], + "install_type": "git-clone", + "description": "Nodes:Image Square Adapter Node, Image Resize And Crop Node" + }, + { + "author": "komojini", + "title": "ComfyUI_SDXL_DreamBooth_LoRA_CustomNodes", + "reference": "https://github.com/komojini/ComfyUI_SDXL_DreamBooth_LoRA_CustomNodes", + "files": [ + "https://github.com/komojini/ComfyUI_SDXL_DreamBooth_LoRA_CustomNodes" + ], + "install_type": "git-clone", + "description": "Nodes:XL DreamBooth LoRA, S3 Bucket LoRA" + }, + { + "author": "komojini", + "title": "komojini-comfyui-nodes", + "id": "komojini-nodes", + "reference": "https://github.com/komojini/komojini-comfyui-nodes", + "files": [ + "https://github.com/komojini/komojini-comfyui-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:YouTube Video Loader. Custom ComfyUI Nodes for video generation" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "APISR IN COMFYUI", + "id": "apisr-zho", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of APISR for ComfyUI, both image and video" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-Text_Image-Composite [WIP]", + "id": "txtimg-composite", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Text_Image-Composite", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Text_Image-Composite" + ], + "install_type": "git-clone", + "description": "Nodes:Text_Image_Zho, Text_Image_Multiline_Zho, RGB_Image_Zho, AlphaChanelAddByMask, ImageComposite_Zho, ..." + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-Gemini", + "id": "gemini", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Gemini", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Gemini" + ], + "install_type": "git-clone", + "description": "Using Gemini-pro & Gemini-pro-vision in ComfyUI." + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "comfyui-portrait-master-zh-cn", + "id": "portrait-master-zho", + "reference": "https://github.com/ZHO-ZHO-ZHO/comfyui-portrait-master-zh-cn", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/comfyui-portrait-master-zh-cn" + ], + "install_type": "git-clone", + "description": "ComfyUI Portrait Master 简体中文版." + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-Q-Align", + "id": "qalign-zho", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Q-Align", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Q-Align" + ], + "install_type": "git-clone", + "description": "Nodes:Q-Align Scoring. Implementation of [a/Q-Align](https://arxiv.org/abs/2312.17090) for ComfyUI" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-InstantID", + "id": "instantid-zho", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-InstantID", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-InstantID" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/InstantID](https://github.com/InstantID/InstantID) for ComfyUI" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI PhotoMaker (ZHO)", + "id": "photomaker-zho", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PhotoMaker-ZHO", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PhotoMaker-ZHO" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/PhotoMaker](https://github.com/TencentARC/PhotoMaker) for ComfyUI" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-Qwen-VL-API", + "id": "qwen-vl-api", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-VL-API", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-VL-API" + ], + "install_type": "git-clone", + "description": "QWen-VL-Plus & QWen-VL-Max in ComfyUI" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-SVD-ZHO (WIP)", + "id": "svd-zho", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SVD-ZHO", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SVD-ZHO" + ], + "install_type": "git-clone", + "description": "My Workflows + Auxiliary nodes for Stable Video Diffusion (SVD)" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI SegMoE", + "id": "segmoe", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SegMoE", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SegMoE" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/SegMoE: Segmind Mixture of Diffusion Experts](https://github.com/segmind/segmoe) for ComfyUI" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI YoloWorld-EfficientSAM", + "id": "yoloworld", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/YOLO-World + EfficientSAM](https://huggingface.co/spaces/SkalskiP/YOLO-World) & [a/YOLO-World](https://github.com/AILab-CVC/YOLO-World) for ComfyUI\nNOTE: Install the efficient_sam model from the Install models menu.\n[w/When installing or updating this custom node, many installation packages may be downgraded due to the installation of requirements.\n!! python3.12 is incompatible.]" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-PixArt-alpha-Diffusers", + "id": "pixart-alpha", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PixArt-alpha-Diffusers", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PixArt-alpha-Diffusers" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/PixArt-alpha-Diffusers](https://github.com/PixArt-alpha/PixArt-alpha) for ComfyUI" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-BRIA_AI-RMBG", + "id": "bria-ai-rmbg", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BRIA_AI-RMBG", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BRIA_AI-RMBG" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of BRIA RMBG Model for ComfyUI." + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "DepthFM IN COMFYUI", + "id": "depthfm", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-DepthFM", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-DepthFM" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/DepthFM](https://github.com/CompVis/depth-fm) for ComfyUI" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-BiRefNet-ZHO", + "id": "birefnet", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BiRefNet-ZHO", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BiRefNet-ZHO" + ], + "install_type": "git-clone", + "description": "Better version for [a/BiRefNet](https://github.com/zhengpeng7/birefnet) in ComfyUI | Both img and video" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "Phi-3-mini in ComfyUI", + "id": "phi3mini", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Phi-3-mini", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Phi-3-mini" + ], + "install_type": "git-clone", + "description": "Nodes:Phi3mini_4k_ModelLoader_Zho, Phi3mini_4k_Zho, Phi3mini_4k_Chat_Zho" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-ArtGallery", + "id": "artgallery", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-ArtGallery", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-ArtGallery" + ], + "install_type": "git-clone", + "description": "Prompt Visualization | Art Gallery\n[w/WARN: Installation requires 2GB of space, and it will involve a long download time.]" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-Animated-optical-illusions", + "id": "animated-optical-illusion", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Animated-optical-illusions", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Animated-optical-illusions" + ], + "install_type": "git-clone", + "description": "Animated optical illusions in ComfyUI" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-Qwen-2", + "id": "qwen-2", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-2", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-2" + ], + "install_type": "git-clone", + "description": "Using Qwen-2 in ComfyUI" + }, + { + "author": "kenjiqq", + "title": "qq-nodes-comfyui", + "reference": "https://github.com/kenjiqq/qq-nodes-comfyui", + "files": [ + "https://github.com/kenjiqq/qq-nodes-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:Any List, Image Accumulator Start, Image Accumulator End, Load Lines From Text File, XY Grid Helper, Slice List, Axis To String/Int/Float/Model, ..." + }, + { + "author": "80sVectorz", + "title": "ComfyUI-Static-Primitives", + "reference": "https://github.com/80sVectorz/ComfyUI-Static-Primitives", + "files": [ + "https://github.com/80sVectorz/ComfyUI-Static-Primitives" + ], + "install_type": "git-clone", + "description": "Adds Static Primitives to ComfyUI. Mostly to work with reroute nodes" + }, + { + "author": "AbdullahAlfaraj", + "title": "Comfy-Photoshop-SD", + "reference": "https://github.com/AbdullahAlfaraj/Comfy-Photoshop-SD", + "files": [ + "https://github.com/AbdullahAlfaraj/Comfy-Photoshop-SD" + ], + "install_type": "git-clone", + "description": "Nodes: load Image with metadata, get config data, load image from base64 string, Load Loras From Prompt, Generate Latent Noise, Combine Two Latents Into Batch, General Purpose Controlnet Unit, ControlNet Script, Content Mask Latent, Auto-Photoshop-SD Seed, Expand and Blur the Mask" + }, + { + "author": "zhuanqianfish", + "title": "EasyCaptureNode for ComfyUI", + "reference": "https://github.com/zhuanqianfish/ComfyUI-EasyNode", + "files": [ + "https://github.com/zhuanqianfish/ComfyUI-EasyNode" + ], + "install_type": "git-clone", + "description": "Capture window content from other programs, easyway combined with LCM for real-time painting" + }, + { + "author": "discopixel-studio", + "title": "ComfyUI Discopixel Nodes", + "reference": "https://github.com/discopixel-studio/comfyui-discopixel", + "files": [ + "https://github.com/discopixel-studio/comfyui-discopixel" + ], + "install_type": "git-clone", + "description": "Nodes:TransformTemplateOntoFaceMask, ... A small collection of custom nodes for use with ComfyUI, by Discopixel" + }, + { + "author": "zcfrank1st", + "title": "ComfyUI Yolov8", + "reference": "https://github.com/zcfrank1st/Comfyui-Yolov8", + "files": [ + "https://github.com/zcfrank1st/Comfyui-Yolov8" + ], + "install_type": "git-clone", + "description": "Nodes: Yolov8Detection, Yolov8Segmentation. Deadly simple yolov8 comfyui plugin" + }, + { + "author": "SoftMeng", + "title": "ComfyUI_Mexx_Styler", + "reference": "https://github.com/SoftMeng/ComfyUI_Mexx_Styler", + "files": [ + "https://github.com/SoftMeng/ComfyUI_Mexx_Styler" + ], + "install_type": "git-clone", + "description": "Nodes: ComfyUI Mexx Styler, ComfyUI Mexx Styler Advanced" + }, + { + "author": "SoftMeng", + "title": "ComfyUI_Mexx_Poster", + "reference": "https://github.com/SoftMeng/ComfyUI_Mexx_Poster", + "files": [ + "https://github.com/SoftMeng/ComfyUI_Mexx_Poster" + ], + "install_type": "git-clone", + "description": "Nodes: ComfyUI_Mexx_Poster" + }, + { + "author": "SoftMeng", + "title": "ComfyUI_ImageToText", + "reference": "https://github.com/SoftMeng/ComfyUI_ImageToText", + "files": [ + "https://github.com/SoftMeng/ComfyUI_ImageToText" + ], + "install_type": "git-clone", + "description": "Nodes: ComfyUI_ImageToText" + }, + { + "author": "wmatson", + "title": "easy-comfy-nodes", + "reference": "https://github.com/wmatson/easy-comfy-nodes", + "files": [ + "https://github.com/wmatson/easy-comfy-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: HTTP POST, Empty Dict, Assoc Str, Assoc Dict, Assoc Img, Load Img From URL (EZ), Load Img Batch From URLs (EZ), Video Combine + upload (EZ), ..." + }, + { + "author": "DrJKL", + "title": "ComfyUI-Anchors", + "reference": "https://github.com/DrJKL/ComfyUI-Anchors", + "files": [ + "https://github.com/DrJKL/ComfyUI-Anchors" + ], + "install_type": "git-clone", + "description": "A ComfyUI extension to add spatial anchors/waypoints to better navigate large workflows." + }, + { + "author": "vanillacode314", + "title": "Simple Wildcard", + "reference": "https://github.com/vanillacode314/SimpleWildcardsComfyUI", + "files": ["https://github.com/vanillacode314/SimpleWildcardsComfyUI"], + "install_type": "git-clone", + "pip": ["pipe"], + "description": "A simple wildcard node for ComfyUI. Can also be used a style prompt node." + }, + { + "author": "WebDev9000", + "title": "WebDev9000-Nodes", + "reference": "https://github.com/WebDev9000/WebDev9000-Nodes", + "files": [ + "https://github.com/WebDev9000/WebDev9000-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Ignore Braces, Settings Switch." + }, + { + "author": "Scholar01", + "title": "SComfyUI-Keyframe", + "reference": "https://github.com/Scholar01/ComfyUI-Keyframe", + "files": [ + "https://github.com/Scholar01/ComfyUI-Keyframe" + ], + "install_type": "git-clone", + "description": "Nodes:Keyframe Part, Keyframe Interpolation Part, Keyframe Apply." + }, + { + "author": "Haoming02", + "title": "ComfyUI Diffusion Color Grading", + "reference": "https://github.com/Haoming02/comfyui-diffusion-cg", + "files": [ + "https://github.com/Haoming02/comfyui-diffusion-cg" + ], + "install_type": "git-clone", + "description": "This is the ComfyUI port of the joint research between me and TimothyAlexisVass. For more information, check out the original [a/Extension](https://github.com/Haoming02/sd-webui-diffusion-cg) for Automatic1111." + }, + { + "author": "Haoming02", + "title": "comfyui-prompt-format", + "reference": "https://github.com/Haoming02/comfyui-prompt-format", + "files": [ + "https://github.com/Haoming02/comfyui-prompt-format" + ], + "install_type": "git-clone", + "description": "This is an Extension for ComfyUI, which helps formatting texts." + }, + { + "author": "Haoming02", + "title": "ComfyUI Clear Screen", + "reference": "https://github.com/Haoming02/comfyui-clear-screen", + "files": [ + "https://github.com/Haoming02/comfyui-clear-screen" + ], + "install_type": "git-clone", + "description": "Adds a CLS button to clear the console." + }, + { + "author": "Haoming02", + "title": "ComfyUI Menu Anchor", + "reference": "https://github.com/Haoming02/comfyui-menu-anchor", + "files": [ + "https://github.com/Haoming02/comfyui-menu-anchor" + ], + "install_type": "git-clone", + "description": "This is an Extension for ComfyUI, which moves the menu to the specified corner on startup." + }, + { + "author": "Haoming02", + "title": "ComfyUI Tab Handler", + "reference": "https://github.com/Haoming02/comfyui-tab-handler", + "files": [ + "https://github.com/Haoming02/comfyui-tab-handler" + ], + "install_type": "git-clone", + "description": "Intercepts the Tab key to switch between textarea" + }, + { + "author": "Haoming02", + "title": "ComfyUI Floodgate", + "reference": "https://github.com/Haoming02/comfyui-floodgate", + "files": [ + "https://github.com/Haoming02/comfyui-floodgate" + ], + "install_type": "git-clone", + "description": "A node that allows you to switch between execution flow" + }, + { + "author": "Haoming02", + "title": "ComfyUI Node Beautify", + "reference": "https://github.com/Haoming02/comfyui-node-beautify", + "files": [ + "https://github.com/Haoming02/comfyui-node-beautify" + ], + "install_type": "git-clone", + "description": "This is an Extension for ComfyUI, which helps formatting the workflow." + }, + { + "author": "bedovyy", + "title": "ComfyUI_NAIDGenerator", + "reference": "https://github.com/bedovyy/ComfyUI_NAIDGenerator", + "files": [ + "https://github.com/bedovyy/ComfyUI_NAIDGenerator" + ], + "install_type": "git-clone", + "description": "This extension helps generate images through NAI." + }, + { + "author": "Off-Live", + "title": "ComfyUI-off-suite", + "reference": "https://github.com/Off-Live/ComfyUI-off-suite", + "files": [ + "https://github.com/Off-Live/ComfyUI-off-suite" + ], + "install_type": "git-clone", + "description": "Nodes:Image Crop Fit, OFF SEGS to Image, Crop Center wigh SEGS, Watermarking, GW Number Formatting Node." + }, + { + "author": "ningxiaoxiao", + "title": "comfyui-NDI", + "reference": "https://github.com/ningxiaoxiao/comfyui-NDI", + "files": [ + "https://github.com/ningxiaoxiao/comfyui-NDI" + ], + "pip": ["ndi-python"], + "install_type": "git-clone", + "description": "Real-time input output node for ComfyUI by NDI. Leveraging the powerful linking capabilities of NDI, you can access NDI video stream frames and send images generated by the model to NDI video streams." + }, + { + "author": "subtleGradient", + "title": "Touchpad two-finger gesture support for macOS", + "reference": "https://github.com/subtleGradient/TinkerBot-tech-for-ComfyUI-Touchpad", + "files": [ + "https://github.com/subtleGradient/TinkerBot-tech-for-ComfyUI-Touchpad" + ], + "install_type": "git-clone", + "description": "Two-finger scrolling (vertical and horizontal) to pan the canvas. Two-finger pinch to zoom in and out. Command-scroll up and down to zoom in and out. Fixes [a/comfyanonymous/ComfyUI#2059](https://github.com/comfyanonymous/ComfyUI/issues/2059)." + }, + { + "author": "zcfrank1st", + "title": "comfyui_visual_anagram", + "reference": "https://github.com/zcfrank1st/comfyui_visual_anagrams", + "files": [ + "https://github.com/zcfrank1st/comfyui_visual_anagrams" + ], + "install_type": "git-clone", + "description": "Nodes:visual_anagrams_sample, visual_anagrams_animate" + }, + { + "author": "Electrofried", + "title": "OpenAINode", + "reference": "https://github.com/Electrofried/ComfyUI-OpenAINode", + "files": [ + "https://github.com/Electrofried/ComfyUI-OpenAINode" + ], + "install_type": "git-clone", + "description": "A simply node for hooking in to openAI API based servers via comfyUI" + }, + { + "author": "AustinMroz", + "title": "SpliceTools", + "id": "splicetools", + "reference": "https://github.com/AustinMroz/ComfyUI-SpliceTools", + "files": [ + "https://github.com/AustinMroz/ComfyUI-SpliceTools" + ], + "install_type": "git-clone", + "description": "Experimental utility nodes with a focus on manipulation of noised latents" + }, + { + "author": "AustinMroz", + "title": "DynamicOversampling", + "id": "dynamic-oversampling", + "reference": "https://github.com/AustinMroz/ComfyUI-DynamicOversampling", + "files": [ + "https://github.com/AustinMroz/ComfyUI-DynamicOversampling" + ], + "install_type": "git-clone", + "description": "Nodes:DynamicSampler, MeasuredSampler, ResolveMaskPromise" + }, + { + "author": "AustinMroz", + "title": "ComfyUI-WorkflowCheckpointing", + "id": "workflowcheckpointing", + "reference": "https://github.com/AustinMroz/ComfyUI-WorkflowCheckpointing", + "files": [ + "https://github.com/AustinMroz/ComfyUI-WorkflowCheckpointing" + ], + "install_type": "git-clone", + "description": "Automatically creates checkpoints during workflow execution. If If an workflow is canceled or ComfyUI crashes mid-execution, then these checkpoints are used when the workflow is re-queued to resume execution with minimal progress loss." + }, + { + "author": "11cafe", + "title": "ComfyUI Workspace Manager - Comfyspace", + "reference": "https://github.com/11cafe/comfyui-workspace-manager", + "files": [ + "https://github.com/11cafe/comfyui-workspace-manager" + ], + "install_type": "git-clone", + "description": "A ComfyUI custom node for project management to centralize the management of all your workflows in one place. Seamlessly switch between workflows, create and update them within a single workspace, like Google Docs." + }, + { + "author": "knuknX", + "title": "ComfyUI-Image-Tools", + "reference": "https://github.com/knuknX/ComfyUI-Image-Tools", + "files": [ + "https://github.com/knuknX/ComfyUI-Image-Tools" + ], + "install_type": "git-clone", + "description": "Nodes:BatchImageResizeProcessor, SingleImagePathLoader, SingleImageUrlLoader" + }, + { + "author": "jtrue", + "title": "ComfyUI-JaRue", + "reference": "https://github.com/jtrue/ComfyUI-JaRue", + "files": [ + "https://github.com/jtrue/ComfyUI-JaRue" + ], + "nodename_pattern": "_jru$", + "install_type": "git-clone", + "description": "A collection of nodes powering a tensor oracle on a home network with automation" + }, + { + "author": "filliptm", + "title": "ComfyUI_Fill-Nodes", + "reference": "https://github.com/filliptm/ComfyUI_Fill-Nodes", + "files": [ + "https://github.com/filliptm/ComfyUI_Fill-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:FL Image Randomizer. The start of a pack that I will continue to build out to fill the gaps of nodes and functionality that I feel is missing in comfyUI" + }, + { + "author": "zfkun", + "title": "ComfyUI_zfkun", + "reference": "https://github.com/zfkun/ComfyUI_zfkun", + "files": [ + "https://github.com/zfkun/ComfyUI_zfkun" + ], + "install_type": "git-clone", + "description": "A collection of nodes for common tools, including text preview, text translation (multi-platform, multi-language), image loader, webcamera capture." + }, + { + "author": "zcfrank1st", + "title": "Comfyui-Toolbox", + "reference": "https://github.com/zcfrank1st/Comfyui-Toolbox", + "files": [ + "https://github.com/zcfrank1st/Comfyui-Toolbox" + ], + "install_type": "git-clone", + "description": "Nodes:Preview Json, Save Json, Test Json Preview, ... preview and save nodes" + }, + { + "author": "talesofai", + "title": "ComfyUI Browser", + "reference": "https://github.com/talesofai/comfyui-browser", + "files": [ + "https://github.com/talesofai/comfyui-browser" + ], + "install_type": "git-clone", + "description": "This is an image/video/workflow browser and manager for ComfyUI. You could add image/video/workflow to collections and load it to ComfyUI. You will be able to use your collections everywhere." + }, + { + "author": "yolain", + "title": "ComfyUI Easy Use", + "reference": "https://github.com/yolain/ComfyUI-Easy-Use", + "files": [ + "https://github.com/yolain/ComfyUI-Easy-Use" + ], + "install_type": "git-clone", + "description": "To enhance the usability of ComfyUI, optimizations and integrations have been implemented for several commonly used nodes." + }, + { + "author": "bruefire", + "title": "ComfyUI Sequential Image Loader", + "reference": "https://github.com/bruefire/ComfyUI-SeqImageLoader", + "files": [ + "https://github.com/bruefire/ComfyUI-SeqImageLoader" + ], + "install_type": "git-clone", + "description": "This is an extension node for ComfyUI that allows you to load frames from a video in bulk and perform masking and sketching on each frame through a GUI." + }, + { + "author": "mmaker", + "title": "Color Enhance", + "reference": "https://git.mmaker.moe/mmaker/sd-webui-color-enhance", + "files": [ + "https://git.mmaker.moe/mmaker/sd-webui-color-enhance" + ], + "install_type": "git-clone", + "description": "Node: Color Enhance, Color Blend. This is the same algorithm GIMP/GEGL uses for color enhancement. The gist of this implementation is that it converts the color space to CIELCh(ab) and normalizes the chroma (or [colorfulness](https://en.wikipedia.org/wiki/Colorfulness)] component. Original source can be found in the link below." + }, + { + "author": "modusCell", + "title": "Preset Dimensions", + "reference": "https://github.com/modusCell/ComfyUI-dimension-node-modusCell", + "files": [ + "https://github.com/modusCell/ComfyUI-dimension-node-modusCell" + ], + "install_type": "git-clone", + "description": "Simple node for sharing latent image size between nodes. Preset dimensions for SD and XL." + }, + { + "author": "aria1th", + "title": "ComfyUI-LogicUtils", + "reference": "https://github.com/aria1th/ComfyUI-LogicUtils", + "files": [ + "https://github.com/aria1th/ComfyUI-LogicUtils" + ], + "install_type": "git-clone", + "description": "Nodes:UniformRandomFloat..., RandomShuffleInt, YieldableIterator..., LogicGate..., Add..., MergeString, MemoryNode, ..." + }, + { + "author": "MitoshiroPJ", + "title": "ComfyUI Slothful Attention", + "reference": "https://github.com/MitoshiroPJ/comfyui_slothful_attention", + "files": [ + "https://github.com/MitoshiroPJ/comfyui_slothful_attention" + ], + "install_type": "git-clone", + "description": "This custom node allow controlling output without training. The reducing method is similar to [a/Spatial-Reduction Attention](https://paperswithcode.com/method/spatial-reduction-attention), but generating speed may not be increased on typical image sizes due to overheads. (In some cases, slightly slower)" + }, + { + "author": "brianfitzgerald", + "title": "StyleAligned for ComfyUI", + "reference": "https://github.com/brianfitzgerald/style_aligned_comfy", + "files": [ + "https://github.com/brianfitzgerald/style_aligned_comfy" + ], + "install_type": "git-clone", + "description": "Implementation of the [a/StyleAligned](https://style-aligned-gen.github.io/) paper for ComfyUI. This node allows you to apply a consistent style to all images in a batch; by default it will use the first image in the batch as the style reference, forcing all other images to be consistent with it." + }, + { + "author": "deroberon", + "title": "demofusion-comfyui", + "id": "demofusion", + "reference": "https://github.com/deroberon/demofusion-comfyui", + "files": [ + "https://github.com/deroberon/demofusion-comfyui" + ], + "install_type": "git-clone", + "description": "The Demofusion Custom Node is a wrapper that adapts the work and implementation of the [a/DemoFusion](https://ruoyidu.github.io/demofusion/demofusion.html) technique created and implemented by Ruoyi Du to the Comfyui environment." + }, + { + "author": "deroberon", + "title": "StableZero123-comfyui", + "reference": "https://github.com/deroberon/StableZero123-comfyui", + "files": [ + "https://github.com/deroberon/StableZero123-comfyui" + ], + "install_type": "git-clone", + "description": "StableZero123 is a node wrapper that uses the model and technique provided [here](https://github.com/SUDO-AI-3D/zero123plus/). It uses the Zero123plus model to generate 3D views using just one image." + }, + { + "author": "glifxyz", + "title": "ComfyUI-GlifNodes", + "id": "glif", + "reference": "https://github.com/glifxyz/ComfyUI-GlifNodes", + "files": [ + "https://github.com/glifxyz/ComfyUI-GlifNodes" + ], + "install_type": "git-clone", + "description": "Nodes:Consistency VAE Decoder." + }, + { + "author": "concarne000", + "title": "ConCarneNode", + "reference": "https://github.com/concarne000/ConCarneNode", + "files": [ + "https://github.com/concarne000/ConCarneNode" + ], + "install_type": "git-clone", + "description": "Nodes:Bing Image Grabber, Zephyr chat, Hermes Chat" + }, + { + "author": "Aegis72", + "title": "AegisFlow Utility Nodes", + "id": "aegis", + "reference": "https://github.com/aegis72/aegisflow_utility_nodes", + "files": [ + "https://github.com/aegis72/aegisflow_utility_nodes" + ], + "install_type": "git-clone", + "description": "These nodes will be placed in comfyui/custom_nodes/aegisflow and contains the image passer (accepts an image as either wired or wirelessly, input and passes it through. Latent passer does the same for latents, and the Preprocessor chooser allows a passthrough image and 10 controlnets to be passed in AegisFlow Shima. The inputs on the Preprocessor chooser should not be renamed if you intend to accept image inputs wirelessly through UE nodes. It can be done, but the send node input regex for each controlnet preprocessor column must also be changed." + }, + { + "author": "Aegis72", + "title": "ComfyUI-styles-all", + "id": "styles-all", + "reference": "https://github.com/aegis72/comfyui-styles-all", + "files": [ + "https://github.com/aegis72/comfyui-styles-all" + ], + "install_type": "git-clone", + "description": "This is a straight clone of Azazeal04's all-in-one styler menu, which was removed from gh on Jan 21, 2024. I have made no changes to the files at all." + }, + { + "author": "glibsonoran", + "title": "Plush-for-ComfyUI", + "id": "plush", + "reference": "https://github.com/glibsonoran/Plush-for-ComfyUI", + "files": [ + "https://github.com/glibsonoran/Plush-for-ComfyUI" + ], + "install_type": "git-clone", + "description": "Nodes: Style Prompt, OAI Dall_e Image. Plush contains two OpenAI enabled nodes: Style Prompt: Takes your prompt and the art style you specify and generates a prompt from ChatGPT3 or 4 that Stable Diffusion can use to generate an image in that style. OAI Dall_e 3: Takes your prompt and parameters and produces a Dall_e3 image in ComfyUI." + }, + { + "author": "vienteck", + "title": "ComfyUI-Chat-GPT-Integration", + "reference": "https://github.com/vienteck/ComfyUI-Chat-GPT-Integration", + "files": [ + "https://github.com/vienteck/ComfyUI-Chat-GPT-Integration" + ], + "install_type": "git-clone", + + "description": "This extension is a reimagined version based on the [a/ComfyUI-QualityOfLifeSuit_Omar92](https://github.com/omar92/ComfyUI-QualityOfLifeSuit_Omar92) extension, and it supports integration with ChatGPT through the new OpenAI API.\nNOTE: See detailed installation instructions on the [a/repository](https://github.com/vienteck/ComfyUI-Chat-GPT-Integration)." + }, + { + "author": "MNeMoNiCuZ", + "title": "ComfyUI-mnemic-nodes", + "id": "mnemic", + "reference": "https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes", + "files": [ + "https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Save Text File, Download Image from URL, Groq LLM API, Generate Negative Prompt (experimental)" + }, + { + "author": "AI2lab", + "title": "comfyUI-tool-2lab", + "id": "tool-2lab", + "reference": "https://github.com/AI2lab/comfyUI-tool-2lab", + "files": [ + "https://github.com/AI2lab/comfyUI-tool-2lab" + ], + "install_type": "git-clone", + "description": "tool set for developing workflow and publish to web api server" + }, + { + "author": "AI2lab", + "title": "comfyUI-DeepSeek-2lab", + "id": "deepseek", + "reference": "https://github.com/AI2lab/comfyUI-DeepSeek-2lab", + "files": [ + "https://github.com/AI2lab/comfyUI-DeepSeek-2lab" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of DeepSeek for ComfyUI" + }, + { + "author": "AI2lab", + "title": "comfyUI-siliconflow-api-2lab", + "id": "siliconflow", + "reference": "https://github.com/AI2lab/comfyUI-siliconflow-api-2lab", + "files": [ + "https://github.com/AI2lab/comfyUI-siliconflow-api-2lab" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of siliconflow API for ComfyUI\nHow to use:apply api key in :https://cloud.siliconflow.cn/\nadd api key in config.json" + }, + { + "author": "SpaceKendo", + "title": "Text to video for Stable Video Diffusion in ComfyUI", + "id": "svd-txt2vid", + "reference": "https://github.com/SpaceKendo/ComfyUI-svd_txt2vid", + "files": [ + "https://github.com/SpaceKendo/ComfyUI-svd_txt2vid" + ], + "install_type": "git-clone", + "description": "This is node replaces the init_image conditioning for the [a/Stable Video Diffusion](https://github.com/Stability-AI/generative-models) image to video model with text embeds, together with a conditioning frame. The conditioning frame is a set of latents." + }, + { + "author": "NimaNzrii", + "title": "comfyui-popup_preview", + "id": "popup-preview", + "reference": "https://github.com/NimaNzrii/comfyui-popup_preview", + "files": [ + "https://github.com/NimaNzrii/comfyui-popup_preview" + ], + "install_type": "git-clone", + "description": "popup preview for comfyui" + }, + { + "author": "NimaNzrii", + "title": "comfyui-photoshop", + "id": "comfy-photoshop", + "reference": "https://github.com/NimaNzrii/comfyui-photoshop", + "files": [ + "https://github.com/NimaNzrii/comfyui-photoshop" + ], + "install_type": "git-clone", + "description": "Powerfull bridge to Photoshop by NimaNzrii" + }, + { + "author": "Rui", + "title": "RUI-Nodes", + "id": "rui-nodes", + "reference": "https://github.com/rui40000/RUI-Nodes", + "files": [ + "https://github.com/rui40000/RUI-Nodes" + ], + "install_type": "git-clone", + "description": "Rui's workflow-specific custom node, written using GPT." + }, + { + "author": "dmarx", + "title": "ComfyUI-Keyframed", + "id": "keyframed", + "reference": "https://github.com/dmarx/ComfyUI-Keyframed", + "files": [ + "https://github.com/dmarx/ComfyUI-Keyframed" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes to facilitate parameter/prompt keyframing using comfyui nodes for defining and manipulating parameter curves. Essentially provides a ComfyUI interface to the [a/keyframed](https://github.com/dmarx/keyframed) library." + }, + { + "author": "dmarx", + "title": "ComfyUI-AudioReactive", + "id": "audioreactive", + "reference": "https://github.com/dmarx/ComfyUI-AudioReactive", + "files": [ + "https://github.com/dmarx/ComfyUI-AudioReactive" + ], + "install_type": "git-clone", + "description": "porting audioreactivity pipeline from vktrs to comfyui." + }, + { + "author": "TripleHeadedMonkey", + "title": "ComfyUI_MileHighStyler", + "id": "milehighstyler", + "reference": "https://github.com/TripleHeadedMonkey/ComfyUI_MileHighStyler", + "files": [ + "https://github.com/TripleHeadedMonkey/ComfyUI_MileHighStyler" + ], + "install_type": "git-clone", + "description": "This extension provides various SDXL Prompt Stylers. See: [a/youtube](https://youtu.be/WBHI-2uww7o?si=dijvDaUI4nmx4VkF)" + }, + { + "author": "BennyKok", + "title": "ComfyUI Deploy", + "id": "comfy-deploy", + "reference": "https://github.com/BennyKok/comfyui-deploy", + "files": [ + "https://github.com/BennyKok/comfyui-deploy" + ], + "install_type": "git-clone", + "description": "Open source comfyui deployment platform, a vercel for generative workflow infra." + }, + { + "author": "florestefano1975", + "title": "comfyui-portrait-master", + "id": "portrait-master", + "reference": "https://github.com/florestefano1975/comfyui-portrait-master", + "files": [ + "https://github.com/florestefano1975/comfyui-portrait-master" + ], + "install_type": "git-clone", + "description": "ComfyUI Portrait Master. A node designed to help AI image creators to generate prompts for human portraits." + }, + { + "author": "florestefano1975", + "title": "comfyui-prompt-composer", + "id": "prompt-composer", + "reference": "https://github.com/florestefano1975/comfyui-prompt-composer", + "files": [ + "https://github.com/florestefano1975/comfyui-prompt-composer" + ], + "install_type": "git-clone", + "description": "A suite of tools for prompt management. Combining nodes helps the user sequence strings for prompts, also creating logical groupings if necessary. Individual nodes can be chained together in any order." + }, + { + "author": "florestefano1975", + "title": "ComfyUI StabilityAI Suite", + "id": "sai-suite", + "reference": "https://github.com/florestefano1975/ComfyUI-StabilityAI-Suite", + "files": [ + "https://github.com/florestefano1975/ComfyUI-StabilityAI-Suite" + ], + "install_type": "git-clone", + "description": "This fork of the official StabilityAI repository contains a number of enhancements and implementations." + }, + { + "author": "florestefano1975", + "title": "ComfyUI HiDiffusion", + "id": "hidiffusion", + "reference": "https://github.com/florestefano1975/ComfyUI-HiDiffusion", + "files": [ + "https://github.com/florestefano1975/ComfyUI-HiDiffusion" + ], + "install_type": "git-clone", + "description": "Simple custom nodes for testing and use HiDiffusion technology: https://github.com/megvii-research/HiDiffusion/" + }, + { + "author": "mozman", + "title": "ComfyUI_mozman_nodes", + "id": "mozman-nodes", + "reference": "https://github.com/mozman/ComfyUI_mozman_nodes", + "files": [ + "https://github.com/mozman/ComfyUI_mozman_nodes" + ], + "install_type": "git-clone", + "description": "This extension provides styler nodes for SDXL.\n\nNOTE: Due to the dynamic nature of node name definitions, ComfyUI-Manager cannot recognize the node list from this extension. The Missing nodes and Badge features are not available for this extension." + }, + { + "author": "rcsaquino", + "title": "rcsaquino/comfyui-custom-nodes", + "id": "rcsaquino-nodes", + "reference": "https://github.com/rcsaquino/comfyui-custom-nodes", + "files": [ + "https://github.com/rcsaquino/comfyui-custom-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: VAE Processor, VAE Loader, Background Remover" + }, + { + "author": "rcfcu2000", + "title": "zhihuige-nodes-comfyui", + "id": "zhihuige-nodes", + "reference": "https://github.com/rcfcu2000/zhihuige-nodes-comfyui", + "files": [ + "https://github.com/rcfcu2000/zhihuige-nodes-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes: Combine ZHGMasks, Cover ZHGMasks, ZHG FaceIndex, ZHG SaveImage, ZHG SmoothEdge, ZHG GetMaskArea, ..." + }, + { + "author": "IDGallagher", + "title": "IG Interpolation Nodes", + "id": "ig-nodes", + "reference": "https://github.com/IDGallagher/ComfyUI-IG-Nodes", + "files": [ + "https://github.com/IDGallagher/ComfyUI-IG-Nodes" + ], + "install_type": "git-clone", + "description": "Custom nodes to aid in the exploration of Latent Space" + }, + { + "author": "violet-chen", + "title": "comfyui-psd2png", + "id": "psd2png", + "reference": "https://github.com/violet-chen/comfyui-psd2png", + "files": [ + "https://github.com/violet-chen/comfyui-psd2png" + ], + "install_type": "git-clone", + "description": "Nodes: Psd2Png." + }, + { + "author": "lldacing", + "title": "comfyui-easyapi-nodes", + "id": "easyapi", + "reference": "https://github.com/lldacing/comfyui-easyapi-nodes", + "files": [ + "https://github.com/lldacing/comfyui-easyapi-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Base64 To Image, Image To Base64, Load Image To Base64." + }, + { + "author": "CosmicLaca", + "title": "Primere nodes for ComfyUI", + "id": "primere", + "reference": "https://github.com/CosmicLaca/ComfyUI_Primere_Nodes", + "files": [ + "https://github.com/CosmicLaca/ComfyUI_Primere_Nodes" + ], + "install_type": "git-clone", + "description": "This extension provides various utility nodes. Inputs(prompt, styles, dynamic, merger, ...), Outputs(style pile), Dashboard(selectors, loader, switch, ...), Networks(LORA, Embedding, Hypernetwork), Visuals(visual selectors, )" + }, + { + "author": "RenderRift", + "title": "ComfyUI-RenderRiftNodes", + "id": "renderrift", + "reference": "https://github.com/RenderRift/ComfyUI-RenderRiftNodes", + "files": [ + "https://github.com/RenderRift/ComfyUI-RenderRiftNodes" + ], + "install_type": "git-clone", + "description": "Nodes:RR_Date_Folder_Format, RR_Image_Metadata_Overlay, RR_VideoPathMetaExtraction, RR_DisplayMetaOptions. This extension provides nodes designed to enhance the Animatediff workflow." + }, + { + "author": "OpenArt-AI", + "title": "ComfyUI Assistant", + "id": "openart", + "reference": "https://github.com/OpenArt-AI/ComfyUI-Assistant", + "files": [ + "https://github.com/OpenArt-AI/ComfyUI-Assistant" + ], + "install_type": "git-clone", + "description": "ComfyUI Assistant is your one stop plugin for everything you need to get started with comfy-ui. Now it provides useful courses, tutorials, and basic templates." + }, + { + "author": "ttulttul", + "title": "ComfyUI Iterative Mixing Nodes", + "id": "itermix", + "reference": "https://github.com/ttulttul/ComfyUI-Iterative-Mixer", + "files": [ + "https://github.com/ttulttul/ComfyUI-Iterative-Mixer" + ], + "install_type": "git-clone", + "description": "Nodes to use Florence2 VLM for image vision tasks: object detection, captioning, segmentation and ocr" + }, + { + "author": "ttulttul", + "title": "ComfyUI-Tensor-Operations", + "id": "tensorop", + "reference": "https://github.com/ttulttul/ComfyUI-Tensor-Operations", + "files": [ + "https://github.com/ttulttul/ComfyUI-Tensor-Operations" + ], + "install_type": "git-clone", + "description": "This repo contains nodes for ComfyUI that implement some helpful operations on tensors, such as normalization." + }, + { + "author": "jitcoder", + "title": "LoraInfo", + "id": "lorainfo", + "reference": "https://github.com/jitcoder/lora-info", + "files": [ + "https://github.com/jitcoder/lora-info" + ], + "install_type": "git-clone", + "description": "Shows Lora information from CivitAI and outputs trigger words and example prompt" + }, + { + "author": "ceruleandeep", + "title": "ComfyUI LLaVA Captioner", + "id": "llava-captioner", + "reference": "https://github.com/ceruleandeep/ComfyUI-LLaVA-Captioner", + "files": [ + "https://github.com/ceruleandeep/ComfyUI-LLaVA-Captioner" + ], + "install_type": "git-clone", + "description": "A ComfyUI extension for chatting with your images. Runs on your own system, no external services used, no filter. Uses the [a/LLaVA multimodal LLM](https://llava-vl.github.io/) so you can give instructions or ask questions in natural language. It's maybe as smart as GPT3.5, and it can see." + }, + { + "author": "styler00dollar", + "title": "ComfyUI-sudo-latent-upscale", + "id": "sudo-latent-upscale", + "reference": "https://github.com/styler00dollar/ComfyUI-sudo-latent-upscale", + "files": [ + "https://github.com/styler00dollar/ComfyUI-sudo-latent-upscale" + ], + "install_type": "git-clone", + "description": "Directly upscaling inside the latent space. Model was trained for SD1.5 and drawn content. Might add new architectures or update models at some point. This took heavy inspriration from [city96/SD-Latent-Upscaler](https://github.com/city96/SD-Latent-Upscaler) and [Ttl/ComfyUi_NNLatentUpscale](https://github.com/Ttl/ComfyUi_NNLatentUpscale). " + }, + { + "author": "styler00dollar", + "title": "ComfyUI-deepcache", + "id": "deepcache", + "reference": "https://github.com/styler00dollar/ComfyUI-deepcache", + "files": [ + "https://github.com/styler00dollar/ComfyUI-deepcache" + ], + "install_type": "git-clone", + "description": "This extension provides nodes for [a/DeepCache: Accelerating Diffusion Models for Free](https://arxiv.org/abs/2312.00858)\nNOTE:Original code can be found [a/here](https://gist.github.com/laksjdjf/435c512bc19636e9c9af4ee7bea9eb86). Full credit to laksjdjf for sharing the code. " + }, + { + "author": "HarroweD and quadmoon", + "title": "Harrlogos Prompt Builder Node", + "id": "harrlogos-prompt-builder", + "reference": "https://github.com/NotHarroweD/Harronode", + "nodename_pattern": "Harronode", + "files": [ + "https://github.com/NotHarroweD/Harronode" + ], + "install_type": "git-clone", + "description": "Harronode is a custom node designed to build prompts easily for use with the Harrlogos SDXL LoRA. This Node simplifies the process of crafting prompts and makes all built in activation terms available at your fingertips." + }, + { + "author": "Limitex", + "title": "ComfyUI-Calculation", + "id": "calc", + "reference": "https://github.com/Limitex/ComfyUI-Calculation", + "files": [ + "https://github.com/Limitex/ComfyUI-Calculation" + ], + "install_type": "git-clone", + "description": "Nodes: Center Calculation. Improved Numerical Calculation for ComfyUI" + }, + { + "author": "Limitex", + "title": "ComfyUI-Diffusers", + "id": "diffusers", + "reference": "https://github.com/Limitex/ComfyUI-Diffusers", + "files": [ + "https://github.com/Limitex/ComfyUI-Diffusers" + ], + "install_type": "git-clone", + "description": "This extension enables the use of the diffuser pipeline in ComfyUI." + }, + { + "author": "aiXander", + "title": "Various custom nodes by Eden.art", + "id": "Eden", + "reference": "https://github.com/edenartlab/eden_comfy_pipelines", + "files": [ + "https://github.com/edenartlab/eden_comfy_pipelines" + ], + "install_type": "git-clone", + "description": "A set of custom nodes for various purposed, maintained by Eden.art" + }, + { + "author": "pkpk", + "title": "ComfyUI-SaveAVIF", + "id": "saveavif", + "reference": "https://github.com/pkpkTech/ComfyUI-SaveAVIF", + "files": [ + "https://github.com/pkpkTech/ComfyUI-SaveAVIF" + ], + "install_type": "git-clone", + "description": "A custom node on ComfyUI that saves images in AVIF format. Workflow can be loaded from images saved at this node." + }, + { + "author": "pkpkTech", + "title": "ComfyUI-ngrok", + "id": "ngrok", + "reference": "https://github.com/pkpkTech/ComfyUI-ngrok", + "files": [ + "https://github.com/pkpkTech/ComfyUI-ngrok" + ], + "install_type": "git-clone", + "description": "Use ngrok to allow external access to ComfyUI.\nNOTE: Need to manually modify a token inside the __init__.py file." + }, + { + "author": "pkpk", + "title": "ComfyUI-TemporaryLoader", + "id": "temploader", + "reference": "https://github.com/pkpkTech/ComfyUI-TemporaryLoader", + "files": [ + "https://github.com/pkpkTech/ComfyUI-TemporaryLoader" + ], + "install_type": "git-clone", + "description": "This is a custom node of ComfyUI that downloads and loads models from the input URL. The model is temporarily downloaded into memory and not saved to storage.\nThis could be useful when trying out models or when using various models on machines with limited storage. Since the model is downloaded into memory, expect higher memory usage than usual." + }, + { + "author": "pkpkTech", + "title": "ComfyUI-SaveQueues", + "id": "savequeues", + "reference": "https://github.com/pkpkTech/ComfyUI-SaveQueues", + "files": [ + "https://github.com/pkpkTech/ComfyUI-SaveQueues" + ], + "install_type": "git-clone", + "description": "Add a button to the menu to save and load the running queue and the pending queues.\nThis is intended to be used when you want to exit ComfyUI with queues still remaining." + }, + { + "author": "Crystian", + "title": "Crystools", + "id": "crytools", + "reference": "https://github.com/crystian/ComfyUI-Crystools", + "files": [ + "https://github.com/crystian/ComfyUI-Crystools" + ], + "nodename_pattern": " \\[Crystools\\]$", + "install_type": "git-clone", + "description": "With this suit, you can see the resources monitor, progress bar & time elapsed, metadata and compare between two images, compare between two JSONs, show any value to console/display, pipes, and more!\nThis provides better nodes to load/save images, previews, etc, and see \"hidden\" data without loading a new workflow." + }, + { + "author": "Crystian", + "title": "Crystools-save", + "id": "crytools-save", + "reference": "https://github.com/crystian/ComfyUI-Crystools-save", + "files": [ + "https://github.com/crystian/ComfyUI-Crystools-save" + ], + "install_type": "git-clone", + "description": "With this quality of life extension, you can save your workflow with a specific name and include additional details such as the author, a description, and the version (in metadata/json). Important: When you share your workflow (via png/json), others will be able to see your information!" + }, + { + "author": "Kangkang625", + "title": "ComfyUI-Paint-by-Example", + "id": "paint-by-example", + "reference": "https://github.com/Kangkang625/ComfyUI-paint-by-example", + "pip": ["diffusers"], + "files": [ + "https://github.com/Kangkang625/ComfyUI-paint-by-example" + ], + "install_type": "git-clone", + "description": "This repo is a simple implementation of [a/Paint-by-Example](https://github.com/Fantasy-Studio/Paint-by-Example) based on its [a/huggingface pipeline](https://huggingface.co/Fantasy-Studio/Paint-by-Example)." + }, + { + "author": "54rt1n", + "title": "ComfyUI-DareMerge", + "id": "daremerge", + "reference": "https://github.com/54rt1n/ComfyUI-DareMerge", + "files": [ + "https://github.com/54rt1n/ComfyUI-DareMerge" + ], + "install_type": "git-clone", + "description": "Merge two checkpoint models by dare ties [a/(https://github.com/yule-BUAA/MergeLM)](https://github.com/yule-BUAA/MergeLM), sort of." + }, + { + "author": "an90ray", + "title": "ComfyUI_RErouter_CustomNodes", + "id": "rerouter", + "reference": "https://github.com/an90ray/ComfyUI_RErouter_CustomNodes", + "files": [ + "https://github.com/an90ray/ComfyUI_RErouter_CustomNodes" + ], + "install_type": "git-clone", + "description": "Nodes: RErouter, String (RE), Int (RE)" + }, + { + "author": "jesenzhang", + "title": "ComfyUI_StreamDiffusion", + "id": "streamdiffusion", + "reference": "https://github.com/jesenzhang/ComfyUI_StreamDiffusion", + "files": [ + "https://github.com/jesenzhang/ComfyUI_StreamDiffusion" + ], + "install_type": "git-clone", + "description": "This is a simple implementation StreamDiffusion(A Pipeline-Level Solution for Real-Time Interactive Generation) for ComfyUI" + }, + { + "author": "ai-liam", + "title": "LiamUtil (single node)", + "id": "liam-util-single", + "reference": "https://github.com/ai-liam/comfyui_liam_util", + "files": [ + "https://github.com/ai-liam/comfyui_liam_util" + ], + "install_type": "git-clone", + "description": "Nodes: LiamLoadImage. This node provides the capability to load images from a URL." + }, + { + "author": "ai-liam", + "title": "LiamUtil", + "id": "liam-util", + "reference": "https://github.com/ai-liam/comfyui-liam", + "files": [ + "https://github.com/ai-liam/comfyui-liam" + ], + "install_type": "git-clone", + "description": "Nodes: LiamLibLoadImage, LiamLibImageToGray, LiamLibSaveImg, LiamLibFillImage, PreviewReliefImage, GetBetterDepthImage, LiamLibSaveText" + }, + { + "author": "Ryuukeisyou", + "title": "comfyui_face_parsing", + "id": "face-parsing", + "reference": "https://github.com/Ryuukeisyou/comfyui_face_parsing", + "files": [ + "https://github.com/Ryuukeisyou/comfyui_face_parsing" + ], + "install_type": "git-clone", + "description": "This is a set of custom nodes for ComfyUI. The nodes utilize the [a/face parsing model](https://huggingface.co/jonathandinu/face-parsing) to provide detailed segmantation of face. To improve face segmantation accuracy, [a/yolov8 face model](https://huggingface.co/Bingsu/adetailer/) is used to first extract face from an image. There are also auxiliary nodes for image and mask processing. A guided filter is also provided for skin smoothing." + }, + { + "author": "tocubed", + "title": "ComfyUI-AudioReactor", + "id": "audioreactor", + "reference": "https://github.com/tocubed/ComfyUI-AudioReactor", + "files": [ + "https://github.com/tocubed/ComfyUI-AudioReactor" + ], + "install_type": "git-clone", + "description": "Nodes: Shadertoy, Load Audio (from Path), Audio Frame Transform (Shadertoy), Audio Frame Transform (Beats)" + }, + { + "author": "ntc-ai", + "title": "ComfyUI - Apply LoRA Stacker with DARE", + "reference": "https://github.com/ntc-ai/ComfyUI-DARE-LoRA-Merge", + "files": [ + "https://github.com/ntc-ai/ComfyUI-DARE-LoRA-Merge" + ], + "install_type": "git-clone", + "description": "An experiment about combining multiple LoRAs with [a/DARE](https://arxiv.org/pdf/2311.03099.pdf)" + }, + { + "author": "wwwins", + "title": "ComfyUI-Simple-Aspect-Ratio", + "reference": "https://github.com/wwwins/ComfyUI-Simple-Aspect-Ratio", + "files": [ + "https://github.com/wwwins/ComfyUI-Simple-Aspect-Ratio" + ], + "install_type": "git-clone", + "description": "Nodes:SimpleAspectRatio" + }, + { + "author": "ownimage", + "title": "ComfyUI-ownimage", + "reference": "https://github.com/ownimage/ComfyUI-ownimage", + "files": [ + "https://github.com/ownimage/ComfyUI-ownimage" + ], + "install_type": "git-clone", + "description": "Nodes:Caching Image Loader." + }, + { + "author": "Millyarde", + "title": "Pomfy - Photoshop and ComfyUI 2-way sync", + "reference": "https://github.com/Millyarde/Pomfy", + "files": [ + "https://github.com/Millyarde/Pomfy" + ], + "install_type": "git-clone", + "description": "Photoshop custom nodes inside of ComfyUi, send and get data via Photoshop UXP plugin for cross platform support" + }, + { + "author": "Ryuukeisyou", + "title": "comfyui_io_helpers", + "reference": "https://github.com/Ryuukeisyou/comfyui_io_helpers", + "files": [ + "https://github.com/Ryuukeisyou/comfyui_io_helpers" + ], + "install_type": "git-clone", + "description": "Nodes:ImageLoadFromBase64, ImageLoadByPath, ImageLoadAsMaskByPath, ImageSaveToPath, ImageSaveAsBase64." + }, + { + "author": "flowtyone", + "title": "ComfyUI-Flowty-LDSR", + "reference": "https://github.com/flowtyone/ComfyUI-Flowty-LDSR", + "files": [ + "https://github.com/flowtyone/ComfyUI-Flowty-LDSR" + ], + "install_type": "git-clone", + "description": "This is a custom node that lets you take advantage of Latent Diffusion Super Resolution (LDSR) models inside ComfyUI." + }, + { + "author": "flowtyone", + "title": "ComfyUI-Flowty-TripoSR", + "reference": "https://github.com/flowtyone/ComfyUI-Flowty-TripoSR", + "files": [ + "https://github.com/flowtyone/ComfyUI-Flowty-TripoSR" + ], + "install_type": "git-clone", + "description": "This is a custom node that lets you use TripoSR right from ComfyUI.\n[a/TripoSR](https://github.com/VAST-AI-Research/TripoSR) is a state-of-the-art open-source model for fast feedforward 3D reconstruction from a single image, collaboratively developed by Tripo AI and Stability AI. (TL;DR it creates a 3d model from an image.)" + }, + { + "author": "flowtyone", + "title": "ComfyUI-Flowty-CRM", + "reference": "https://github.com/flowtyone/ComfyUI-Flowty-CRM", + "files": [ + "https://github.com/flowtyone/ComfyUI-Flowty-CRM" + ], + "install_type": "git-clone", + "description": "This is a custom node that lets you use Convolutional Reconstruction Models right from ComfyUI.\n[a/CRM](https://ml.cs.tsinghua.edu.cn/~zhengyi/CRM/) is a high-fidelity feed-forward single image-to-3D generative model." + }, + { + "author": "massao000", + "title": "ComfyUI_aspect_ratios", + "reference": "https://github.com/massao000/ComfyUI_aspect_ratios", + "files": [ + "https://github.com/massao000/ComfyUI_aspect_ratios" + ], + "install_type": "git-clone", + "description": "Aspect ratio selector for ComfyUI based on [a/sd-webui-ar](https://github.com/alemelis/sd-webui-ar?tab=readme-ov-file)." + }, + { + "author": "SiliconFlow", + "title": "OneDiff Nodes", + "id": "onddiff", + "reference": "https://github.com/siliconflow/onediff_comfy_nodes", + "files": [ + "https://github.com/siliconflow/onediff_comfy_nodes" + ], + "install_type": "git-clone", + "description": "[a/Onediff](https://github.com/siliconflow/onediff) ComfyUI Nodes." + }, + { + "author": "hinablue", + "title": "ComfyUI 3D Pose Editor", + "id": "3d-pose-editor", + "reference": "https://github.com/hinablue/ComfyUI_3dPoseEditor", + "files": [ + "https://github.com/hinablue/ComfyUI_3dPoseEditor" + ], + "install_type": "git-clone", + "description": "Nodes:3D Pose Editor" + }, + { + "author": "chaojie", + "title": "ComfyUI-CameraCtrl-Wrapper", + "id": "cameractrl-wrapper", + "reference": "https://github.com/chaojie/ComfyUI-CameraCtrl-Wrapper", + "files": [ + "https://github.com/chaojie/ComfyUI-CameraCtrl-Wrapper" + ], + "install_type": "git-clone", + "description": "ComfyUI-CameraCtrl-Wrapper" + }, + { + "author": "chaojie", + "title": "ComfyUI-EasyAnimate", + "id": "easyanimate", + "reference": "https://github.com/chaojie/ComfyUI-EasyAnimate", + "files": [ + "https://github.com/chaojie/ComfyUI-EasyAnimate" + ], + "install_type": "git-clone", + "description": "ComfyUI-EasyAnimate" + }, + { + "author": "chaojie", + "title": "ComfyUI_StreamingT2V", + "id": "streamingt2v", + "reference": "https://github.com/chaojie/ComfyUI_StreamingT2V", + "files": [ + "https://github.com/chaojie/ComfyUI_StreamingT2V" + ], + "install_type": "git-clone", + "description": "ComfyUI_StreamingT2V" + }, + { + "author": "chaojie", + "title": "ComfyUI-Open-Sora-Plan", + "id": "opensora-plan", + "reference": "https://github.com/chaojie/ComfyUI-Open-Sora-Plan", + "files": [ + "https://github.com/chaojie/ComfyUI-Open-Sora-Plan" + ], + "install_type": "git-clone", + "description": "ComfyUI node for [a/Open-Sora-Plan](https://github.com/PKU-YuanGroup/Open-Sora-Plan)" + }, + { + "author": "chaojie", + "title": "ComfyUI-MuseTalk", + "id": "musetalk-chaojie", + "reference": "https://github.com/chaojie/ComfyUI-MuseTalk", + "files": [ + "https://github.com/chaojie/ComfyUI-MuseTalk" + ], + "install_type": "git-clone", + "description": "ComfyUI MuseTalk" + }, + { + "author": "chaojie", + "title": "ComfyUI-MuseV", + "id": "musev", + "reference": "https://github.com/chaojie/ComfyUI-MuseV", + "files": [ + "https://github.com/chaojie/ComfyUI-MuseV" + ], + "install_type": "git-clone", + "description": "ComfyUI MuseV" + }, + { + "author": "chaojie", + "title": "ComfyUI-AniPortrait", + "id": "aniportrait", + "reference": "https://github.com/chaojie/ComfyUI-AniPortrait", + "files": [ + "https://github.com/chaojie/ComfyUI-AniPortrait" + ], + "install_type": "git-clone", + "description": "ComfyUI [a/AniPortrait](https://github.com/Zejun-Yang/AniPortrait)" + }, + { + "author": "chaojie", + "title": "ComfyUI-Img2Img-Turbo", + "id": "img2img-turbo", + "reference": "https://github.com/chaojie/ComfyUI-Img2Img-Turbo", + "files": [ + "https://github.com/chaojie/ComfyUI-Img2Img-Turbo" + ], + "install_type": "git-clone", + "description": "ComfyUI Img2Img-Turbo" + }, + { + "author": "chaojie", + "title": "ComfyUI-Champ", + "id": "champ", + "reference": "https://github.com/chaojie/ComfyUI-Champ", + "files": [ + "https://github.com/chaojie/ComfyUI-Champ" + ], + "install_type": "git-clone", + "description": "ComfyUI Champ" + }, + { + "author": "chaojie", + "title": "ComfyUI-Open-Sora", + "id": "opensora", + "reference": "https://github.com/chaojie/ComfyUI-Open-Sora", + "files": [ + "https://github.com/chaojie/ComfyUI-Open-Sora" + ], + "install_type": "git-clone", + "description": "ComfyUI Open Sora\nNOTE:only supports Linux now" + }, + { + "author": "chaojie", + "title": "ComfyUI-Trajectory", + "id": "trajectory", + "reference": "https://github.com/chaojie/ComfyUI-Trajectory", + "files": [ + "https://github.com/chaojie/ComfyUI-Trajectory" + ], + "install_type": "git-clone", + "description": "ComfyUI Trajectory" + }, + { + "author": "chaojie", + "title": "ComfyUI-dust3r", + "id": "dust3r", + "reference": "https://github.com/chaojie/ComfyUI-dust3r", + "files": [ + "https://github.com/chaojie/ComfyUI-dust3r" + ], + "install_type": "git-clone", + "description": "ComfyUI dust3r" + }, + { + "author": "chaojie", + "title": "ComfyUI-Gemma", + "id": "gamma", + "reference": "https://github.com/chaojie/ComfyUI-Gemma", + "files": [ + "https://github.com/chaojie/ComfyUI-Gemma" + ], + "install_type": "git-clone", + "description": "ComfyUI Gemma" + }, + { + "author": "chaojie", + "title": "ComfyUI-DynamiCrafter", + "id": "dynamicrafter-chaojie", + "reference": "https://github.com/chaojie/ComfyUI-DynamiCrafter", + "files": [ + "https://github.com/chaojie/ComfyUI-DynamiCrafter" + ], + "install_type": "git-clone", + "description": "Better Dynamic, Higher Resolution, and Stronger Coherence!" + }, + { + "author": "chaojie", + "title": "ComfyUI-Panda3d", + "id": "panda3d", + "reference": "https://github.com/chaojie/ComfyUI-Panda3d", + "files": [ + "https://github.com/chaojie/ComfyUI-Panda3d" + ], + "install_type": "git-clone", + "description": "ComfyUI 3d engine" + }, + { + "author": "chaojie", + "title": "ComfyUI-Pymunk", + "id": "pymunk", + "reference": "https://github.com/chaojie/ComfyUI-Pymunk", + "files": [ + "https://github.com/chaojie/ComfyUI-Pymunk" + ], + "install_type": "git-clone", + "description": "Pymunk is a easy-to-use pythonic 2d physics library that can be used whenever you need 2d rigid body physics from Python" + }, + { + "author": "chaojie", + "title": "ComfyUI-MotionCtrl", + "id": "motionctrl", + "reference": "https://github.com/chaojie/ComfyUI-MotionCtrl", + "files": [ + "https://github.com/chaojie/ComfyUI-MotionCtrl" + ], + "install_type": "git-clone", + "description": "Nodes: Download the weights of MotionCtrl [a/motionctrl.pth](https://huggingface.co/TencentARC/MotionCtrl/blob/main/motionctrl.pth) and put it to ComfyUI/models/checkpoints" + }, + { + "author": "chaojie", + "title": "ComfyUI-Motion-Vector-Extractor", + "id": "motion-vector-extractor", + "reference": "https://github.com/chaojie/ComfyUI-Motion-Vector-Extractor", + "files": [ + "https://github.com/chaojie/ComfyUI-Motion-Vector-Extractor" + ], + "install_type": "git-clone", + "description": "Nodes: that we currently provide the package only for x86-64 linux, such as Ubuntu or Debian, and Python 3.8, 3.9, and 3.10." + }, + { + "author": "chaojie", + "title": "ComfyUI-MotionCtrl-SVD", + "id": "motionctrl-svd", + "reference": "https://github.com/chaojie/ComfyUI-MotionCtrl-SVD", + "files": [ + "https://github.com/chaojie/ComfyUI-MotionCtrl-SVD" + ], + "install_type": "git-clone", + "description": "Nodes: Download the weights of MotionCtrl-SVD [a/motionctrl_svd.ckpt](https://huggingface.co/TencentARC/MotionCtrl/blob/main/motionctrl_svd.ckpt) and put it to ComfyUI/models/checkpoints" + }, + { + "author": "chaojie", + "title": "ComfyUI-DragAnything", + "id": "draganything", + "reference": "https://github.com/chaojie/ComfyUI-DragAnything", + "files": [ + "https://github.com/chaojie/ComfyUI-DragAnything" + ], + "install_type": "git-clone", + "description": "DragAnything" + }, + { + "author": "chaojie", + "title": "ComfyUI-DragNUWA", + "id": "dragnuwa", + "reference": "https://github.com/chaojie/ComfyUI-DragNUWA", + "files": [ + "https://github.com/chaojie/ComfyUI-DragNUWA" + ], + "install_type": "git-clone", + "description": "Nodes: Download the weights of DragNUWA [a/drag_nuwa_svd.pth](https://drive.google.com/file/d/1Z4JOley0SJCb35kFF4PCc6N6P1ftfX4i/view) and put it to ComfyUI/models/checkpoints/drag_nuwa_svd.pth\n[w/Due to changes in the torch package and versions of many other packages, it may disrupt your installation environment.]" + }, + { + "author": "chaojie", + "title": "ComfyUI-Moore-AnimateAnyone", + "id": "moore-animateanyone", + "reference": "https://github.com/chaojie/ComfyUI-Moore-AnimateAnyone", + "files": [ + "https://github.com/chaojie/ComfyUI-Moore-AnimateAnyone" + ], + "install_type": "git-clone", + "description": "Nodes: Run python tools/download_weights.py first to download weights automatically" + }, + { + "author": "chaojie", + "title": "ComfyUI-I2VGEN-XL", + "id": "i2vgen-xl", + "reference": "https://github.com/chaojie/ComfyUI-I2VGEN-XL", + "files": [ + "https://github.com/chaojie/ComfyUI-I2VGEN-XL" + ], + "install_type": "git-clone", + "description": "This is an implementation of [a/i2vgen-xl](https://github.com/ali-vilab/i2vgen-xl)" + }, + { + "author": "chaojie", + "title": "ComfyUI-LightGlue", + "id": "lightglue", + "reference": "https://github.com/chaojie/ComfyUI-LightGlue", + "files": [ + "https://github.com/chaojie/ComfyUI-LightGlue" + ], + "install_type": "git-clone", + "description": "This is an ComfyUI implementation of LightGlue to generate motion brush" + }, + { + "author": "chaojie", + "title": "ComfyUI-RAFT", + "id": "raft", + "reference": "https://github.com/chaojie/ComfyUI-RAFT", + "files": [ + "https://github.com/chaojie/ComfyUI-RAFT" + ], + "install_type": "git-clone", + "description": "This is an ComfyUI implementation of RAFT to generate motion brush" + }, + { + "author": "chaojie", + "title": "ComfyUI-LaVIT", + "id": "lavit", + "reference": "https://github.com/chaojie/ComfyUI-LaVIT", + "files": [ + "https://github.com/chaojie/ComfyUI-LaVIT" + ], + "install_type": "git-clone", + "description": "Nodes:VideoLaVITLoader, VideoLaVITT2V, VideoLaVITI2V, VideoLaVITI2VLong, VideoLaVITT2VLong, VideoLaVITI2I" + }, + { + "author": "chaojie", + "title": "ComfyUI-SimDA", + "id": "simda", + "reference": "https://github.com/chaojie/ComfyUI-SimDA", + "files": [ + "https://github.com/chaojie/ComfyUI-SimDA" + ], + "install_type": "git-clone", + "description": "Nodes:SimDATrain, SimDALoader, SimDARun, VHS_FILENAMES_STRING_SimDA" + }, + { + "author": "chaojie", + "title": "ComfyUI-Video-Editing-X-Attention", + "id": "video-editing-x-attention", + "reference": "https://github.com/chaojie/ComfyUI-Video-Editing-X-Attention", + "files": [ + "https://github.com/chaojie/ComfyUI-Video-Editing-X-Attention" + ], + "install_type": "git-clone", + "description": "Investigating the Effectiveness of Cross Attention to Unlock Zero-Shot Editing of Text-to-Video Diffusion Models" + }, + { + "author": "alexopus", + "title": "ComfyUI Image Saver", + "id": "image-saver", + "reference": "https://github.com/alexopus/ComfyUI-Image-Saver", + "files": [ + "https://github.com/alexopus/ComfyUI-Image-Saver" + ], + "install_type": "git-clone", + "description": "Allows you to save images with their generation metadata compatible with Civitai. Works with png, jpeg and webp. Stores LoRAs, models and embeddings hashes for resource recognition." + }, + { + "author": "kft334", + "title": "Knodes", + "id": "knodes", + "reference": "https://github.com/kft334/Knodes", + "files": [ + "https://github.com/kft334/Knodes" + ], + "install_type": "git-clone", + "description": "Nodes: Image(s) To Websocket (Base64), Load Image (Base64),Load Images (Base64)" + }, + { + "author": "MrForExample", + "title": "ComfyUI-3D-Pack", + "id": "3dpack", + "reference": "https://github.com/MrForExample/ComfyUI-3D-Pack", + "files": [ + "https://github.com/MrForExample/ComfyUI-3D-Pack" + ], + "nodename_pattern": "^\\[Comfy3D\\]", + "install_type": "git-clone", + "description": "An extensive node suite that enables ComfyUI to process 3D inputs (Mesh & UV Texture, etc) using cutting edge algorithms (3DGS, NeRF, etc.)\nNOTE: Pre-built python wheels can be download from [a/https://github.com/remsky/ComfyUI3D-Assorted-Wheels](https://github.com/remsky/ComfyUI3D-Assorted-Wheels)" + }, + { + "author": "Mr.ForExample", + "title": "ComfyUI-AnimateAnyone-Evolved", + "id": "animateanyone-evolved", + "reference": "https://github.com/MrForExample/ComfyUI-AnimateAnyone-Evolved", + "files": [ + "https://github.com/MrForExample/ComfyUI-AnimateAnyone-Evolved" + ], + "nodename_pattern": "^\\[AnimateAnyone\\]", + "install_type": "git-clone", + "description": "Improved AnimateAnyone implementation that allows you to use the opse image sequence and reference image to generate stylized video.\nThe current goal of this project is to achieve desired pose2video result with 1+FPS on GPUs that are equal to or better than RTX 3080!🚀\n[w/The torch environment may be compromised due to version issues as some torch-related packages are being reinstalled.]" + }, + { + "author": "Hangover3832", + "title": "ComfyUI-Hangover-Nodes", + "reference": "https://github.com/Hangover3832/ComfyUI-Hangover-Nodes", + "files": [ + "https://github.com/Hangover3832/ComfyUI-Hangover-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes: MS kosmos-2 Interrogator, Save Image w/o Metadata, Image Scale Bounding Box. An implementation of Microsoft [a/kosmos-2](https://huggingface.co/microsoft/kosmos-2-patch14-224) image to text transformer." + }, + { + "author": "Hangover3832", + "title": "ComfyUI-Hangover-Moondream", + "reference": "https://github.com/Hangover3832/ComfyUI-Hangover-Moondream", + "files": [ + "https://github.com/Hangover3832/ComfyUI-Hangover-Moondream" + ], + "install_type": "git-clone", + "description": "Moondream is a lightweight multimodal large language model.\n[w/WARN:Additional python code will be downloaded from huggingface and executed. You have to trust this creator if you want to use this node!]" + }, + { + "author": "Hangover3832", + "title": "Recognize Anything Model (RAM) for ComfyUI", + "reference": "https://github.com/Hangover3832/ComfyUI-Hangover-Recognize_Anything", + "files": [ + "https://github.com/Hangover3832/ComfyUI-Hangover-Recognize_Anything" + ], + "install_type": "git-clone", + "description": "This is an image recognition node for ComfyUI based on the RAM++ model from [a/xinyu1205](https://huggingface.co/xinyu1205).\nThis node outputs a string of tags with all the recognized objects and elements in the image in English or Chinese language.\nFor image tagging and captioning." + }, + { + "author": "tzwm", + "title": "ComfyUI Profiler", + "reference": "https://github.com/tzwm/comfyui-profiler", + "files": [ + "https://github.com/tzwm/comfyui-profiler" + ], + "install_type": "git-clone", + "description": "Calculate the execution time of all nodes." + }, + { + "author": "Daniel Lewis", + "title": "ComfyUI-Llama", + "reference": "https://github.com/daniel-lewis-ab/ComfyUI-Llama", + "files": [ + "https://github.com/daniel-lewis-ab/ComfyUI-Llama" + ], + "install_type": "git-clone", + "description": "This is a set of nodes to interact with llama-cpp-python" + }, + { + "author": "Daniel Lewis", + "title": "ComfyUI-TTS", + "reference": "https://github.com/daniel-lewis-ab/ComfyUI-TTS", + "files": [ + "https://github.com/daniel-lewis-ab/ComfyUI-TTS" + ], + "install_type": "git-clone", + "description": "Text To Speech (TTS) for ComfyUI" + }, + { + "author": "djbielejeski", + "title": "a-person-mask-generator", + "reference": "https://github.com/djbielejeski/a-person-mask-generator", + "files": [ + "https://github.com/djbielejeski/a-person-mask-generator" + ], + "install_type": "git-clone", + "description": "Extension for Automatic1111 and ComfyUI to automatically create masks for Background/Hair/Body/Face/Clothes in Img2Img" + }, + { + "author": "smagnetize", + "title": "kb-comfyui-nodes", + "reference": "https://github.com/smagnetize/kb-comfyui-nodes", + "files": [ + "https://github.com/smagnetize/kb-comfyui-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:SingleImageDataUrlLoader" + }, + { + "author": "ginlov", + "title": "segment_to_mask_comfyui", + "reference": "https://github.com/ginlov/segment_to_mask_comfyui", + "files": [ + "https://github.com/ginlov/segment_to_mask_comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:SegToMask" + }, + { + "author": "glowcone", + "title": "Load Image From Base64 URI", + "reference": "https://github.com/glowcone/comfyui-base64-to-image", + "files": [ + "https://github.com/glowcone/comfyui-base64-to-image" + ], + "install_type": "git-clone", + "description": "Nodes: LoadImageFromBase64. Loads an image and its transparency mask from a base64-encoded data URI for easy API connection." + }, + { + "author": "AInseven", + "title": "ComfyUI-fastblend", + "reference": "https://github.com/AInseven/ComfyUI-fastblend", + "files": [ + "https://github.com/AInseven/ComfyUI-fastblend" + ], + "install_type": "git-clone", + "description": "fastblend for comfyui, and other nodes that I write for video2video. rebatch image, my openpose" + }, + { + "author": "HebelHuber", + "title": "comfyui-enhanced-save-node", + "reference": "https://github.com/HebelHuber/comfyui-enhanced-save-node", + "files": [ + "https://github.com/HebelHuber/comfyui-enhanced-save-node" + ], + "install_type": "git-clone", + "description": "Nodes:Enhanced Save Node" + }, + { + "author": "LarryJane491", + "title": "Lora-Training-in-Comfy", + "reference": "https://github.com/LarryJane491/Lora-Training-in-Comfy", + "files": [ + "https://github.com/LarryJane491/Lora-Training-in-Comfy" + ], + "install_type": "git-clone", + "description": "If you see this message, your ComfyUI-Manager is outdated.\nRecent channel provides only the list of the latest nodes. If you want to find the complete node list, please go to the Default channel.\nMaking LoRA has never been easier!" + }, + { + "author": "LarryJane491", + "title": "Image-Captioning-in-ComfyUI", + "reference": "https://github.com/LarryJane491/Image-Captioning-in-ComfyUI", + "files": [ + "https://github.com/LarryJane491/Image-Captioning-in-ComfyUI" + ], + "install_type": "git-clone", + "description": "The LoRA Caption custom nodes, just like their name suggests, allow you to caption images so they are ready for LoRA training." + }, + { + "author": "Layer-norm", + "title": "Comfyui lama remover", + "reference": "https://github.com/Layer-norm/comfyui-lama-remover", + "files": [ + "https://github.com/Layer-norm/comfyui-lama-remover" + ], + "install_type": "git-clone", + "description": "A very simple ComfyUI node to remove item with mask." + }, + { + "author": "Taremin", + "title": "ComfyUI Prompt ExtraNetworks", + "reference": "https://github.com/Taremin/comfyui-prompt-extranetworks", + "files": [ + "https://github.com/Taremin/comfyui-prompt-extranetworks" + ], + "install_type": "git-clone", + "description": "Instead of LoraLoader or HypernetworkLoader, it receives a prompt and loads and applies LoRA or HN based on the specifications within the prompt. The main purpose of this custom node is to allow changes without reconnecting the LoraLoader node when the prompt is randomly altered, etc." + }, + { + "author": "Taremin", + "title": "ComfyUI String Tools", + "reference": "https://github.com/Taremin/comfyui-string-tools", + "files": [ + "https://github.com/Taremin/comfyui-string-tools" + ], + "install_type": "git-clone", + "description": " This extension provides the StringToolsConcat node, which concatenates multiple texts, and the StringToolsRandomChoice node, which selects one randomly from multiple texts." + }, + { + "author": "Taremin", + "title": "WebUI Monaco Prompt", + "reference": "https://github.com/Taremin/webui-monaco-prompt", + "files": [ + "https://github.com/Taremin/webui-monaco-prompt" + ], + "install_type": "git-clone", + "description": "Make it possible to edit the prompt using the Monaco Editor, an editor implementation used in VSCode.\nNOTE: This extension supports both ComfyUI and A1111 simultaneously." + }, + { + "author": "foxtrot-roger", + "title": "RF Nodes", + "reference": "https://github.com/foxtrot-roger/comfyui-rf-nodes", + "files": [ + "https://github.com/foxtrot-roger/comfyui-rf-nodes" + ], + "install_type": "git-clone", + "description": "A bunch of nodes that can be useful to manipulate primitive types (numbers, text, ...) Also some helpers to generate text and timestamps." + }, + { + "author": "abyz22", + "title": "image_control", + "reference": "https://github.com/abyz22/image_control", + "files": [ + "https://github.com/abyz22/image_control" + ], + "install_type": "git-clone", + "description": "Nodes:abyz22_Padding Image, abyz22_ImpactWildcardEncode, abyz22_setimageinfo, abyz22_SaveImage, abyz22_ImpactWildcardEncode_GetPrompt, abyz22_SetQueue, abyz22_drawmask, abyz22_FirstNonNull, abyz22_blendimages, abyz22_blend_onecolor. Please check workflow in [a/https://github.com/abyz22/image_control](https://github.com/abyz22/image_control)" + }, + { + "author": "HAL41", + "title": "ComfyUI aichemy nodes", + "reference": "https://github.com/HAL41/ComfyUI-aichemy-nodes", + "files": [ + "https://github.com/HAL41/ComfyUI-aichemy-nodes" + ], + "install_type": "git-clone", + "description": "Simple node to handle scaling of YOLOv8 segmentation masks" + }, + { + "author": "nkchocoai", + "title": "ComfyUI-SizeFromPresets", + "reference": "https://github.com/nkchocoai/ComfyUI-SizeFromPresets", + "files": [ + "https://github.com/nkchocoai/ComfyUI-SizeFromPresets" + ], + "install_type": "git-clone", + "description": "Add a node that outputs width and height of the size selected from the preset (.csv)." + }, + { + "author": "nkchocoai", + "title": "ComfyUI-PromptUtilities", + "reference": "https://github.com/nkchocoai/ComfyUI-PromptUtilities", + "files": [ + "https://github.com/nkchocoai/ComfyUI-PromptUtilities" + ], + "install_type": "git-clone", + "description": "Nodes: Format String, Join String List, Load Preset, Load Preset (Advanced), Const String, Const String (multi line). Add useful nodes related to prompt." + }, + { + "author": "nkchocoai", + "title": "ComfyUI-TextOnSegs", + "reference": "https://github.com/nkchocoai/ComfyUI-TextOnSegs", + "files": [ + "https://github.com/nkchocoai/ComfyUI-TextOnSegs" + ], + "install_type": "git-clone", + "description": "Add a node for drawing text with CR Draw Text of ComfyUI_Comfyroll_CustomNodes to the area of SEGS detected by Ultralytics Detector of ComfyUI-Impact-Pack." + }, + { + "author": "nkchocoai", + "title": "ComfyUI-SaveImageWithMetaData", + "reference": "https://github.com/nkchocoai/ComfyUI-SaveImageWithMetaData", + "files": [ + "https://github.com/nkchocoai/ComfyUI-SaveImageWithMetaData" + ], + "install_type": "git-clone", + "description": "Add a node to save images with metadata (PNGInfo) extracted from the input values of each node.\nSince the values are extracted dynamically, values output by various extension nodes can be added to metadata." + }, + { + "author": "nkchocoai", + "title": "ComfyUI-Dart", + "id": "dart", + "reference": "https://github.com/nkchocoai/ComfyUI-Dart", + "files": [ + "https://github.com/nkchocoai/ComfyUI-Dart" + ], + "install_type": "git-clone", + "description": "Add nodes that generates danbooru tags by [a/Dart(Danbooru Tags Transformer)](https://huggingface.co/p1atdev/dart-v1-sft)." + }, + { + "author": "JaredTherriault", + "title": "ComfyUI-JNodes", + "id": "jnodes", + "reference": "https://github.com/JaredTherriault/ComfyUI-JNodes", + "files": [ + "https://github.com/JaredTherriault/ComfyUI-JNodes" + ], + "install_type": "git-clone", + "description": "python and web UX improvements for ComfyUI: Lora/Embedding picker, web extension manager (enable/disable any extension without disabling python nodes), control any parameter with text prompts, image and video viewer, metadata viewer, token counter, comments in prompts, font control, and more! \n[w/'ImageFeed.js' from the custom scripts of pythongosssss is not compatible with this suite's ImageDrawer feature. Additionally, 'DynamicPrompts.js' and 'EditAttention.js' from the core, along with 'favicon.js' from the custom scripts of pythongosssss, are incompatible with advanced features of the suite. Please use the JNodes Extension Management setting in Settings > JNodes > Extension Management to disable these extensions by unchecking them to use the full functionality of the suite.]" + }, + { + "author": "prozacgod", + "title": "ComfyUI Multi-Workspace", + "id": "multi-workspace", + "reference": "https://github.com/prozacgod/comfyui-pzc-multiworkspace", + "files": [ + "https://github.com/prozacgod/comfyui-pzc-multiworkspace" + ], + "install_type": "git-clone", + "description": "A simple, quick, and dirty implementation of multiple workspaces within ComfyUI." + }, + { + "author": "Siberpone", + "title": "Lazy Pony Prompter", + "id": "lazy-pony-prompter", + "reference": "https://github.com/Siberpone/lazy-pony-prompter", + "files": [ + "https://github.com/Siberpone/lazy-pony-prompter" + ], + "install_type": "git-clone", + "description": "A booru API powered prompt generator for A1111 and ComfyUI with flexible tag filtering system and customizable prompt templates." + }, + { + "author": "dave-palt", + "title": "comfyui_DSP_imagehelpers", + "id": "dsp-imagehelpers", + "reference": "https://github.com/dave-palt/comfyui_DSP_imagehelpers", + "files": [ + "https://github.com/dave-palt/comfyui_DSP_imagehelpers" + ], + "install_type": "git-clone", + "description": "Nodes: DSP Image Concat" + }, + { + "author": "Inzaniak", + "title": "Ranbooru for ComfyUI", + "id": "ranbooru", + "reference": "https://github.com/Inzaniak/comfyui-ranbooru", + "files": [ + "https://github.com/Inzaniak/comfyui-ranbooru" + ], + "install_type": "git-clone", + "description": "Ranbooru is an extension for the comfyUI. The purpose of this extension is to add a node that gets a random set of tags from boorus pictures. This is mostly being used to help me test my checkpoints on a large variety of" + }, + { + "author": "miosp", + "title": "ComfyUI-FBCNN", + "id": "fbcnn", + "reference": "https://github.com/Miosp/ComfyUI-FBCNN", + "files": [ + "https://github.com/Miosp/ComfyUI-FBCNN" + ], + "install_type": "git-clone", + "description": "A node for JPEG de-artifacting using [a/FBCNN](https://github.com/jiaxi-jiang/FBCNN)." + }, + { + "author": "JcandZero", + "title": "ComfyUI_GLM4Node", + "id": "glm4node", + "reference": "https://github.com/JcandZero/ComfyUI_GLM4Node", + "files": [ + "https://github.com/JcandZero/ComfyUI_GLM4Node" + ], + "install_type": "git-clone", + "description": "GLM4 Vision Integration" + }, + { + "author": "darkpixel", + "title": "DarkPrompts", + "id": "darkprompts", + "reference": "https://github.com/darkpixel/darkprompts", + "files": [ + "https://github.com/darkpixel/darkprompts" + ], + "install_type": "git-clone", + "description": "Slightly better random prompt generation tools that allow combining and picking prompts from both file and text input sources." + }, + { + "author": "shiimizu", + "title": "ComfyUI PhotoMaker Plus", + "id": "photomaker-plus", + "reference": "https://github.com/shiimizu/ComfyUI-PhotoMaker-Plus", + "files": [ + "https://github.com/shiimizu/ComfyUI-PhotoMaker-Plus" + ], + "install_type": "git-clone", + "description": "ComfyUI reference implementation for [a/PhotoMaker](https://github.com/TencentARC/PhotoMaker) models. [w/WARN:The repository name has been changed. For those who have previously installed it, please delete custom_nodes/ComfyUI-PhotoMaker from disk and reinstall this.]" + }, + { + "author": "yytdfc", + "title": "Amazon Bedrock nodes for ComfyUI", + "id": "bedrock", + "reference": "https://github.com/aws-samples/comfyui-llm-node-for-amazon-bedrock", + "files": [ + "https://github.com/aws-samples/comfyui-llm-node-for-amazon-bedrock" + ], + "pip": ["boto3"], + "install_type": "git-clone", + "description": "Amazon Bedrock is a fully managed service that offers a choice of high-performing foundation models (FMs) from leading AI companies. This repo is the ComfyUI nodes for Bedrock service. You could invoke the foundation model in your ComfyUI pipeline." + }, + { + "author": "Qais Malkawi", + "title": "ComfyUI-Qais-Helper", + "id": "qais-helper", + "reference": "https://github.com/QaisMalkawi/ComfyUI-QaisHelper", + "files": [ + "https://github.com/QaisMalkawi/ComfyUI-QaisHelper" + ], + "install_type": "git-clone", + "description": "This Extension adds a few custom QOL nodes that ComfyUI lacks by default." + }, + { + "author": "longgui0318", + "title": "comfyui-mask-util", + "id": "mask-util", + "reference": "https://github.com/longgui0318/comfyui-mask-util", + "files": [ + "https://github.com/longgui0318/comfyui-mask-util" + ], + "install_type": "git-clone", + "description": "Nodes:Split Masks, Mask Selection Of Masks, Mask Region Info" + }, + { + "author": "longgui0318", + "title": "comfyui-llm-assistant", + "id": "llm-assistant", + "reference": "https://github.com/longgui0318/comfyui-llm-assistant", + "files": [ + "https://github.com/longgui0318/comfyui-llm-assistant" + ], + "install_type": "git-clone", + "description": "Nodes:Generate Stable Diffsution Prompt With LLM, Translate Text With LLM, Chat With LLM" + }, + { + "author": "longgui0318", + "title": "comfyui-oms-diffusion", + "id": "oms-diffusion", + "reference": "https://github.com/longgui0318/comfyui-oms-diffusion", + "files": [ + "https://github.com/longgui0318/comfyui-oms-diffusion" + ], + "install_type": "git-clone", + "description": "Nodes:Extract Features With Unet, Additional Features With Attention" + }, + { + "author": "longgui0318", + "title": "comfyui-magic-clothing", + "id": "magic-clothing", + "reference": "https://github.com/longgui0318/comfyui-magic-clothing", + "files": [ + "https://github.com/longgui0318/comfyui-magic-clothing" + ], + "install_type": "git-clone", + "description": "The comfyui supported version of the [a/Magic Clothing](https://github.com/ShineChen1024/MagicClothing) project, not the diffusers version, allows direct integration with modules such as ipadapter" + }, + { + "author": "longgui0318", + "title": "comfyui-common-util", + "id": "common-util", + "reference": "https://github.com/longgui0318/comfyui-common-util", + "files": [ + "https://github.com/longgui0318/comfyui-common-util" + ], + "install_type": "git-clone", + "description": "Nodes:Init Layer Info Array, Added Layer Info To Array, Layer Info Array Fuse, Layer Image Seleted, Layer Images IPAdapter Advanced, Enhanced Random Light Source" + }, + { + "author": "DimaChaichan", + "title": "LAizypainter-Exporter-ComfyUI", + "reference": "https://github.com/DimaChaichan/LAizypainter-Exporter-ComfyUI", + "files": [ + "https://github.com/DimaChaichan/LAizypainter-Exporter-ComfyUI" + ], + "install_type": "git-clone", + "description": "This exporter is a plugin for ComfyUI, which can export tasks for [a/LAizypainter](https://github.com/DimaChaichan/LAizypainter).\nLAizypainter is a Photoshop plugin with which you can send tasks directly to a Stable Diffusion server. More information about a [a/Task](https://github.com/DimaChaichan/LAizypainter?tab=readme-ov-file#task)" + }, + { + "author": "adriflex", + "title": "ComfyUI_Blender_Texdiff", + "id": "blender-texdiff", + "reference": "https://github.com/adriflex/ComfyUI_Blender_Texdiff", + "files": [ + "https://github.com/adriflex/ComfyUI_Blender_Texdiff" + ], + "install_type": "git-clone", + "description": "Nodes:Blender viewport color, Blender Viewport depth" + }, + { + "author": "Shraknard", + "title": "ComfyUI-Remover", + "id": "remover", + "reference": "https://github.com/Shraknard/ComfyUI-Remover", + "files": [ + "https://github.com/Shraknard/ComfyUI-Remover" + ], + "install_type": "git-clone", + "description": "Custom node for ComfyUI that makes parts of the image transparent (face, background...)" + }, + { + "author": "FlyingFireCo", + "title": "tiled_ksampler", + "reference": "https://github.com/FlyingFireCo/tiled_ksampler", + "files": [ + "https://github.com/FlyingFireCo/tiled_ksampler" + ], + "install_type": "git-clone", + "description": "Nodes:Tiled KSampler, Asymmetric Tiled KSampler, Circular VAEDecode." + }, + { + "author": "Nlar", + "title": "ComfyUI_CartoonSegmentation", + "id": "cartoon-seg", + "reference": "https://github.com/Nlar/ComfyUI_CartoonSegmentation", + "files": [ + "https://github.com/Nlar/ComfyUI_CartoonSegmentation" + ], + "install_type": "git-clone", + "description": "Front end ComfyUI nodes for CartoonSegmentation Based upon the work of the CartoonSegmentation repository this project will provide a front end to some of the features." + }, + { + "author": "godspede", + "title": "ComfyUI Substring", + "id": "substring", + "reference": "https://github.com/godspede/ComfyUI_Substring", + "files": [ + "https://github.com/godspede/ComfyUI_Substring" + ], + "install_type": "git-clone", + "description": "Just a simple substring node that takes text and length as input, and outputs the first length characters." + }, + { + "author": "gokayfem", + "title": "VLM_nodes", + "id": "vlm", + "reference": "https://github.com/gokayfem/ComfyUI_VLM_nodes", + "files": [ + "https://github.com/gokayfem/ComfyUI_VLM_nodes" + ], + "install_type": "git-clone", + "description": "Custom Nodes for Vision Language Models (VLM) , Large Language Models (LLM), Image Captioning, Automatic Prompt Generation, Creative and Consistent Prompt Suggestion, Keyword Extraction" + }, + { + "author": "gokayfem", + "title": "ComfyUI-Dream-Interpreter", + "id": "dream-interpreter", + "reference": "https://github.com/gokayfem/ComfyUI-Dream-Interpreter", + "files": [ + "https://github.com/gokayfem/ComfyUI-Dream-Interpreter" + ], + "install_type": "git-clone", + "description": "Tell your dream and it interprets it and puts you inside your dream" + }, + { + "author": "gokayfem", + "title": "ComfyUI-Depth-Visualization", + "id": "delpth-visualization", + "reference": "https://github.com/gokayfem/ComfyUI-Depth-Visualization", + "files": [ + "https://github.com/gokayfem/ComfyUI-Depth-Visualization" + ], + "install_type": "git-clone", + "description": "Works with any Depth Map and visualizes the applied version it inside ComfyUI" + }, + { + "author": "gokayfem", + "title": "ComfyUI-Texture-Simple", + "id": "texture-simple", + "reference": "https://github.com/gokayfem/ComfyUI-Texture-Simple", + "files": [ + "https://github.com/gokayfem/ComfyUI-Texture-Simple" + ], + "install_type": "git-clone", + "description": "Visualize your textures inside ComfyUI" + }, + { + "author": "Hiero207", + "title": "Hiero-Nodes", + "id": "hiero", + "reference": "https://github.com/Hiero207/ComfyUI-Hiero-Nodes", + "files": [ + "https://github.com/Hiero207/ComfyUI-Hiero-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Post to Discord w/ Webhook" + }, + { + "author": "azure-dragon-ai", + "title": "ComfyUI-ClipScore-Nodes", + "id": "clipscore", + "reference": "https://github.com/azure-dragon-ai/ComfyUI-ClipScore-Nodes", + "files": [ + "https://github.com/azure-dragon-ai/ComfyUI-ClipScore-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:ImageScore, Loader, Image Processor, Real Image Processor, Fake Image Processor, Text Processor. ComfyUI Nodes for ClipScore" + }, + { + "author": "yuvraj108c", + "title": "ComfyUI Whisper", + "id": "whisper", + "reference": "https://github.com/yuvraj108c/ComfyUI-Whisper", + "files": [ + "https://github.com/yuvraj108c/ComfyUI-Whisper" + ], + "install_type": "git-clone", + "description": "Transcribe audio and add subtitles to videos using Whisper in ComfyUI" + }, + { + "author": "yuvraj108c", + "title": "ComfyUI-Pronodes", + "id": "pronodes", + "reference": "https://github.com/yuvraj108c/ComfyUI-Pronodes", + "files": [ + "https://github.com/yuvraj108c/ComfyUI-Pronodes" + ], + "install_type": "git-clone", + "description": "A collection of nice utility nodes for ComfyUI" + }, + { + "author": "yuvraj108c", + "title": "ComfyUI-Vsgan", + "id": "vsgan", + "reference": "https://github.com/yuvraj108c/ComfyUI-Vsgan", + "files": [ + "https://github.com/yuvraj108c/ComfyUI-Vsgan" + ], + "install_type": "git-clone", + "description": "Nodes:Upscale Video Tensorrt" + }, + { + "author": "yuvraj108c", + "title": "ComfyUI Depth Anything TensorRT", + "id": "depth-anything-tensorrt", + "reference": "https://github.com/yuvraj108c/ComfyUI-Depth-Anything-Tensorrt", + "files": [ + "https://github.com/yuvraj108c/ComfyUI-Depth-Anything-Tensorrt" + ], + "install_type": "git-clone", + "description": "This extension provides a ComfyUI Custom Node implementation of the [a/Depth-Anything-Tensorrt](https://github.com/spacewalk01/depth-anything-tensorrt) in Python for ultra fast depth map generation" + }, + { + "author": "yuvraj108c", + "title": "ComfyUI PiperTTS", + "id": "pipertts", + "reference": "https://github.com/yuvraj108c/ComfyUI-PiperTTS", + "files": [ + "https://github.com/yuvraj108c/ComfyUI-PiperTTS" + ], + "install_type": "git-clone", + "description": "Convert Text-to-Speech inside ComfyUI using [a/Piper](https://github.com/rhasspy/piper)" + }, + { + "author": "yuvraj108c", + "title": "ComfyUI Upscaler TensorRT", + "id": "upscaler-tensorrt", + "reference": "https://github.com/yuvraj108c/ComfyUI-Upscaler-Tensorrt", + "files": [ + "https://github.com/yuvraj108c/ComfyUI-Upscaler-Tensorrt" + ], + "install_type": "git-clone", + "description": "This project provides a Tensorrt implementation for fast image upscaling inside ComfyUI (3-4x faster)" + }, + { + "author": "yuvraj108c", + "title": "ComfyUI YoloNasPose Tensorrt", + "id": "yolonaspose-tensorrt", + "reference": "https://github.com/yuvraj108c/ComfyUI-YoloNasPose-Tensorrt", + "files": [ + "https://github.com/yuvraj108c/ComfyUI-YoloNasPose-Tensorrt" + ], + "install_type": "git-clone", + "description": "This repo provides a ComfyUI Custom Node implementation of [a/YOLO-NAS-POSE](https://github.com/Deci-AI/super-gradients), powered by TensorRT for ultra fast pose estimation. It has been adapted to work with openpose controlnet (experimental)" + }, + { + "author": "blepping", + "title": "ComfyUI-bleh", + "id": "bleh", + "reference": "https://github.com/blepping/ComfyUI-bleh", + "files": [ + "https://github.com/blepping/ComfyUI-bleh" + ], + "install_type": "git-clone", + "description": "Better TAESD previews, BlehHyperTile." + }, + { + "author": "blepping", + "title": "ComfyUI-sonar", + "id": "sonar", + "reference": "https://github.com/blepping/ComfyUI-sonar", + "files": [ + "https://github.com/blepping/ComfyUI-sonar" + ], + "install_type": "git-clone", + "description": "A janky implementation of Sonar sampling (momentum-based sampling) for ComfyUI." + }, + { + "author": "blepping", + "title": "ComfyUI jank HiDiffusion", + "id": "jank-hidiffusion", + "reference": "https://github.com/blepping/comfyui_jankhidiffusion", + "files": [ + "https://github.com/blepping/comfyui_jankhidiffusion" + ], + "install_type": "git-clone", + "description": "Janky experimental attempt at implementing [a/HiDiffusion](https://github.com/megvii-research/HiDiffusion) for ComfyUI." + }, + { + "author": "JerryOrbachJr", + "title": "Random Size", + "reference": "https://github.com/JerryOrbachJr/ComfyUI-RandomSize", + "files": [ + "https://github.com/JerryOrbachJr/ComfyUI-RandomSize" + ], + "install_type": "git-clone", + "description": "A ComfyUI custom node that randomly selects a height and width pair from a list in a config file" + }, + { + "author": "jamal-alkharrat", + "title": "ComfyUI_rotate_image", + "reference": "https://github.com/jamal-alkharrat/ComfyUI_rotate_image", + "files": [ + "https://github.com/jamal-alkharrat/ComfyUI_rotate_image" + ], + "install_type": "git-clone", + "description": "ComfyUI Custom Node to Rotate Images, Img2Img node." + }, + { + "author": "mape", + "title": "mape's helpers", + "id": "mape-helpers", + "reference": "https://github.com/mape/ComfyUI-mape-Helpers", + "files": [ + "https://github.com/mape/ComfyUI-mape-Helpers" + ], + "install_type": "git-clone", + "description": "Multi-monitor image preview, Variable Assigment/Wireless Nodes, Prompt Tweaking, Command Palette, Pinned favourite nodes, Node navigation, Fuzzy search, Node time tracking, Organizing and Error management. For more info visit: [a/https://comfyui.ma.pe/](https://comfyui.ma.pe/)" + }, + { + "author": "zhongpei", + "title": "Comfyui_image2prompt", + "id": "img2prompt", + "reference": "https://github.com/zhongpei/Comfyui_image2prompt", + "files": [ + "https://github.com/zhongpei/Comfyui_image2prompt" + ], + "install_type": "git-clone", + "description": "Nodes:Image to Text, Loader Image to Text Model." + }, + { + "author": "zhongpei", + "title": "ComfyUI for InstructIR", + "id": "instructir", + "reference": "https://github.com/zhongpei/ComfyUI-InstructIR", + "files": [ + "https://github.com/zhongpei/ComfyUI-InstructIR" + ], + "install_type": "git-clone", + "description": "Enhancing Image Restoration. (ref:[a/InstructIR](https://github.com/mv-lab/InstructIR))" + }, + { + "author": "Loewen-Hob", + "title": "Rembg Background Removal Node for ComfyUI (Better)", + "id": "rembg-better", + "reference": "https://github.com/Loewen-Hob/rembg-comfyui-node-better", + "files": [ + "https://github.com/Loewen-Hob/rembg-comfyui-node-better" + ], + "install_type": "git-clone", + "description": "This custom node is based on the [a/rembg-comfyui-node](https://github.com/Jcd1230/rembg-comfyui-node) but provides additional functionality to select ONNX models." + }, + { + "author": "HaydenReeve", + "title": "ComfyUI Better Strings", + "id": "better-string", + "reference": "https://github.com/HaydenReeve/ComfyUI-Better-Strings", + "files": [ + "https://github.com/HaydenReeve/ComfyUI-Better-Strings" + ], + "install_type": "git-clone", + "description": "Strings should be easy, and simple. This extension aims to provide a set of nodes that make working with strings in ComfyUI a little bit easier." + }, + { + "author": "StartHua", + "title": "ComfyUI_Seg_VITON", + "id": "seg-viton", + "reference": "https://github.com/StartHua/ComfyUI_Seg_VITON", + "files": [ + "https://github.com/StartHua/ComfyUI_Seg_VITON" + ], + "install_type": "git-clone", + "description": "Nodes:segformer_clothes, segformer_agnostic, segformer_remove_bg, stabel_vition. Nodes for model dress up." + }, + { + "author": "StartHua", + "title": "Comfyui_joytag", + "id": "joytag", + "reference": "https://github.com/StartHua/Comfyui_joytag", + "files": [ + "https://github.com/StartHua/Comfyui_joytag" + ], + "install_type": "git-clone", + "description": "JoyTag is a state of the art AI vision model for tagging images, with a focus on sex positivity and inclusivity. It uses the Danbooru tagging schema, but works across a wide range of images, from hand drawn to photographic.\nDownload the weight and put it under checkpoints: [a/https://huggingface.co/fancyfeast/joytag/tree/main](https://huggingface.co/fancyfeast/joytag/tree/main)" + }, + { + "author": "StartHua", + "title": "comfyui_segformer_b2_clothes", + "id": "segformer-b2-clothes", + "reference": "https://github.com/StartHua/Comfyui_segformer_b2_clothes", + "files": [ + "https://github.com/StartHua/Comfyui_segformer_b2_clothes" + ], + "install_type": "git-clone", + "description": "SegFormer model fine-tuned on ATR dataset for clothes segmentation but can also be used for human segmentation!\nDownload the weight and put it under checkpoints: [a/https://huggingface.co/mattmdjaga/segformer_b2_clothes](https://huggingface.co/mattmdjaga/segformer_b2_clothes)" + }, + { + "author": "StartHua", + "title": "ComfyUI_OOTDiffusion_CXH", + "id": "ootdiffusion-cxh", + "reference": "https://github.com/StartHua/ComfyUI_OOTDiffusion_CXH", + "files": [ + "https://github.com/StartHua/ComfyUI_OOTDiffusion_CXH" + ], + "install_type": "git-clone", + "description": "Nodes:Ood_hd_CXH, Ood_hd_CXH. [a/OOTDiffusion](https://github.com/levihsu/OOTDiffusion)" + }, + { + "author": "StartHua", + "title": "ComfyUI_PCDMs", + "id": "pcdms", + "reference": "https://github.com/StartHua/ComfyUI_PCDMs", + "files": [ + "https://github.com/StartHua/ComfyUI_PCDMs" + ], + "install_type": "git-clone", + "description": "Original project: [a/link](https://github.com/tencent-ailab/PCDMs)\nBased on testing, the author's original images work very well, but using my own images generally requires some luck!" + }, + { + "author": "ricklove", + "title": "comfyui-ricklove", + "id": "ricklove", + "reference": "https://github.com/ricklove/comfyui-ricklove", + "files": [ + "https://github.com/ricklove/comfyui-ricklove" + ], + "install_type": "git-clone", + "description": "Nodes: Image Crop and Resize by Mask, Image Uncrop, Image Shadow, Optical Flow (Dip), Warp Image with Flow, Image Threshold (Channels), Finetune Variable, Finetune Analyze, Finetune Analyze Batch, ... Misc ComfyUI nodes by Rick Love" + }, + { + "author": "nosiu", + "title": "ComfyUI InstantID Faceswapper", + "id": "instantid-faceswapper", + "reference": "https://github.com/nosiu/comfyui-instantId-faceswap", + "files": [ + "https://github.com/nosiu/comfyui-instantId-faceswap" + ], + "install_type": "git-clone", + "description": "Implementation of [a/faceswap](https://github.com/nosiu/InstantID-faceswap/tree/main) based on [a/InstantID](https://github.com/InstantID/InstantID) for ComfyUI. Allows usage of [a/LCM Lora](https://huggingface.co/latent-consistency/lcm-lora-sdxl) which can produce good results in only a few generation steps.\nNOTE:Works ONLY with SDXL checkpoints." + }, + { + "author": "LyazS", + "title": "Anime Character Segmentation node for comfyui", + "reference": "https://github.com/LyazS/comfyui-anime-seg", + "files": [ + "https://github.com/LyazS/comfyui-anime-seg" + ], + "install_type": "git-clone", + "description": "A Anime Character Segmentation node for comfyui, based on [this hf space](https://huggingface.co/spaces/skytnt/anime-remove-background)." + }, + { + "author": "Chan-0312", + "title": "ComfyUI-IPAnimate", + "reference": "https://github.com/Chan-0312/ComfyUI-IPAnimate", + "files": [ + "https://github.com/Chan-0312/ComfyUI-IPAnimate" + ], + "install_type": "git-clone", + "description": "This is a project that generates videos frame by frame based on IPAdapter+ControlNet. Unlike [a/Steerable-motion](https://github.com/banodoco/Steerable-Motion), we do not rely on AnimateDiff. This decision is primarily due to the fact that the videos generated by AnimateDiff are often blurry. Through frame-by-frame control using IPAdapter+ControlNet, we can produce higher definition and more controllable videos." + }, + { + "author": "Chan-0312", + "title": "ComfyUI-EasyDeforum", + "reference": "https://github.com/Chan-0312/ComfyUI-EasyDeforum", + "files": [ + "https://github.com/Chan-0312/ComfyUI-EasyDeforum" + ], + "install_type": "git-clone", + "description": "Nodes:Easy2DDeforum (Chan)" + }, + { + "author": "trumanwong", + "title": "ComfyUI-NSFW-Detection", + "reference": "https://github.com/trumanwong/ComfyUI-NSFW-Detection", + "files": [ + "https://github.com/trumanwong/ComfyUI-NSFW-Detection" + ], + "install_type": "git-clone", + "description": "An implementation of NSFW Detection for ComfyUI" + }, + { + "author": "TemryL", + "title": "ComfyS3", + "reference": "https://github.com/TemryL/ComfyS3", + "files": [ + "https://github.com/TemryL/ComfyS3" + ], + "install_type": "git-clone", + "description": "ComfyS3 seamlessly integrates with [a/Amazon S3](https://aws.amazon.com/en/s3/) in ComfyUI. This open-source project provides custom nodes for effortless loading and saving of images, videos, and checkpoint models directly from S3 buckets within the ComfyUI graph interface." + }, + { + "author": "MaraScott", + "title": "🐰 MaraScott Nodes", + "id": "marascott-nodes", + "reference": "https://github.com/MaraScott/ComfyUI_MaraScott_Nodes", + "files": [ + "https://github.com/MaraScott/ComfyUI_MaraScott_Nodes" + ], + "install_type": "git-clone", + "description": "A set of nodes including a universal bus, an Inpainting By Mask and a large Upscaler/Refiner\n[AnyBus,McInpainty,McBoaty]" + }, + { + "author": "yffyhk", + "title": "comfyui_auto_danbooru", + "reference": "https://github.com/yffyhk/comfyui_auto_danbooru", + "files": [ + "https://github.com/yffyhk/comfyui_auto_danbooru" + ], + "install_type": "git-clone", + "description": "Nodes: Get Danbooru, Tag Encode" + }, + { + "author": "dfl", + "title": "CLIP with BREAK syntax", + "reference": "https://github.com/dfl/comfyui-clip-with-break", + "files": [ + "https://github.com/dfl/comfyui-clip-with-break" + ], + "install_type": "git-clone", + "description": "Clip text encoder with BREAK formatting like A1111 (uses conditioning concat)" + }, + { + "author": "dfl", + "title": "ComfyUI-TCD-scheduler", + "id": "dfl-tcd", + "reference": "https://github.com/dfl/comfyui-tcd-scheduler", + "files": [ + "https://github.com/dfl/comfyui-tcd-scheduler" + ], + "install_type": "git-clone", + "description": "ComfyUI Custom Sampler nodes that implement Zheng et al.'s Trajectory Consistency Distillation based on [a/https://mhh0318.github.io/tcd](https://mhh0318.github.io/tcd)" + }, + { + "author": "antrobot", + "title": "antrobots ComfyUI Nodepack", + "reference": "https://github.com/antrobot1234/antrobots-comfyUI-nodepack", + "files": [ + "https://github.com/antrobot1234/antrobots-comfyUI-nodepack" + ], + "install_type": "git-clone", + "description": "A small node pack containing various things I felt like ought to be in base comfy-UI. Currently includes Some image handling nodes to help with inpainting, a version of KSampler (advanced) that allows for denoise, and a node that can swap it's inputs. Remember to make an issue if you experience any bugs or errors!" + }, + { + "author": "bilal-arikan", + "title": "ComfyUI_TextAssets", + "reference": "https://github.com/bilal-arikan/ComfyUI_TextAssets", + "files": [ + "https://github.com/bilal-arikan/ComfyUI_TextAssets" + ], + "install_type": "git-clone", + "description": "With this node you can upload text files to input folder from your local computer." + }, + { + "author": "kadirnar", + "title": "ComfyUI-Transformers", + "id": "comfy-transformers", + "reference": "https://github.com/kadirnar/ComfyUI-Transformers", + "files": [ + "https://github.com/kadirnar/ComfyUI-Transformers" + ], + "install_type": "git-clone", + "description": "ComfyUI-Transformers is a cutting-edge project combining the power of computer vision and natural language processing to create intuitive and user-friendly interfaces. Our goal is to make technology more accessible and engaging." + }, + { + "author": "kadirnar", + "title": "ComfyUI-YOLO", + "id": "comfy-yolo", + "reference": "https://github.com/kadirnar/ComfyUI-YOLO", + "files": [ + "https://github.com/kadirnar/ComfyUI-YOLO" + ], + "install_type": "git-clone", + "description": "Ultralytics-Powered Object Recognition for ComfyUI" + }, + { + "author": "digitaljohn", + "title": "ComfyUI-ProPost", + "reference": "https://github.com/digitaljohn/comfyui-propost", + "files": [ + "https://github.com/digitaljohn/comfyui-propost" + ], + "install_type": "git-clone", + "description": "A set of custom ComfyUI nodes for performing basic post-processing effects including Film Grain and Vignette. These effects can help to take the edge off AI imagery and make them feel more natural." + }, + { + "author": "DonBaronFactory", + "title": "ComfyUI-Cre8it-Nodes", + "reference": "https://github.com/DonBaronFactory/ComfyUI-Cre8it-Nodes", + "files": [ + "https://github.com/DonBaronFactory/ComfyUI-Cre8it-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:CRE8IT Serial Prompter, CRE8IT Apply Serial Prompter, CRE8IT Image Sizer. A few simple nodes to facilitate working wiht ComfyUI Workflows" + }, + { + "author": "deforum", + "title": "Deforum Nodes", + "reference": "https://github.com/XmYx/deforum-comfy-nodes", + "files": [ + "https://github.com/XmYx/deforum-comfy-nodes" + ], + "install_type": "git-clone", + "description": "Official Deforum animation pipeline tools that provide a unique way to create frame-by-frame generative motion art." + }, + { + "author": "adbrasi", + "title": "ComfyUI-TrashNodes-DownloadHuggingface", + "reference": "https://github.com/adbrasi/ComfyUI-TrashNodes-DownloadHuggingface", + "files": [ + "https://github.com/adbrasi/ComfyUI-TrashNodes-DownloadHuggingface" + ], + "install_type": "git-clone", + "description": "ComfyUI-TrashNodes-DownloadHuggingface is a ComfyUI node designed to facilitate the download of models you have just trained and uploaded to Hugging Face. This node is particularly useful for users who employ Google Colab for training and need to quickly download their models for deployment." + }, + { + "author": "mbrostami", + "title": "ComfyUI-HF", + "reference": "https://github.com/mbrostami/ComfyUI-HF", + "files": [ + "https://github.com/mbrostami/ComfyUI-HF" + ], + "install_type": "git-clone", + "description": "ComfyUI Node to work with Hugging Face repositories" + }, + { + "author": "Billius-AI", + "title": "ComfyUI-Path-Helper", + "reference": "https://github.com/Billius-AI/ComfyUI-Path-Helper", + "files": [ + "https://github.com/Billius-AI/ComfyUI-Path-Helper" + ], + "install_type": "git-clone", + "description": "Nodes:Create Project Root, Add Folder, Add Folder Advanced, Add File Name Prefix, Add File Name Prefix Advanced, ShowPath" + }, + { + "author": "Franck-Demongin", + "title": "NX_PromptStyler", + "reference": "https://github.com/Franck-Demongin/NX_PromptStyler", + "files": [ + "https://github.com/Franck-Demongin/NX_PromptStyler" + ], + "install_type": "git-clone", + "description": "A custom node for ComfyUI to create a prompt based on a list of keywords saved in CSV files." + }, + { + "author": "xiaoxiaodesha", + "title": "hd-nodes-comfyui", + "reference": "https://github.com/xiaoxiaodesha/hd_node", + "files": [ + "https://github.com/xiaoxiaodesha/hd_node" + ], + "install_type": "git-clone", + "description": "Nodes:Combine HDMasks, Cover HDMasks, HD FaceIndex, HD SmoothEdge, HD GetMaskArea, HD Image Levels, HD Ultimate SD Upscale" + }, + { + "author": "ShmuelRonen", + "title": "ComfyUI-SVDResizer", + "id": "svdresizer", + "reference": "https://github.com/ShmuelRonen/ComfyUI-SVDResizer", + "files": [ + "https://github.com/ShmuelRonen/ComfyUI-SVDResizer" + ], + "install_type": "git-clone", + "description": "SVDResizer is a helper for resizing the source image, according to the sizes enabled in Stable Video Diffusion. The rationale behind the possibility of changing the size of the image in steps between the ranges of 576 and 1024, is the use of the greatest common denominator of these two numbers which is 64. SVD is lenient with resizing that adheres to this rule, so the chance of coherent video that is not the standard size of 576X1024 is greater. It is advisable to keep the value 1024 constant and play with the second size to maintain the stability of the result." + }, + { + "author": "ShmuelRonen", + "title": "Wav2Lip Node for ComfyUI", + "id": "wav2lip", + "reference": "https://github.com/ShmuelRonen/ComfyUI_wav2lip", + "files": [ + "https://github.com/ShmuelRonen/ComfyUI_wav2lip" + ], + "install_type": "git-clone", + "description": "The Wav2Lip node is a custom node for ComfyUI that allows you to perform lip-syncing on videos using the Wav2Lip model. It takes an input video and an audio file and generates a lip-synced output video." + }, + { + "author": "ShmuelRonen", + "title": "ComfyUI_Gemini_Flash", + "id": "gemini-flash", + "reference": "https://github.com/ShmuelRonen/ComfyUI_Gemini_Flash", + "files": [ + "https://github.com/ShmuelRonen/ComfyUI_Gemini_Flash" + ], + "install_type": "git-clone", + "description": "ComfyUI_Gemini_Flash is a custom node for ComfyUI, integrating the capabilities of the Gemini 1.5 Flash model. This node supports text and vision-based prompts, allowing users to analyze and adapt images to text prompts for text2image tasks." + }, + { + "author": "redhottensors", + "title": "ComfyUI-Prediction", + "id": "prediction", + "reference": "https://github.com/redhottensors/ComfyUI-Prediction", + "files": [ + "https://github.com/redhottensors/ComfyUI-Prediction" + ], + "install_type": "git-clone", + "description": "Fully customizable Classifier Free Guidance for ComfyUI." + }, + { + "author": "Mamaaaamooooo", + "title": "Batch Rembg for ComfyUI", + "id": "batch-rembg", + "reference": "https://github.com/Mamaaaamooooo/batchImg-rembg-ComfyUI-nodes", + "files": [ + "https://github.com/Mamaaaamooooo/batchImg-rembg-ComfyUI-nodes" + ], + "install_type": "git-clone", + "description": "Remove background of plural images." + }, + { + "author": "jordoh", + "title": "ComfyUI Deepface", + "id": "deepface", + "reference": "https://github.com/jordoh/ComfyUI-Deepface", + "files": [ + "https://github.com/jordoh/ComfyUI-Deepface" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes wrapping the [a/deepface](https://github.com/serengil/deepface) library." + }, + { + "author": "al-swaiti", + "title": "ComfyUI-CascadeResolutions", + "id": "cascade-resolution", + "reference": "https://github.com/al-swaiti/ComfyUI-CascadeResolutions", + "files": [ + "https://github.com/al-swaiti/ComfyUI-CascadeResolutions" + ], + "install_type": "git-clone", + "description": "Nodes:Cascade Resolutions" + }, + { + "author": "mirabarukaso", + "title": "ComfyUI_Mira", + "id": "mira", + "reference": "https://github.com/mirabarukaso/ComfyUI_Mira", + "files": [ + "https://github.com/mirabarukaso/ComfyUI_Mira" + ], + "install_type": "git-clone", + "description": "Nodes:Integer Multiplier, Float Multiplier, Convert Numeral to String, Create Canvas Advanced, Create Canvas, Create PNG Mask, Color Mask to HEX String, Color Mask to INT RGB, Color Masks to List" + }, + { + "author": "1038lab", + "title": "ComfyUI-GPT2P", + "id": "gpt2p", + "reference": "https://github.com/1038lab/ComfyUI-GPT2P", + "files": [ + "https://github.com/1038lab/ComfyUI-GPT2P" + ], + "install_type": "git-clone", + "description": "ComfyUI Node - Hugging Face repositories GTP2 Prompt" + }, + { + "author": "1038lab", + "title": "ComfyUI-latentSizeSelector", + "id": "ComfyUI-latentSizeSelector", + "reference": "https://github.com/1038lab/ComfyUI_LatentSizeSelector", + "files": [ + "https://github.com/1038lab/ComfyUI_LatentSizeSelector" + ], + "install_type": "git-clone", + "description": "You'll get a new node Latent Size Selector, you can pick the x and y sizes from a list." + }, + { + "author": "Klinter", + "title": "Klinter_nodes", + "id": "klinter", + "reference": "https://github.com/klinter007/klinter_nodes", + "files": [ + "https://github.com/klinter007/klinter_nodes" + ], + "install_type": "git-clone", + "description": "Concat_strings atm - celebrating first_node" + }, + { + "author": "Ludobico", + "title": "ComfyUI-ScenarioPrompt", + "id": "scenarioprompt", + "reference": "https://github.com/Ludobico/ComfyUI-ScenarioPrompt", + "files": [ + "https://github.com/Ludobico/ComfyUI-ScenarioPrompt" + ], + "install_type": "git-clone", + "description": "ScenarioPrompt is a custom node that helps you understand what you're prompting for each property as you build your prompts" + }, + { + "author": "logtd", + "title": "InstanceDiffusion Nodes", + "id": "instancediffusion", + "reference": "https://github.com/logtd/ComfyUI-InstanceDiffusion", + "files": [ + "https://github.com/logtd/ComfyUI-InstanceDiffusion" + ], + "install_type": "git-clone", + "description": "A set of nodes to perform multi-object prompting with InstanceDiffusion" + }, + { + "author": "logtd", + "title": "Tracking Nodes for Videos", + "id": "tracking", + "reference": "https://github.com/logtd/ComfyUI-TrackingNodes", + "files": [ + "https://github.com/logtd/ComfyUI-TrackingNodes" + ], + "install_type": "git-clone", + "description": "A set of nodes to track objects through videos using YOLO and other processors." + }, + { + "author": "logtd", + "title": "ComfyUI-InversedNoise", + "id": "inversed-noise", + "reference": "https://github.com/logtd/ComfyUI-InversedNoise", + "files": [ + "https://github.com/logtd/ComfyUI-InversedNoise" + ], + "install_type": "git-clone", + "description": "Nodes:Inversed Euler Sampler, Mix Noise with Latent, Combine Latent Noise" + }, + { + "author": "logtd", + "title": "ComfyUI-RefSampling", + "id": "refsampling", + "reference": "https://github.com/logtd/ComfyUI-RefSampling", + "files": [ + "https://github.com/logtd/ComfyUI-RefSampling" + ], + "install_type": "git-clone", + "description": "Nodes:Apply Ref UNet, Ref Sampler, Ref Sampler Custom" + }, + { + "author": "logtd", + "title": "ComfyUI-FLATTEN", + "id": "flatten", + "reference": "https://github.com/logtd/ComfyUI-FLATTEN", + "files": [ + "https://github.com/logtd/ComfyUI-FLATTEN" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes to use [a/FLATTEN: optical FLow-guided ATTENtion for consistent text-to-video editing](https://github.com/yrcong/flatten)." + }, + { + "author": "logtd", + "title": "ComfyUI-RAVE Attention", + "id": "rave", + "reference": "https://github.com/logtd/ComfyUI-RAVE_ATTN", + "files": [ + "https://github.com/logtd/ComfyUI-RAVE_ATTN" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes to use RAVE attention as a temporal attention mechanism.\nThis differs from other implementations in that it does not concatenate the images together, but within the UNet's Self-Attention mechanism performs the RAVE technique. By not altering the images/latents throughout the UNet, this method does not affect other temporal techniques, style mechanisms, or other UNet modifications.\nFor example, it can be combined with AnimateDiff, ModelScope/ZeroScope, or FLATTEN." + }, + { + "author": "Big-Idea-Technology", + "title": "ComfyUI-Book-Tools Nodes for ComfyUI", + "id": "booktool", + "reference": "https://github.com/Big-Idea-Technology/ComfyUI-Book-Tools", + "files": [ + "https://github.com/Big-Idea-Technology/ComfyUI-Book-Tools" + ], + "install_type": "git-clone", + "description": "ComfyUI-Book-Tools is a set o new nodes for ComfyUI that allows users to easily add text overlays to images within their ComfyUI projects. This Node leverages Python Imaging Library (PIL) and PyTorch to dynamically render text on images, supporting a wide range of customization options including font size, alignment, color, and padding. Loop with any parameters (*), prompt batch schedule with prompt selector, end queue for automatic ending current queue." + }, + { + "author": "Big Idea Technology", + "title": "LLM Node for ComfyUI", + "reference": "https://github.com/Big-Idea-Technology/ComfyUI_LLM_Node", + "files": [ + "https://github.com/Big-Idea-Technology/ComfyUI_LLM_Node" + ], + "install_type": "git-clone", + "description": "The LLM_Node enhances ComfyUI by integrating advanced language model capabilities, enabling a wide range of NLP tasks such as text generation, content summarization, question answering, and more. This flexibility is powered by various transformer model architectures from the transformers library, allowing for the deployment of models like T5, GPT-2, and others based on your project's needs." + }, + { + "author": "Guillaume-Fgt", + "title": "ComfyUI_StableCascadeLatentRatio", + "id": "cascade-latent-ratio", + "reference": "https://github.com/Guillaume-Fgt/ComfyUI_StableCascadeLatentRatio", + "files": [ + "https://github.com/Guillaume-Fgt/ComfyUI_StableCascadeLatentRatio" + ], + "install_type": "git-clone", + "description": "A custom node to create empty latents for Stable Cascade.\nfeatures: width and height incrementation of 64 by default, possibility to lock the aspect ratio, switch width/height at execution" + }, + { + "author": "AuroBit", + "title": "ComfyUI OOTDiffusion", + "id": "ootdiffusion", + "reference": "https://github.com/AuroBit/ComfyUI-OOTDiffusion", + "files": [ + "https://github.com/AuroBit/ComfyUI-OOTDiffusion" + ], + "install_type": "git-clone", + "description": "A ComfyUI custom node that simply integrates the [a/OOTDiffusion](https://github.com/levihsu/OOTDiffusion) functionality." + }, + { + "author": "AuroBit", + "title": "ComfyUI-AnimateAnyone-reproduction", + "id": "animateanyone-reproduction", + "reference": "https://github.com/AuroBit/ComfyUI-AnimateAnyone-reproduction", + "files": [ + "https://github.com/AuroBit/ComfyUI-AnimateAnyone-reproduction" + ], + "install_type": "git-clone", + "description": "A ComfyUI custom node that simply integrates the [a/animate-anyone-reproduction](https://github.com/bendanzzc/AnimateAnyone-reproduction) functionality." + }, + { + "author": "czcz1024", + "title": "Face Compare", + "id": "facecompare", + "reference": "https://github.com/czcz1024/Comfyui-FaceCompare", + "files": [ + "https://github.com/czcz1024/Comfyui-FaceCompare" + ], + "install_type": "git-clone", + "description": "Nodes:FaceCompare" + }, + { + "author": "TheBill2001", + "title": "comfyui-upscale-by-model", + "reference": "https://github.com/TheBill2001/comfyui-upscale-by-model", + "files": [ + "https://github.com/TheBill2001/comfyui-upscale-by-model" + ], + "install_type": "git-clone", + "description": "This custom node allow upscaling an image by a factor using a model." + }, + { + "author": "leoleelxh", + "title": "ComfyUI-LLMs", + "reference": "https://github.com/leoleelxh/ComfyUI-LLMs", + "files": [ + "https://github.com/leoleelxh/ComfyUI-LLMs" + ], + "install_type": "git-clone", + "description": "A minimalist node that calls LLMs, combined with one API, can call all language models, including local models." + }, + { + "author": "hughescr", + "title": "OpenPose Keypoint Extractor", + "reference": "https://github.com/hughescr/ComfyUI-OpenPose-Keypoint-Extractor", + "files": [ + "https://github.com/hughescr/ComfyUI-OpenPose-Keypoint-Extractor" + ], + "install_type": "git-clone", + "description": "This is a single node which can take the POSE_KEYPOINT output from the OpenPose extractor node, parse it, and return x,y,width,height bounding boxes around any elements of the OpenPose skeleton" + }, + { + "author": "jkrauss82", + "title": "ULTools for ComfyUI", + "reference": "https://github.com/jkrauss82/ultools-comfyui", + "files": [ + "https://github.com/jkrauss82/ultools-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:SaveImgAdv, CLIPTextEncodeWithStats. Collection of tools supporting txt2img generation in ComfyUI and other tasks." + }, + { + "author": "hiforce", + "title": "Comfyui HiFORCE Plugin", + "reference": "https://github.com/hiforce/comfyui-hiforce-plugin", + "files": [ + "https://github.com/hiforce/comfyui-hiforce-plugin" + ], + "install_type": "git-clone", + "description": "Custom nodes pack provided by [a/HiFORCE](https://www.hiforce.net/) for ComfyUI. This custom node helps to conveniently enhance images through Sampler, Upscaler, Mask, and more.\nNOTE:You should install [a/ComfyUI-Impact-Pack](https://github.com/ltdrdata/ComfyUI-Impact-Pack). Many optimizations are built upon the foundation of ComfyUI-Impact-Pack." + }, + { + "author": "kuschanow", + "title": "Advanced Latent Control", + "reference": "https://github.com/RomanKuschanow/ComfyUI-Advanced-Latent-Control", + "files": [ + "https://github.com/RomanKuschanow/ComfyUI-Advanced-Latent-Control" + ], + "install_type": "git-clone", + "description": "This custom node helps to transform latent in different ways." + }, + { + "author": "guill", + "title": "abracadabra-comfyui", + "reference": "https://github.com/guill/abracadabra-comfyui", + "files": [ + "https://github.com/guill/abracadabra-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:Abracadabra Summary, Abracadabra" + }, + { + "author": "cerspense", + "title": "cspnodes", + "reference": "https://github.com/cerspense/ComfyUI_cspnodes", + "files": [ + "https://github.com/cerspense/ComfyUI_cspnodes" + ], + "install_type": "git-clone", + "description": "Nodes:Image Dir Iterator, Modelscopet2v, Modelscopev2v." + }, + { + "author": "qwixiwp", + "title": "queuetools", + "reference": "https://github.com/qwixiwp/queuetools", + "files": [ + "https://github.com/qwixiwp/queuetools" + ], + "install_type": "git-clone", + "description": "Nodes:load images (queue tools). tools made for queueing in comfyUI" + }, + { + "author": "Chan-0312", + "title": "ComfyUI-Prompt-Preview", + "reference": "https://github.com/Chan-0312/ComfyUI-Prompt-Preview", + "files": [ + "https://github.com/Chan-0312/ComfyUI-Prompt-Preview" + ], + "install_type": "git-clone", + "description": "Welcome to ComfyUI Prompt Preview, where you can visualize the styles from [sdxl_prompt_styler](https://github.com/twri/sdxl_prompt_styler)." + }, + { + "author": "munkyfoot", + "title": "ComfyUI-TextOverlay", + "id": "textoverlay-munkyfoot", + "reference": "https://github.com/Munkyfoot/ComfyUI-TextOverlay", + "files": [ + "https://github.com/Munkyfoot/ComfyUI-TextOverlay" + ], + "install_type": "git-clone", + "description": "This extension provides a node that allows you to overlay text on an image or a batch of images with support for custom fonts and styles." + }, + { + "author": "holchan", + "title": "ComfyUI-ModelDownloader", + "reference": "https://github.com/holchan/ComfyUI-ModelDownloader", + "files": [ + "https://github.com/holchan/ComfyUI-ModelDownloader" + ], + "install_type": "git-clone", + "description": "A ComfyUI node to download models(Checkpoints and LoRA) from external links and act as an output standalone node." + }, + { + "author": "CC-BryanOttho", + "title": "ComfyUI_API_Manager", + "reference": "https://github.com/CC-BryanOttho/ComfyUI_API_Manager", + "files": [ + "https://github.com/CC-BryanOttho/ComfyUI_API_Manager" + ], + "install_type": "git-clone", + "description": "This package provides three custom nodes designed to streamline workflows involving API requests, dynamic text manipulation based on API responses, and image posting to APIs. These nodes are particularly useful for automating interactions with APIs, enhancing text-based workflows with dynamic data, and facilitating image uploads." + }, + { + "author": "maracman", + "title": "ComfyUI-SubjectStyle-CSV", + "reference": "https://github.com/maracman/ComfyUI-SubjectStyle-CSV", + "files": [ + "https://github.com/maracman/ComfyUI-SubjectStyle-CSV" + ], + "install_type": "git-clone", + "description": "Store a CSV of prompts where the style can change for each subject. The CSV node initialises with the column (style) and row (subject) names for easy interpretability." + }, + { + "author": "438443467", + "title": "ComfyUI-GPT4V-Image-Captioner", + "reference": "https://github.com/438443467/ComfyUI-GPT4V-Image-Captioner", + "files": [ + "https://github.com/438443467/ComfyUI-GPT4V-Image-Captioner" + ], + "install_type": "git-clone", + "description": "Nodes:GPT4V-Image-Captioner" + }, + { + "author": "uetuluk", + "title": "comfyui-webcam-node", + "id": "webcam", + "reference": "https://github.com/uetuluk/comfyui-webcam-node", + "files": [ + "https://github.com/uetuluk/comfyui-webcam-node" + ], + "install_type": "git-clone", + "description": "Nodes:Webcam Capture" + }, + { + "author": "huchenlei", + "title": "ComfyUI-layerdiffuse (layerdiffusion)", + "id": "layerdiffuse", + "reference": "https://github.com/huchenlei/ComfyUI-layerdiffuse", + "files": [ + "https://github.com/huchenlei/ComfyUI-layerdiffuse" + ], + "install_type": "git-clone", + "description": "ComfyUI implementation of [a/LayerDiffusion](https://github.com/layerdiffusion/LayerDiffusion)." + }, + { + "author": "huchenlei", + "title": "ComfyUI_DanTagGen", + "id": "dantangen", + "reference": "https://github.com/huchenlei/ComfyUI_DanTagGen", + "files": [ + "https://github.com/huchenlei/ComfyUI_DanTagGen" + ], + "install_type": "git-clone", + "description": "ComfyUI node of [a/Kohaku's DanTagGen Demo](https://huggingface.co/KBlueLeaf/DanTagGen?not-for-all-audiences=true)." + }, + { + "author": "huchenlei", + "title": "ComfyUI-openpose-editor", + "reference": "https://github.com/huchenlei/ComfyUI-openpose-editor", + "files": [ + "https://github.com/huchenlei/ComfyUI-openpose-editor" + ], + "install_type": "git-clone", + "description": "Port of [a/https://github.com/huchenlei/sd-webui-openpose-editor](https://github.com/huchenlei/sd-webui-openpose-editor) in ComfyUI" + }, + { + "author": "huchenlei", + "title": "ComfyUI-IC-Light-Native", + "id": "ic-light-native", + "reference": "https://github.com/huchenlei/ComfyUI-IC-Light-Native", + "files": [ + "https://github.com/huchenlei/ComfyUI-IC-Light-Native" + ], + "install_type": "git-clone", + "description": "ComfyUI native implementation of [a/IC-Light](https://github.com/lllyasviel/IC-Light)." + }, + { + "author": "huchenlei", + "title": "ComfyUI DenseDiffusion", + "id": "densediffusion", + "reference": "https://github.com/huchenlei/ComfyUI_densediffusion", + "files": [ + "https://github.com/huchenlei/ComfyUI_densediffusion" + ], + "install_type": "git-clone", + "description": "[a/DenseDiffusion](https://github.com/naver-ai/DenseDiffusion) custom node for ComfyUI." + }, + { + "author": "huchenlei", + "title": "ComfyUI_omost", + "id": "omost", + "reference": "https://github.com/huchenlei/ComfyUI_omost", + "files": [ + "https://github.com/huchenlei/ComfyUI_omost" + ], + "install_type": "git-clone", + "description": "ComfyUI implementation of [a/Omost](https://github.com/lllyasviel/Omost), and everything about regional prompt.\nNOTE: You need to install ComfyUI_densediffusion to use this node." + }, + { + "author": "nathannlu", + "title": "ComfyUI Pets", + "id": "pets", + "reference": "https://github.com/nathannlu/ComfyUI-Pets", + "files": [ + "https://github.com/nathannlu/ComfyUI-Pets" + ], + "install_type": "git-clone", + "description": "Play with your pet while your workflow generates!" + }, + { + "author": "nathannlu", + "title": "Comfy Cloud", + "id": "cloud", + "reference": "https://github.com/nathannlu/ComfyUI-Cloud", + "files": [ + "https://github.com/nathannlu/ComfyUI-Cloud" + ], + "install_type": "git-clone", + "description": "Run your workflow using cloud GPU resources, from your local ComfyUI.\nNOTE:After you first install the plugin...\nThe first time you click 'generate', you will be prompted to log into your account.Subsequent generations after the first is faster (the first run it takes a while to process your workflow). Once those two steps have been completed, you will be able to seamlessly generate your workflow on the cloud!" + }, + { + "author": "11dogzi", + "title": "Comfyui-ergouzi-Nodes", + "id": "ergouzi-nodes", + "reference": "https://github.com/11dogzi/Comfyui-ergouzi-Nodes", + "files": [ + "https://github.com/11dogzi/Comfyui-ergouzi-Nodes" + ], + "install_type": "git-clone", + "description": "This is a node group kit that covers multiple nodes such as local refinement, tag management, random prompt words, text processing, image processing, mask processing, etc" + }, + { + "author": "11dogzi", + "title": "Comfyui-ergouzi-samplers", + "id": "ergouzi-samplers", + "reference": "https://github.com/11dogzi/Comfyui-ergouzi-samplers", + "files": [ + "https://github.com/11dogzi/Comfyui-ergouzi-samplers" + ], + "install_type": "git-clone", + "description": "Partial redraw sampler and variant seed sampler" + }, + { + "author": "11dogzi", + "title": "ComfUI-EGAdapterMadAssistant", + "id": "ergouzi-samplers", + "reference": "https://github.com/11dogzi/ComfUI-EGAdapterMadAssistant", + "files": [ + "https://github.com/11dogzi/ComfUI-EGAdapterMadAssistant" + ], + "install_type": "git-clone", + "description": "This is a hierarchical auxiliary project of the IPAdapter project, which uses a slider to quickly control the hierarchical weights and add fully random and semi random modes" + }, + { + "author": "BXYMartin", + "title": "ComfyUI-InstantIDUtils", + "id": "instantid-utils", + "reference": "https://github.com/BXYMartin/ComfyUI-InstantIDUtils", + "files": [ + "https://github.com/BXYMartin/ComfyUI-InstantIDUtils" + ], + "install_type": "git-clone", + "description": "Nodes:Multi-ControlNet Converter, List of Images, Convert PIL to Tensor (NHWC), Convert Tensor (NHWC) to (NCHW), Convert Tensor (NHWC) to PIL" + }, + { + "author": "cdb-boop", + "title": "comfyui-image-round", + "id": "image-round", + "reference": "https://github.com/cdb-boop/comfyui-image-round", + "files": [ + "https://github.com/cdb-boop/comfyui-image-round" + ], + "install_type": "git-clone", + "description": "A simple node to round an input image up (pad) or down (crop) to the nearest integer multiple. Padding offset from left/bottom and the padding value are adjustable." + }, + { + "author": "cdb-boop", + "title": "ComfyUI Bringing Old Photos Back to Life", + "reference": "https://github.com/cdb-boop/ComfyUI-Bringing-Old-Photos-Back-to-Life", + "files": [ + "https://github.com/cdb-boop/ComfyUI-Bringing-Old-Photos-Back-to-Life" + ], + "install_type": "git-clone", + "description": "Enhance old or low-quality images in ComfyUI. Optional features include automatic scratch removal and face enhancement. Based on Microsoft's Bringing-Old-Photos-Back-to-Life. Requires installing models, so see instructions here: https://github.com/cdb-boop/ComfyUI-Bringing-Old-Photos-Back-to-Life." + }, + { + "author": "atmaranto", + "title": "SaveAsScript", + "id": "saveasscript", + "reference": "https://github.com/atmaranto/ComfyUI-SaveAsScript", + "files": [ + "https://github.com/atmaranto/ComfyUI-SaveAsScript" + ], + "install_type": "git-clone", + "description": "A version of ComfyUI-to-Python-Extension that works as a custom node. Adds a button in the UI that saves the current workflow as a Python file, a CLI for converting workflows, and slightly better custom node support." + }, + { + "author": "meshmesh-io", + "title": "mm-comfyui-megamask", + "id": "megamask", + "reference": "https://github.com/meshmesh-io/mm-comfyui-megamask", + "files": [ + "https://github.com/meshmesh-io/mm-comfyui-megamask" + ], + "install_type": "git-clone", + "description": "Nodes:ColorListMaskToImage, FlattenAndCombineMaskImages" + }, + { + "author": "meshmesh-io", + "title": "mm-comfyui-loopback", + "id": "mm-loopback", + "reference": "https://github.com/meshmesh-io/mm-comfyui-loopback", + "files": [ + "https://github.com/meshmesh-io/mm-comfyui-loopback" + ], + "install_type": "git-clone", + "description": "Nodes:Loop, LoopStart, LoopEnd, LoopStart_SEGIMAGE, LoopEnd_SEGIMAGE" + }, + { + "author": "meshmesh-io", + "title": "ComfyUI-MeshMesh", + "id": "meshmesh", + "reference": "https://github.com/meshmesh-io/ComfyUI-MeshMesh", + "files": [ + "https://github.com/meshmesh-io/ComfyUI-MeshMesh" + ], + "install_type": "git-clone", + "description": "Nodes:Masks to Colored Masks, Color Picker" + }, + { + "author": "CozyMantis", + "title": "Cozy Human Parser", + "id": "humanparser", + "reference": "https://github.com/cozymantis/human-parser-comfyui-node", + "files": [ + "https://github.com/cozymantis/human-parser-comfyui-node" + ], + "install_type": "git-clone", + "description": "A ComfyUI node to automatically extract masks for body regions and clothing/fashion items. Made with 💚 by the CozyMantis squad." + }, + { + "author": "CozyMantis", + "title": "Cozy Reference Pose Generator", + "id": "posegen", + "reference": "https://github.com/cozymantis/pose-generator-comfyui-node", + "files": [ + "https://github.com/cozymantis/pose-generator-comfyui-node" + ], + "install_type": "git-clone", + "description": "Generate OpenPose face/body reference poses in ComfyUI with ease. Made with 💚 by the CozyMantis squad." + }, + { + "author": "CozyMantis", + "title": "Cozy Utils", + "id": "cozy-utils", + "reference": "https://github.com/cozymantis/cozy-utils-comfyui-nodes", + "files": [ + "https://github.com/cozymantis/cozy-utils-comfyui-nodes" + ], + "install_type": "git-clone", + "description": "Various cozy nodes, made with 💚 by the CozyMantis squad." + }, + { + "author": "vivax3794", + "title": "ComfyUI-Vivax-Nodes", + "reference": "https://github.com/vivax3794/ComfyUI-Vivax-Nodes", + "files": [ + "https://github.com/vivax3794/ComfyUI-Vivax-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Inspect, Any String, Model From URL" + }, + { + "author": "vivax3794", + "title": "ComfyUI-Sub-Nodes", + "reference": "https://github.com/vivax3794/ComfyUI-Sub-Nodes", + "files": [ + "https://github.com/vivax3794/ComfyUI-Sub-Nodes" + ], + "install_type": "git-clone", + "description": "Creating subgraph and Calling subgraphs." + }, + { + "author": "victorchall", + "title": "Comfyui Webcam capture node", + "reference": "https://github.com/victorchall/comfyui_webcamcapture", + "files": [ + "https://github.com/victorchall/comfyui_webcamcapture" + ], + "install_type": "git-clone", + "description": "This node captures images one at a time from your webcam when you click generate.\nThis is particular useful for img2img or controlnet workflows.\nNOTE:This node will take over your webcam, so if you have another program using it, you may need to close that program first. Likewise, you may need to close Comfyui or close the workflow to release the webcam." + }, + { + "author": "ljleb", + "title": "Mecha Merge Node Pack", + "id": "mecha", + "reference": "https://github.com/ljleb/comfy-mecha", + "files": [ + "https://github.com/ljleb/comfy-mecha" + ], + "install_type": "git-clone", + "description": "model merging nodes powered by sd-mecha, a memory efficient state dict recipe merger." + }, + { + "author": "diSty", + "title": "ComfyUI Frame Maker", + "id": "frame-maker", + "reference": "https://github.com/diStyApps/ComfyUI_FrameMaker", + "files": [ + "https://github.com/diStyApps/ComfyUI_FrameMaker" + ], + "install_type": "git-clone", + "description": "This node creates a sequence of frames by moving and scaling a subject image over a background image." + }, + { + "author": "hackkhai", + "title": "ComfyUI-Image-Matting", + "id": "image-matting", + "reference": "https://github.com/hackkhai/ComfyUI-Image-Matting", + "files": [ + "https://github.com/hackkhai/ComfyUI-Image-Matting" + ], + "install_type": "git-clone", + "description": "This node improves the quality of the image mask. more suitable for image composite matting" + }, + { + "author": "Pos13", + "title": "Cyclist", + "id": "cyclist", + "reference": "https://github.com/Pos13/comfyui-cyclist", + "files": [ + "https://github.com/Pos13/comfyui-cyclist" + ], + "install_type": "git-clone", + "description": "This extension provides tools to iterate generation results between runs. In general, it's for cycles." + }, + { + "author": "ExponentialML", + "title": "ComfyUI_ModelScopeT2V", + "id": "modelscopet2v", + "reference": "https://github.com/ExponentialML/ComfyUI_ModelScopeT2V", + "files": [ + "https://github.com/ExponentialML/ComfyUI_ModelScopeT2V" + ], + "install_type": "git-clone", + "description": "Allows native usage of ModelScope based Text To Video Models in ComfyUI" + }, + { + "author": "ExponentialML", + "title": "ComfyUI - Native DynamiCrafter", + "id": "dynamicrafter", + "reference": "https://github.com/ExponentialML/ComfyUI_Native_DynamiCrafter", + "files": [ + "https://github.com/ExponentialML/ComfyUI_Native_DynamiCrafter" + ], + "install_type": "git-clone", + "description": "DynamiCrafter that works natively with ComfyUI's nodes, optimizations, ControlNet, and more." + }, + { + "author": "ExponentialML", + "title": "ComfyUI_VisualStylePrompting", + "id": "visual-style-prompting", + "reference": "https://github.com/ExponentialML/ComfyUI_VisualStylePrompting", + "files": [ + "https://github.com/ExponentialML/ComfyUI_VisualStylePrompting" + ], + "install_type": "git-clone", + "description": "ComfyUI Version of '[a/Visual Style Prompting with Swapping Self-Attention](https://github.com/naver-ai/Visual-Style-Prompting)'" + }, + { + "author": "angeloshredder", + "title": "StableCascadeResizer", + "reference": "https://github.com/angeloshredder/StableCascadeResizer", + "files": [ + "https://github.com/angeloshredder/StableCascadeResizer" + ], + "install_type": "git-clone", + "description": "Nodes:Cascade_Resizer" + }, + { + "author": "stavsap", + "title": "ComfyUI Ollama", + "id": "ollama", + "reference": "https://github.com/stavsap/comfyui-ollama", + "files": [ + "https://github.com/stavsap/comfyui-ollama" + ], + "install_type": "git-clone", + "description": "Custom ComfyUI Nodes for interacting with [a/Ollama](https://ollama.com/) using the [a/ollama python client](https://github.com/ollama/ollama-python).\nIntegrate the power of LLMs into CompfyUI workflows easily." + }, + { + "author": "dchatel", + "title": "comfyui_facetools", + "id": "facetools", + "reference": "https://github.com/dchatel/comfyui_facetools", + "files": [ + "https://github.com/dchatel/comfyui_facetools" + ], + "install_type": "git-clone", + "description": "These custom nodes provide a rotation aware face extraction, paste back, and various face related masking options." + }, + { + "author": "prodogape", + "title": "Comfyui-Minio", + "id": "minio", + "reference": "https://github.com/prodogape/ComfyUI-Minio", + "files": [ + "https://github.com/prodogape/ComfyUI-Minio" + ], + "install_type": "git-clone", + "description": "This plugin is mainly based on Minio, implementing the ability to read images from Minio, save images, facilitating expansion and connection across multiple machines." + }, + { + "author": "prodogape", + "title": "ComfyUI-EasyOCR", + "id": "easyocr", + "reference": "https://github.com/prodogape/ComfyUI-EasyOCR", + "files": [ + "https://github.com/prodogape/ComfyUI-EasyOCR" + ], + "install_type": "git-clone", + "description": "This node is primarily based on Easy-OCR to implement OCR text recognition functionality." + }, + { + "author": "prodogape", + "title": "ComfyUI-OmDet", + "id": "omdet", + "reference": "https://github.com/prodogape/ComfyUI-OmDet", + "files": [ + "https://github.com/prodogape/ComfyUI-OmDet" + ], + "install_type": "git-clone", + "description": "This node is mainly based on [a/OmDet](https://github.com/om-ai-lab/OmDet) for object detection, and it outputs related images, masks, and Labelme JSON information." + }, + { + "author": "prodogape", + "title": "Comfyui-Yolov8-JSON", + "reference": "https://github.com/prodogape/Comfyui-Yolov8-JSON", + "files": [ + "https://github.com/prodogape/Comfyui-Yolov8-JSON" + ], + "install_type": "git-clone", + "description": "This node is mainly based on the Yolov8 model for object detection, and it outputs related images, masks, and JSON information.[w/Repository url is changed. Please remove previous one and reinstall.]" + }, + { + "author": "kingzcheung", + "title": "ComfyUI_kkTranslator_nodes", + "id": "kktranslator", + "reference": "https://github.com/AIGCTeam/ComfyUI_kkTranslator_nodes", + "files": [ + "https://github.com/AIGCTeam/ComfyUI_kkTranslator_nodes" + ], + "install_type": "git-clone", + "description": "These nodes are mainly used to translate prompt words from other languages into English. PromptTranslateToText implements prompt word translation based on Helsinki NLP translation model.It doesn't require internet connection。" + }, + { + "author": "vsevolod-oparin", + "title": "Kandinsky 2.2 ComfyUI Plugin", + "id": "kandinsky", + "reference": "https://github.com/vsevolod-oparin/comfyui-kandinsky22", + "files": [ + "https://github.com/vsevolod-oparin/comfyui-kandinsky22" + ], + "install_type": "git-clone", + "description": "Nodes provide an options to combine prior and decoder models of Kandinsky 2.2." + }, + { + "author": "Xyem", + "title": "Xycuno Oobabooga", + "id": "xycuno-oobabooga", + "reference": "https://github.com/Xyem/Xycuno-Oobabooga", + "files": [ + "https://github.com/Xyem/Xycuno-Oobabooga" + ], + "install_type": "git-clone", + "description": "Xycuno Oobabooga provides custom nodes for ComfyUI, for sending requests to an [a/Oobabooga](https://github.com/oobabooga/text-generation-webui) instance to assist in creating prompt texts." + }, + { + "author": "shi3z", + "title": "ComfyUI_Memeplex_DALLE", + "id": "memeplex-dalle", + "reference": "https://github.com/shi3z/ComfyUI_Memeplex_DALLE", + "files": [ + "https://github.com/shi3z/ComfyUI_Memeplex_DALLE" + ], + "install_type": "git-clone", + "description": "You can use memeplex and DALL-E thru ComfyUI. You need API keys." + }, + { + "author": "if-ai", + "title": "ComfyUI-IF_AI_tools", + "id": "if-ai-tools", + "reference": "https://github.com/if-ai/ComfyUI-IF_AI_tools", + "files": [ + "https://github.com/if-ai/ComfyUI-IF_AI_tools" + ], + "install_type": "git-clone", + "description": "Various AI tools to use in Comfy UI. Starting with VL and prompt making tools using Ollma as backend will evolve as I find time." + }, + { + "author": "if-ai", + "title": "ComfyUI-IF_AI_WishperSpeechNode", + "id": "if-ai-whisper-speech", + "reference": "https://github.com/if-ai/ComfyUI-IF_AI_WishperSpeechNode", + "files": [ + "https://github.com/if-ai/ComfyUI-IF_AI_WishperSpeechNode" + ], + "install_type": "git-clone", + "description": "This repository hosts a Text-to-Speech (TTS) application that leverages Whisper Speech for voice synthesis, allowing users to train a voice model on-the-fly. It is built on ComfyUI and supports rapid training and inference processes." + }, + { + "author": "if-ai", + "title": "ComfyUI-IF_AI_HFDownloaderNode", + "id": "if-ai-hfdownloader", + "reference": "https://github.com/if-ai/ComfyUI-IF_AI_HFDownloaderNode", + "files": [ + "https://github.com/if-ai/ComfyUI-IF_AI_HFDownloaderNode" + ], + "install_type": "git-clone", + "description": "Talking avatars Heads for the IF_AI tools integrates dreamtalk in ComfyUI" + }, + { + "author": "dmMaze", + "title": "Sketch2Manga", + "id": "sketch2manga", + "reference": "https://github.com/dmMaze/sketch2manga", + "files": [ + "https://github.com/dmMaze/sketch2manga" + ], + "install_type": "git-clone", + "description": "Apply screentone to line drawings or colored illustrations with diffusion models." + }, + { + "author": "olduvai-jp", + "title": "ComfyUI-HfLoader", + "id": "hfloader", + "reference": "https://github.com/olduvai-jp/ComfyUI-HfLoader", + "files": [ + "https://github.com/olduvai-jp/ComfyUI-HfLoader" + ], + "install_type": "git-clone", + "description": "Nodes:Lora Loader From HF" + }, + { + "author": "AiMiDi", + "title": "ComfyUI-Aimidi-nodes", + "id": "aimidi-nodes", + "reference": "https://github.com/AiMiDi/ComfyUI-Aimidi-nodes", + "files": [ + "https://github.com/AiMiDi/ComfyUI-Aimidi-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Merge Tag, Clear Tag, Add Tag, Load Images Pair Batch, Save Images Pair" + }, + { + "author": "ForeignGods", + "title": "ComfyUI-Mana-Nodes", + "id": "mana-nodes", + "reference": "https://github.com/ForeignGods/ComfyUI-Mana-Nodes", + "files": [ + "https://github.com/ForeignGods/ComfyUI-Mana-Nodes" + ], + "install_type": "git-clone", + "description": "Font Animation, Speech Recognition, Caption Generator, TTS" + }, + { + "author": "Cornea Valentin", + "title": "ControlNet Auxiliar", + "id": "controlnet-aux-valentin", + "reference": "https://github.com/madtunebk/ComfyUI-ControlnetAux", + "files": [ + "https://github.com/madtunebk/ComfyUI-ControlnetAux" + ], + "install_type": "git-clone", + "description": "This ComfyUI custom node, named ControlNet Auxiliar, is designed to provide auxiliary functionalities for image processing tasks. It is particularly useful for various image manipulation and enhancement operations. The node is integrated with functionalities for converting images between different formats and applying various image processing techniques." + }, + { + "author": "MarkoCa1", + "title": "ComfyUI-Text", + "reference": "https://github.com/MarkoCa1/ComfyUI-Text", + "files": [ + "https://github.com/MarkoCa1/ComfyUI-Text" + ], + "install_type": "git-clone", + "description": "Text." + }, + { + "author": "MarkoCa1", + "title": "ComfyUI_Segment_Mask", + "id": "seg-mask", + "reference": "https://github.com/MarkoCa1/ComfyUI_Segment_Mask", + "files": [ + "https://github.com/MarkoCa1/ComfyUI_Segment_Mask" + ], + "install_type": "git-clone", + "description": "Mask cutout based on Segment Anything." + }, + { + "author": "Shadetail", + "title": "Eagleshadow Custom Nodes", + "id": "eagleshadow", + "reference": "https://github.com/Shadetail/ComfyUI_Eagleshadow", + "files": [ + "https://github.com/Shadetail/ComfyUI_Eagleshadow" + ], + "install_type": "git-clone", + "description": "Custom nodes for ComfyUI by Eagleshadow." + }, + { + "author": "ArdeniusAI", + "title": "CPlus_Ardenius ComfyUI Control Box", + "id": "controlbox", + "reference": "https://github.com/ArdeniusAI/CPlus_Ardenius", + "files": [ + "https://github.com/ArdeniusAI/CPlus_Ardenius" + ], + "install_type": "git-clone", + "description": "1 node to have control over your workflow." + }, + { + "author": "Jannchie", + "title": "ComfyUI-J", + "reference": "https://github.com/Jannchie/ComfyUI-J", + "files": [ + "https://github.com/Jannchie/ComfyUI-J" + ], + "install_type": "git-clone", + "description": "This is a completely different set of nodes than Comfy's own KSampler series. This set of nodes is based on Diffusers, which makes it easier to import models, apply prompts with weights, inpaint, reference only, controlnet, etc." + }, + { + "author": "daxcay", + "title": "ComfyUI-JDCN", + "id": "jdcn", + "reference": "https://github.com/daxcay/ComfyUI-JDCN", + "files": [ + "https://github.com/daxcay/ComfyUI-JDCN" + ], + "install_type": "git-clone", + "description": "Jerry Davos Custom Nodes for Saving Latents in Directory (BatchLatentSave) , Importing Latent from directory (BatchLatentLoadFromDir) , List to string, string to list, get any file list from directory which give filepath, filename, move any files from any directory to any other directory, VHS Video combine file mover, rebatch list of strings, batch image load from any dir, load image batch from any directory and other custom nodes." + }, + { + "author": "daxcay", + "title": "ComfyUI-DataSet", + "reference": "https://github.com/daxcay/ComfyUI-DataSet", + "files": [ + "https://github.com/daxcay/ComfyUI-DataSet" + ], + "install_type": "git-clone", + "description": "Data Research, Preparation And Manipulators Nodes for Model Trainers, Artists, Designers and Animators. Captions, Visualizer, Text Manipulator\nNOTE: This repo is renamed to ComfyUI-DataSet.\n[w/Repository name is renamed to ComfyUI-DataSet from ComfyUI-DRMN. Please, remove previous one and reinstall.]" + }, + { + "author": "daxcay", + "title": "ComfyUI-NODEJS", + "reference": "https://github.com/daxcay/ComfyUI-NODEJS", + "files": [ + "https://github.com/daxcay/ComfyUI-NODEJS" + ], + "install_type": "git-clone", + "description": "This node allows the execution of Node.js application within ComfyUI by leveraging the ComfyUI-NODEJS, which starts alongside ComfyUI and facilitates the installation of Node.js. The integration enables Python subprocesses to execute Node.js scripts." + }, + { + "author": "Seedsa", + "title": "ComfyUI Fooocus Nodes", + "id": "fooocus-nodes", + "reference": "https://github.com/Seedsa/Fooocus_Nodes", + "files": [ + "https://github.com/Seedsa/Fooocus_Nodes" + ], + "install_type": "git-clone", + "description": "This extension provides image generation features based on Fooocus." + }, + { + "author": "zhangp365", + "title": "zhangp365/Some Utils for ComfyUI", + "reference": "https://github.com/zhangp365/ComfyUI-utils-nodes", + "files": [ + "https://github.com/zhangp365/ComfyUI-utils-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:LoadImageWithSwitch, ImageBatchOneOrMore, ConcatText, ModifyTextGender" + }, + { + "author": "ratulrafsan", + "title": "Comfyui-SAL-VTON", + "id": "sal-vton", + "reference": "https://github.com/ratulrafsan/Comfyui-SAL-VTON", + "files": [ + "https://github.com/ratulrafsan/Comfyui-SAL-VTON" + ], + "install_type": "git-clone", + "description": "Dressup your models!\nThis is my quick implementation of the SAL-VTON node for ComfyUI.\nBased on the paper [a/Keyu Y. Tingwei G. et al. (2023). Linking Garment with Person via Semantically Associated Landmakrs for Virtual Try-On](https://openaccess.thecvf.com/content/CVPR2023/papers/Yan_Linking_Garment_With_Person_via_Semantically_Associated_Landmarks_for_Virtual_CVPR_2023_paper.pdf)" + }, + { + "author": "Nevysha", + "title": "ComfyUI-nevysha-top-menu", + "id": "nevysha-top-menu", + "reference": "https://github.com/Nevysha/ComfyUI-nevysha-top-menu", + "files": [ + "https://github.com/Nevysha/ComfyUI-nevysha-top-menu" + ], + "install_type": "git-clone", + "description": "A simple sidebar tweak to force fixe the ComfyUI menu to the top of the screen. Reaaally quick and dirty. May break with some ComfyUI setup." + }, + { + "author": "alisson-anjos", + "title": "ComfyUI-Ollama-Describer", + "id": "ollama-describer", + "reference": "https://github.com/alisson-anjos/ComfyUI-Ollama-Describer", + "files": [ + "https://github.com/alisson-anjos/ComfyUI-Ollama-Describer" + ], + "install_type": "git-clone", + "description": "This is an extension for ComfyUI that makes it possible to use some LLM models provided by Ollama, such as Gemma, Llava (multimodal), Llama2, Llama3 or Mistral. Speaking specifically of the LLaVa - Large Language and Vision Assistant model, although trained on a relatively small dataset, it demonstrates exceptional capabilities in understanding images and answering questions about them. This model presents similar behaviors to multimodal models such as GPT-4, even when presented with invisible images and instructions." + }, + { + "author": "chaosaiart", + "title": "Chaosaiart-Nodes", + "id": "chaosaiart", + "reference": "https://github.com/chaosaiart/Chaosaiart-Nodes", + "files": [ + "https://github.com/chaosaiart/Chaosaiart-Nodes" + ], + "install_type": "git-clone", + "description": "LowVRAM Animation : txt2video - img2video - video2video , Frame by Frame, compatible with LowVRAM GPUs\nIncluded : Prompt Switch, Checkpoint Switch, Cache, Number Count by Frame, Ksampler txt2img & img2img ..." + }, + { + "author": "viperyl", + "title": "ComfyUI-BiRefNet", + "id": "birefnet", + "reference": "https://github.com/viperyl/ComfyUI-BiRefNet", + "files": [ + "https://github.com/viperyl/ComfyUI-BiRefNet" + ], + "install_type": "git-clone", + "description": "Bilateral Reference Network achieves SOTA result in multi Salient Object Segmentation dataset, this repo pack BiRefNet as ComfyUI nodes, and make this SOTA model easier use for everyone." + }, + { + "author": "viperyl", + "title": "ComfyUI-RGT", + "id": "rgt", + "reference": "https://github.com/viperyl/ComfyUI-RGT", + "pip": ["loguru"], + "files": [ + "https://github.com/viperyl/ComfyUI-RGT" + ], + "install_type": "git-clone", + "description": "This repo cast Recursive Generalization Transformer for Image Super-Resolution to ComfyUI, the original [a/paper link](https://arxiv.org/abs/2303.06373) and [a/github link](https://github.com/zhengchen1999/RGT)" + }, + { + "author": "SuperBeastsAI", + "title": "ComfyUI-SuperBeasts", + "id": "superbeasts", + "reference": "https://github.com/SuperBeastsAI/ComfyUI-SuperBeasts", + "files": [ + "https://github.com/SuperBeastsAI/ComfyUI-SuperBeasts" + ], + "install_type": "git-clone", + "description": "Nodes:HDR Effects (SuperBeasts.AI). This repository contains custom nodes for ComfyUI created and used by SuperBeasts.AI (@SuperBeasts.AI on Instagram)" + }, + { + "author": "hay86", + "title": "ComfyUI Dreamtalk", + "id": "dreamtalk", + "reference": "https://github.com/hay86/ComfyUI_Dreamtalk", + "files": [ + "https://github.com/hay86/ComfyUI_Dreamtalk" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/dreamtalk](https://github.com/ali-vilab/dreamtalk) for ComfyUI" + }, + { + "author": "hay86", + "title": "ComfyUI Hallo", + "id": "hallo-hay86", + "reference": "https://github.com/hay86/ComfyUI_Hallo", + "files": [ + "https://github.com/hay86/ComfyUI_Hallo" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/hallo](https://github.com/fudan-generative-vision/hallo) for ComfyUI" + }, + { + "author": "hay86", + "title": "ComfyUI OpenVoice", + "id": "openvoice-hay86", + "reference": "https://github.com/hay86/ComfyUI_OpenVoice", + "files": [ + "https://github.com/hay86/ComfyUI_OpenVoice" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/OpenVoice](https://github.com/myshell-ai/OpenVoice) for ComfyUI" + }, + { + "author": "hay86", + "title": "ComfyUI DDColor", + "id": "ddcolor-hay86", + "reference": "https://github.com/hay86/ComfyUI_DDColor", + "files": [ + "https://github.com/hay86/ComfyUI_DDColor" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/DDColor](https://github.com/piddnad/DDColor) for ComfyUI" + }, + { + "author": "hay86", + "title": "ComfyUI MiniCPM-V", + "id": "minicpm-v", + "reference": "https://github.com/hay86/ComfyUI_MiniCPM-V", + "files": [ + "https://github.com/hay86/ComfyUI_MiniCPM-V" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/MiniCPM-V](https://github.com/OpenBMB/MiniCPM-V) for ComfyUI" + }, + { + "author": "hay86", + "title": "ComfyUI AceNodes", + "reference": "https://github.com/hay86/ComfyUI_AceNodes", + "files": [ + "https://github.com/hay86/ComfyUI_AceNodes" + ], + "install_type": "git-clone", + "description": "Some useful custom nodes that are not included in ComfyUI core yet." + }, + { + "author": "shinich39", + "title": "comfyui-load-image-in-seq", + "reference": "https://github.com/shinich39/comfyui-load-image-in-seq", + "files": [ + "https://github.com/shinich39/comfyui-load-image-in-seq" + ], + "install_type": "git-clone", + "description": "This node is load png image sequentially with metadata. Only supported for PNG format that has been created by ComfyUI.[w/renamed from comfyui-load-image-39. You need to remove previous one and reinstall to this.]" + }, + { + "author": "shinich39", + "title": "comfyui-random-node", + "id": "random-node", + "reference": "https://github.com/shinich39/comfyui-ramdom-node", + "files": [ + "https://github.com/shinich39/comfyui-ramdom-node" + ], + "install_type": "git-clone", + "description": "Shuffle nodes after queue added. [w/Repository name has been changed from comfyui-random-node-39 to comfyui-random-node. Please remove and reinstall it.]" + }, + { + "author": "shinich39", + "title": "comfyui-local-db", + "reference": "https://github.com/shinich39/comfyui-local-db", + "files": [ + "https://github.com/shinich39/comfyui-local-db" + ], + "install_type": "git-clone", + "description": "Store text to Key-Values pair json." + }, + { + "author": "wei30172", + "title": "comfygen", + "reference": "https://github.com/wei30172/comfygen", + "files": [ + "https://github.com/wei30172/comfygen" + ], + "install_type": "git-clone", + "description": "Setting Up a Web Interface Using ComfyUI.\nNOTE:When installed, you can access it via http://127.0.0.1:8188/comfygen." + }, + { + "author": "zombieyang", + "title": "SD-PPP", + "reference": "https://github.com/zombieyang/sd-ppp", + "files": [ + "https://github.com/zombieyang/sd-ppp" + ], + "install_type": "git-clone", + "description": "!!Another custom node about Photoshop!! PPP means interoP with your PhotoshoP. You can get or send layers from/to your Photoshop. This custom node is easier to use." + }, + { + "author": "KytraScript", + "title": "ComfyUI_KytraWebhookHTTP", + "reference": "https://github.com/KytraScript/ComfyUI_KytraWebhookHTTP", + "files": [ + "https://github.com/KytraScript/ComfyUI_KytraWebhookHTTP" + ], + "install_type": "git-clone", + "description": "A ComfyUI node that utilizes Moviepy to convert and send your images or videos to a webhook endpoint directly from ComfyUI." + }, + { + "author": "1mckw", + "title": "Comfyui-Gelbooru", + "reference": "https://github.com/1mckw/Comfyui-Gelbooru", + "files": [ + "https://github.com/1mckw/Comfyui-Gelbooru" + ], + "install_type": "git-clone", + "description": "Get random images from gelbooru, support multiple tag searches, exclude tags, etc. user and api key are optional." + }, + { + "author": "NeuralSamurAI", + "title": "SuperPrompter Node for ComfyUI", + "reference": "https://github.com/NeuralSamurAI/Comfyui-Superprompt-Unofficial", + "files": [ + "https://github.com/NeuralSamurAI/Comfyui-Superprompt-Unofficial" + ], + "install_type": "git-clone", + "description": "The SuperPrompter node is a ComfyUI node that uses the SuperPrompt-v1 model from Hugging Face to generate text based on a given prompt. It provides various parameters to control the text generation process." + }, + { + "author": "MokkaBoss1", + "title": "Node Pack mostly for manipulating strings and integers", + "reference": "https://github.com/MokkaBoss1/ComfyUI_Mokkaboss1/wiki/Documentation-for-the-ComfyUI-Nodes-in-this-Node-Pack", + "files": [ + "https://github.com/MokkaBoss1/ComfyUI_Mokkaboss1" + ], + "install_type": "git-clone", + "description": "Node Pack mostly for manipulating strings and integers" + }, + { + "author": "jiaxiangc", + "title": "ResAdapter for ComfyUI", + "reference": "https://github.com/jiaxiangc/ComfyUI-ResAdapter", + "files": [ + "https://github.com/jiaxiangc/ComfyUI-ResAdapter" + ], + "install_type": "git-clone", + "description": "We provide ComfyUI-ResAdapter node to help users to use [a/ResAdapter](https://github.com/bytedance/res-adapter) in ComfyUI." + }, + { + "author": "ParisNeo", + "title": "lollms_nodes_suite", + "reference": "https://github.com/ParisNeo/lollms_nodes_suite", + "files": [ + "https://github.com/ParisNeo/lollms_nodes_suite" + ], + "install_type": "git-clone", + "description": "lollms_nodes_suite is a set of nodes for comfyui that harnesses the power of lollms, a state-of-the-art AI text generation tool, to improve the quality of image generation." + }, + { + "author": "IsItDanOrAi", + "title": "ComfyUI-Stereopsis", + "reference": "https://github.com/IsItDanOrAi/ComfyUI-Stereopsis", + "files": [ + "https://github.com/IsItDanOrAi/ComfyUI-Stereopsis" + ], + "install_type": "git-clone", + "description": "This initiative represents a solo venture dedicated to integrating a stereopsis effect within ComfyUI (Stable Diffusion). Presently, the project is focused on the refinement of node categorization within a unified framework, as it is in the early stages of development. However, it has achieved functionality in a fundamental capacity. By processing a video through the Side-by-Side (SBS) node and applying Frame Delay to one of the inputs, it facilitates the creation of a stereopsis effect. This effect is compatible with any Virtual Reality headset that supports SBS video playback, offering a practical application in immersive media experiences." + }, + { + "author": "nickve28", + "title": "ComfyUI Nich Utils", + "reference": "https://github.com/nickve28/ComfyUI-Nich-Utils", + "files": [ + "https://github.com/nickve28/ComfyUI-Nich-Utils" + ], + "install_type": "git-clone", + "description": "Several utility nodes for use with ComfyUI." + }, + { + "author": "FrankChieng", + "title": "ComfyUI_Aniportrait", + "reference": "https://github.com/frankchieng/ComfyUI_Aniportrait", + "files": [ + "https://github.com/frankchieng/ComfyUI_Aniportrait" + ], + "install_type": "git-clone", + "description": "implementation of [a/AniPortrait](https://github.com/Zejun-Yang/AniPortrait) generating of videos, includes self driven, face reenacment and audio driven with a reference image" + }, + { + "author": "FrankChieng", + "title": "ComfyUI_MagicClothing", + "reference": "https://github.com/frankchieng/ComfyUI_MagicClothing", + "files": [ + "https://github.com/frankchieng/ComfyUI_MagicClothing" + ], + "install_type": "git-clone", + "description": "implementation of MagicClothing with garment and prompt in ComfyUI" + }, + { + "author": "BlakeOne", + "title": "ComfyUI SchedulerMixer", + "reference": "https://github.com/BlakeOne/ComfyUI-SchedulerMixer", + "files": [ + "https://github.com/BlakeOne/ComfyUI-SchedulerMixer" + ], + "install_type": "git-clone", + "description": "Create a custom scheduler from a weighted average of the built-in schedulers" + }, + { + "author": "BlakeOne", + "title": "ComfyUI CustomScheduler", + "reference": "https://github.com/BlakeOne/ComfyUI-CustomScheduler", + "files": [ + "https://github.com/BlakeOne/ComfyUI-CustomScheduler" + ], + "install_type": "git-clone", + "description": "Simple node for setting the sigma values directly. Note, for a full denoise the last sigma should be zero." + }, + { + "author": "BlakeOne", + "title": "ComfyUI NodePresets", + "id": "nodepresets", + "reference": "https://github.com/BlakeOne/ComfyUI-NodePresets", + "files": [ + "https://github.com/BlakeOne/ComfyUI-NodePresets" + ], + "install_type": "git-clone", + "description": "An extension for ComyUI that enables saving and loading node presets using the node's context menu.\nRight click a node and choose 'Presets' from its context menu to access the node's presets." + }, + { + "author": "BlakeOne", + "title": "ComfyUI NodeReset", + "id": "nodereset", + "reference": "https://github.com/BlakeOne/ComfyUI-NodeReset", + "files": [ + "https://github.com/BlakeOne/ComfyUI-NodeReset" + ], + "install_type": "git-clone", + "description": "An extension for ComyUI to allow resetting a node's inputs to their default values.\nNOTE:Right click any node and choose 'Reset' from the context menu." + }, + { + "author": "kale4eat", + "title": "ComfyUI_demucus", + "id": "demucus", + "reference": "https://github.com/kale4eat/ComfyUI-path-util", + "files": [ + "https://github.com/kale4eat/ComfyUI-path-util" + ], + "install_type": "git-clone", + "description": "Path utility for ComfyUI" + }, + { + "author": "kale4eat", + "title": "ComfyUI-string-util", + "reference": "https://github.com/kale4eat/ComfyUI-string-util", + "files": [ + "https://github.com/kale4eat/ComfyUI-string-util" + ], + "install_type": "git-clone", + "description": "String utility for ComfyUI" + }, + { + "author": "kale4eat", + "title": "ComfyUI-text-file-util", + "reference": "https://github.com/kale4eat/ComfyUI-text-file-util", + "files": [ + "https://github.com/kale4eat/ComfyUI-text-file-util" + ], + "install_type": "git-clone", + "description": "Text file utility for ComfyUI" + }, + { + "author": "kale4eat", + "title": "ComfyUI-speech-dataset-toolkit", + "reference": "https://github.com/kale4eat/ComfyUI-speech-dataset-toolkit", + "files": [ + "https://github.com/kale4eat/ComfyUI-speech-dataset-toolkit" + ], + "install_type": "git-clone", + "description": "Basic audio tools using torchaudio for ComfyUI. It is assumed to assist in the speech dataset creation for ASR, TTS, etc." + }, + { + "author": "DrMWeigand", + "title": "ComfyUI Color Detection Nodes", + "reference": "https://github.com/DrMWeigand/ComfyUI_ColorImageDetection", + "files": [ + "https://github.com/DrMWeigand/ComfyUI_ColorImageDetection" + ], + "install_type": "git-clone", + "description": "A collection of nodes for detecting color in images, leveraging RGB and LAB color spaces. These nodes aim to distinguish colored images from black and white, including those with color tints." + }, + { + "author": "bobmagicii", + "title": "ComfyKit Custom Nodes", + "reference": "https://github.com/bobmagicii/comfykit-custom-nodes", + "files": [ + "https://github.com/bobmagicii/comfykit-custom-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:LoraWithMetadata, TypecasterImage." + }, + { + "author": "TJ16th", + "title": "comfyUI_TJ_NormalLighting", + "reference": "https://github.com/TJ16th/comfyUI_TJ_NormalLighting", + "files": [ + "https://github.com/TJ16th/comfyUI_TJ_NormalLighting" + ], + "install_type": "git-clone", + "description": "Custom Node for comfyUI for virtual lighting based on normal map.\nYou can use normal maps to add virtual lighting effects to your images." + }, + { + "author": "A4P7J1N7M05OT", + "title": "ComfyUI-PixelOE", + "reference": "https://github.com/A4P7J1N7M05OT/ComfyUI-PixelOE", + "files": [ + "https://github.com/A4P7J1N7M05OT/ComfyUI-PixelOE" + ], + "install_type": "git-clone", + "description": "A barebones ComfyUI wrapper for [a/PixelOE](https://github.com/KohakuBlueleaf/PixelOE).\nI cannot promise any support, if there is someone who wants to make a proper node, please do." + }, + { + "author": "A4P7J1N7M05OT", + "title": "ComfyUI-AutoColorGimp", + "reference": "https://github.com/A4P7J1N7M05OT/ComfyUI-AutoColorGimp", + "files": [ + "https://github.com/A4P7J1N7M05OT/ComfyUI-AutoColorGimp" + ], + "install_type": "git-clone", + "description": "Shamelessly copied the code to auto color correct the image like in gimp from this answer: [a/https://stackoverflow.com/a/56365560/4561887](https://stackoverflow.com/a/56365560/4561887)" + }, + { + "author": "ronniebasak", + "title": "ComfyUI-Tara-LLM-Integration", + "id": "tarallm", + "reference": "https://github.com/ronniebasak/ComfyUI-Tara-LLM-Integration", + "files": [ + "https://github.com/ronniebasak/ComfyUI-Tara-LLM-Integration" + ], + "install_type": "git-clone", + "description": "Tara is a powerful node for ComfyUI that integrates Large Language Models (LLMs) to enhance and automate workflow processes. With Tara, you can create complex, intelligent workflows that refine and generate content, manage API keys, and seamlessly integrate various LLMs into your projects." + }, + { + "author": "Sida Liu", + "title": "ComfyUI-Debug", + "id": "debug", + "reference": "https://github.com/liusida/ComfyUI-Debug", + "files": [ + "https://github.com/liusida/ComfyUI-Debug" + ], + "install_type": "git-clone", + "description": "Attach a debug node to an output to obtain more detailed information. Uncover the details of your models in ComfyUI with ease." + }, + { + "author": "Sida Liu", + "title": "ComfyUI-Login", + "id": "login", + "reference": "https://github.com/liusida/ComfyUI-Login", + "files": [ + "https://github.com/liusida/ComfyUI-Login" + ], + "install_type": "git-clone", + "description": "A simple password to protect ComfyUI." + }, + { + "author": "Sida Liu", + "title": "ComfyUI-AutoCropFaces", + "id": "autocropfaces", + "reference": "https://github.com/liusida/ComfyUI-AutoCropFaces", + "files": [ + "https://github.com/liusida/ComfyUI-AutoCropFaces" + ], + "install_type": "git-clone", + "description": "Use RetinaFace to detect and automatically crop faces." + }, + { + "author": "Sida Liu", + "title": "ComfyUI-SD3-nodes", + "id": "sd3-nodes", + "reference": "https://github.com/liusida/ComfyUI-SD3-nodes", + "files": [ + "https://github.com/liusida/ComfyUI-SD3-nodes" + ], + "install_type": "git-clone", + "description": "Nodes that support Stable Diffusion 3 Medium better." + }, + { + "author": "Sida Liu", + "title": "ComfyUI-B-LoRA", + "id": "b-lora", + "reference": "https://github.com/liusida/ComfyUI-B-LoRA", + "files": [ + "https://github.com/liusida/ComfyUI-B-LoRA" + ], + "install_type": "git-clone", + "description": "Load and apply B-LoRA models, currently B-LoRA models only works with SDXL (sdxl_base_1.0)." + }, + { + "author": "jtydhr88", + "title": "ComfyUI-Workflow-Encrypt", + "id": "workflow-encrypt", + "reference": "https://github.com/jtydhr88/ComfyUI-Workflow-Encrypt", + "files": [ + "https://github.com/jtydhr88/ComfyUI-Workflow-Encrypt" + ], + "install_type": "git-clone", + "description": "Encrypt your comfyui workflow, and share it with key" + }, + { + "author": "jtydhr88", + "title": "ComfyUI LayerDivider", + "id": "layer-divider", + "reference": "https://github.com/jtydhr88/ComfyUI-LayerDivider", + "files": [ + "https://github.com/jtydhr88/ComfyUI-LayerDivider" + ], + "install_type": "git-clone", + "description": "ComfyUI LayerDivider is custom nodes that generating layered psd files inside ComfyUI[w/Please follow readme and run install_windows_portable_win_py311_cu121 for ComfyUI embedded python.]" + }, + { + "author": "jtydhr88", + "title": "ComfyUI Unique3D", + "id": "unique3d", + "reference": "https://github.com/jtydhr88/ComfyUI-Unique3D", + "files": [ + "https://github.com/jtydhr88/ComfyUI-Unique3D" + ], + "install_type": "git-clone", + "description": "ComfyUI Unique3D is custom nodes that running AiuniAI/Unique3D into ComfyUI[w/Please follow readme to install with ComfyUI embedded python.]" + }, + { + "author": "SeaArtLab", + "title": "ComfyUI-Long-CLIP", + "reference": "https://github.com/SeaArtLab/ComfyUI-Long-CLIP", + "files": [ + "https://github.com/SeaArtLab/ComfyUI-Long-CLIP" + ], + "install_type": "git-clone", + "description": "This project implements the comfyui for long-clip, currently supporting the replacement of clip-l. For SD1.5, the SeaArtLongClip module can be used to replace the original clip in the model, expanding the token length from 77 to 248." + }, + { + "author": "tsogzark", + "title": "ComfyUI-load-image-from-url", + "reference": "https://github.com/tsogzark/ComfyUI-load-image-from-url", + "files": [ + "https://github.com/tsogzark/ComfyUI-load-image-from-url" + ], + "install_type": "git-clone", + "description": "A simple node to load image from local path or http url.\nYou can find this node from 'image' category." + }, + { + "author": "discus0434", + "title": "ComfyUI Caching Embeddings", + "id": "caching-embeddings", + "reference": "https://github.com/discus0434/comfyui-caching-embeddings", + "files": [ + "https://github.com/discus0434/comfyui-caching-embeddings" + ], + "install_type": "git-clone", + "description": "This repository simply caches the CLIP embeddings and subtly accelerates the inference process by bypassing unnecessary computations." + }, + { + "author": "discus0434", + "title": "ComfyUI Aesthetic Predictor V2.5", + "id": "caching-embeddings", + "reference": "https://github.com/discus0434/comfyui-aesthetic-predictor-v2-5", + "files": [ + "https://github.com/discus0434/comfyui-aesthetic-predictor-v2-5" + ], + "install_type": "git-clone", + "description": "Simple ComfyUI node that predicts the score of an aesthetic image with SigLIP-based predictor." + }, + { + "author": "AIFSH", + "title": "ComfyUI-UVR5", + "id": "uvr5", + "reference": "https://github.com/AIFSH/ComfyUI-UVR5", + "files": [ + "https://github.com/AIFSH/ComfyUI-UVR5" + ], + "install_type": "git-clone", + "description": "the custom code for [a/UVR5](https://github.com/Anjok07/ultimatevocalremovergui) to separate vocals and background music" + }, + { + "author": "AIFSH", + "title": "ComfyUI-IP_LAP", + "id": "iplap", + "reference": "https://github.com/AIFSH/ComfyUI-IP_LAP", + "files": [ + "https://github.com/AIFSH/ComfyUI-IP_LAP" + ], + "install_type": "git-clone", + "description": "Nodes:IP_LAP Node, Video Loader, PreView Video, Combine Audio Video. the comfyui custom node of [a/IP_LAP](https://github.com/Weizhi-Zhong/IP_LAP) to make audio driven videos!" + }, + { + "author": "AIFSH", + "title": "ComfyUI-GPT_SoVITS", + "id": "sovits", + "reference": "https://github.com/AIFSH/ComfyUI-GPT_SoVITS", + "files": [ + "https://github.com/AIFSH/ComfyUI-GPT_SoVITS" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/GPT-SoVITS](https://github.com/RVC-Boss/GPT-SoVITS)! you can voice cloning and tts in comfyui now\n[w/NOTE:make sure ffmpeg is worked in your commandline]" + }, + { + "author": "AIFSH", + "title": "ComfyUI-MuseTalk_FSH", + "id": "musetalk-fsh", + "reference": "https://github.com/AIFSH/ComfyUI-MuseTalk_FSH", + "files": [ + "https://github.com/AIFSH/ComfyUI-MuseTalk_FSH" + ], + "install_type": "git-clone", + "description": "the comfyui custom node of [a/MuseTalk](https://github.com/TMElyralab/MuseTalk) to make audio driven videos!" + }, + { + "author": "AIFSH", + "title": "ComfyUI-WhisperX", + "id": "whisperx", + "reference": "https://github.com/AIFSH/ComfyUI-WhisperX", + "files": [ + "https://github.com/AIFSH/ComfyUI-WhisperX" + ], + "install_type": "git-clone", + "description": "a comfyui cuatom node for audio subtitling based on [a/whisperX](https://github.com/m-bain/whisperX.git) and [a/translators](https://github.com/UlionTse/translators)" + }, + { + "author": "AIFSH", + "title": "ComfyUI-RVC", + "id": "aifsh-rvc", + "reference": "https://github.com/AIFSH/ComfyUI-RVC", + "files": [ + "https://github.com/AIFSH/ComfyUI-RVC" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/Retrieval-based-Voice-Conversion-WebUI](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git), you can Voice-Conversion in comfyui now!\nNOTE: make sure ffmpeg is worked in your commandline for Linux" + }, + { + "author": "AIFSH", + "title": "ComfyUI-XTTS", + "id": "xtts", + "reference": "https://github.com/AIFSH/ComfyUI-XTTS", + "files": [ + "https://github.com/AIFSH/ComfyUI-XTTS" + ], + "install_type": "git-clone", + "description": "a custom comfyui node for [a/coqui-ai/TTS](https://github.com/coqui-ai/TTS.git)'s xtts module! support 17 languages voice cloning and tts" + }, + { + "author": "AIFSH", + "title": "ComfyUI-Live2DViewer", + "id": "live2dviewer", + "reference": "https://github.com/AIFSH/ComfyUI-Live2DViewer", + "files": [ + "https://github.com/AIFSH/ComfyUI-Live2DViewer" + ], + "install_type": "git-clone", + "description": "a comfyui node for viewing Live2D model" + }, + { + "author": "AIFSH", + "title": "ComfyUI-FishSpeech", + "id": "fishspeech", + "reference": "https://github.com/AIFSH/ComfyUI-FishSpeech", + "files": [ + "https://github.com/AIFSH/ComfyUI-FishSpeech" + ], + "install_type": "git-clone", + "description": "a custom comfyui node for [a/fish-speech](https://github.com/fishaudio/fish-speech.git)" + }, + { + "author": "AIFSH", + "title": "ComfyUI_V-Express", + "id": "v-express-aifsh", + "reference": "https://github.com/AIFSH/ComfyUI_V-Express", + "files": [ + "https://github.com/AIFSH/ComfyUI_V-Express" + ], + "install_type": "git-clone", + "description": "the comfyui custom node of [a/V-Express](https://github.com/tencent-ailab/V-Express) to make audio driven videos!" + }, + { + "author": "AIFSH", + "title": "ComfyUI-MimicBrush", + "id": "mimicbrush", + "reference": "https://github.com/AIFSH/ComfyUI-MimicBrush", + "files": [ + "https://github.com/AIFSH/ComfyUI-MimicBrush" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/MimicBrush](https://github.com/ali-vilab/MimicBrush),then inpainting with reference image." + }, + { + "author": "AIFSH", + "title": "ComfyUI-Hallo", + "id": "hallo", + "reference": "https://github.com/AIFSH/ComfyUI-Hallo", + "files": [ + "https://github.com/AIFSH/ComfyUI-Hallo" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/hallo](https://github.com/fudan-generative-vision/hallo)" + }, + { + "author": "AIFSH", + "title": "ComfyUI-UniAnimate", + "id": "unianimate", + "reference": "https://github.com/AIFSH/ComfyUI-UniAnimate", + "files": [ + "https://github.com/AIFSH/ComfyUI-UniAnimate" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/UniAnimate](https://github.com/ali-vilab/UniAnimate)" + }, + { + "author": "AIFSH", + "title": "ComfyUI-3d-photo-inpainting", + "id": "3d-photo-inpainting", + "reference": "https://github.com/AIFSH/ComfyUI-3d-photo-inpainting", + "files": [ + "https://github.com/AIFSH/ComfyUI-3d-photo-inpainting" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/3d-photo-inpainting](https://github.com/vt-vl-lab/3d-photo-inpainting),then you can render one image to zoom-in/dolly zoom/swing motion/circle motion video" + }, + { + "author": "AIFSH", + "title": "AIFSH/ComfyUI-AuraSR", + "id": "aurasr-aifsh", + "reference": "https://github.com/AIFSH/ComfyUI-AuraSR", + "files": [ + "https://github.com/AIFSH/ComfyUI-AuraSR" + ], + "install_type": "git-clone", + "description": "a node for [a/AuraSR](https://github.com/fal-ai/aura-sr)" + }, + { + "author": "AIFSH", + "title": "ComfyUI-MARS5-TTS", + "id": "mars5-tts", + "reference": "https://github.com/AIFSH/ComfyUI-MARS5-TTS", + "files": [ + "https://github.com/AIFSH/ComfyUI-MARS5-TTS" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/MARS5-TTS](https://github.com/Camb-ai/MARS5-TTS)" + }, + { + "author": "AIFSH", + "title": "ComfyUI-I2V-Adapter", + "id": "i2v-adapter", + "reference": "https://github.com/AIFSH/ComfyUI-I2V-Adapter", + "files": [ + "https://github.com/AIFSH/ComfyUI-I2V-Adapter" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/I2V-Adapter](https://github.com/KwaiVGI/I2V-Adapter)" + }, + { + "author": "AIFSH", + "title": "ComfyUI-MimicMotion", + "id": "mimicmotion-aifsh", + "reference": "https://github.com/AIFSH/ComfyUI-MimicMotion", + "files": [ + "https://github.com/AIFSH/ComfyUI-MimicMotion" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/MimicMotion](https://github.com/Tencent/MimicMotion)" + }, + { + "author": "AIFSH", + "title": "ComfyUI-DiffSynth-Studio", + "id": "diffsynth-studio", + "reference": "https://github.com/AIFSH/ComfyUI-DiffSynth-Studio", + "files": [ + "https://github.com/AIFSH/ComfyUI-DiffSynth-Studio" + ], + "install_type": "git-clone", + "description": "make [a/DiffSynth-Studio](https://github.com/modelscope/DiffSynth-Studio) available in ComfyUI" + }, + { + "author": "Koishi-Star", + "title": "Euler-Smea-Dyn-Sampler", + "id": "smea", + "reference": "https://github.com/Koishi-Star/Euler-Smea-Dyn-Sampler", + "files": [ + "https://github.com/Koishi-Star/Euler-Smea-Dyn-Sampler" + ], + "install_type": "git-clone", + "description": "СomfyUI version of [a/Euler Smea Dyn Sampler](https://github.com/Koishi-Star/Euler-Smea-Dyn-Sampler). It adds samplers directly to KSampler nodes." + }, + { + "author": "sdfxai", + "title": "SDFXBridgeForComfyUI - ComfyUI Custom Node for SDFX Integration", + "id": "sdfx", + "reference": "https://github.com/sdfxai/SDFXBridgeForComfyUI", + "files": [ + "https://github.com/sdfxai/SDFXBridgeForComfyUI" + ], + "install_type": "git-clone", + "description": "SDFXBridgeForComfyUI is a custom node designed for seamless integration between ComfyUI and SDFX. This custom node allows users to make ComfyUI compatible with SDFX when running the ComfyUI instance on their local machines." + }, + { + "author": "smthemex", + "title": "ComfyUI_ChatGLM_API", + "id": "chatglm-api", + "reference": "https://github.com/smthemex/ComfyUI_ChatGLM_API", + "files": [ + "https://github.com/smthemex/ComfyUI_ChatGLM_API" + ], + "install_type": "git-clone", + "description": "You can call Chatglm's API in comfyUI to translate and describe pictures, and the API similar to OpenAI." + }, + { + "author": "smthemex", + "title": "ComfyUI_StableAudio_Open", + "id": "stable-audio-open-1.0", + "reference": "https://github.com/smthemex/ComfyUI_StableAudio_Open", + "files": [ + "https://github.com/smthemex/ComfyUI_StableAudio_Open" + ], + "install_type": "git-clone", + "description": "You can use stable-audio-open-1.0 in comfyUI" + }, + { + "author": "smthemex", + "title": "ComfyUI_AnyDoor", + "id": "ComfyUI_AnyDoor", + "reference": "https://github.com/smthemex/ComfyUI_AnyDoor", + "files": [ + "https://github.com/smthemex/ComfyUI_AnyDoor" + ], + "install_type": "git-clone", + "description": "You can use anydoor, change clothes or object..." + }, + { + "author": "smthemex", + "title": "ComfyUI_HiDiffusion_Pro", + "id": "hidiffusion-pro", + "reference": "https://github.com/smthemex/ComfyUI_HiDiffusion_Pro", + "files": [ + "https://github.com/smthemex/ComfyUI_HiDiffusion_Pro" + ], + "install_type": "git-clone", + "description": "A HiDiffusion node for ComfyUI." + }, + { + "author": "smthemex", + "title": "ComfyUI_StoryDiffusion", + "id": "StoryDiffusion", + "reference": "https://github.com/smthemex/ComfyUI_StoryDiffusion", + "files": [ + "https://github.com/smthemex/ComfyUI_StoryDiffusion" + ], + "install_type": "git-clone", + "description": "A StoryDiffusion node for ComfyUI." + }, + { + "author": "smthemex", + "title": "ComfyUI_MS_Diffusion", + "id": "MS_Diffusion", + "reference": "https://github.com/smthemex/ComfyUI_MS_Diffusion", + "files": [ + "https://github.com/smthemex/ComfyUI_MS_Diffusion" + ], + "install_type": "git-clone", + "description": "You can using MS-diffusion make story in comfyUI." + }, + { + "author": "smthemex", + "title": "ComfyUI_Pic2Story", + "id": "pic2story", + "reference": "https://github.com/smthemex/ComfyUI_Pic2Story", + "files": [ + "https://github.com/smthemex/ComfyUI_Pic2Story" + ], + "install_type": "git-clone", + "description": "ComfyUI simple node based on BLIP method, with the function of Image to Txt." + }, + { + "author": "smthemex", + "title": "ComfyUI_Llama3_8B", + "id": "llama3-8b", + "reference": "https://github.com/smthemex/ComfyUI_Llama3_8B", + "files": [ + "https://github.com/smthemex/ComfyUI_Llama3_8B" + ], + "install_type": "git-clone", + "description": "Llama3_8B for comfyUI, using pipeline workflow." + }, + { + "author": "smthemex", + "title": "ComfyUI_ParlerTTS", + "id": "parlertts", + "reference": "https://github.com/smthemex/ComfyUI_ParlerTTS", + "files": [ + "https://github.com/smthemex/ComfyUI_ParlerTTS" + ], + "install_type": "git-clone", + "description": "You can call the ParlerTTS tool in comfyUI, which currently only supports English." + }, + { + "author": "smthemex", + "title": "ComfyUI_Pipeline_Tool", + "id": "pipeline-tool", + "reference": "https://github.com/smthemex/ComfyUI_Pipeline_Tool", + "files": [ + "https://github.com/smthemex/ComfyUI_Pipeline_Tool" + ], + "install_type": "git-clone", + "description": "A tool for novice users in Chinese Mainland to call the huggingface hub and download the huggingface models." + }, + { + "author": "smthemex", + "title": "ComfyUI_ID_Animator", + "id": "id-animator", + "reference": "https://github.com/smthemex/ComfyUI_ID_Animator", + "files": [ + "https://github.com/smthemex/ComfyUI_ID_Animator" + ], + "install_type": "git-clone", + "description": "This node allows you to use ID_Animator, the zero shot video generation model" + }, + { + "author": "smthemex", + "title": "ComfyUI_CustomNet", + "id": "customnet", + "reference": "https://github.com/smthemex/ComfyUI_CustomNet", + "files": [ + "https://github.com/smthemex/ComfyUI_CustomNet" + ], + "install_type": "git-clone", + "description": "This node allows you to use customnet." + }, + { + "author": "smthemex", + "title": "ComfyUI_Pops", + "id": "pops", + "reference": "https://github.com/smthemex/ComfyUI_Pops", + "files": [ + "https://github.com/smthemex/ComfyUI_Pops" + ], + "install_type": "git-clone", + "description": "You can use [a/Popspaper](https://popspaper.github.io/pOps/) method in comfyUI" + }, + { + "author": "smthemex", + "title": "ComfyUI_Streamv2v_Plus", + "id": "streamv2v", + "reference": "https://github.com/smthemex/ComfyUI_Streamv2v_Plus", + "files": [ + "https://github.com/smthemex/ComfyUI_Streamv2v_Plus" + ], + "install_type": "git-clone", + "description": "[a/StreamV2V](https://github.com/Jeff-LiangF/streamv2v) for ComfyUI" + }, + { + "author": "choey", + "title": "Comfy-Topaz", + "id": "topaz", + "reference": "https://github.com/choey/Comfy-Topaz", + "files": [ + "https://github.com/choey/Comfy-Topaz" + ], + "install_type": "git-clone", + "description": "Comfy-Topaz is a custom node for ComfyUI, which integrates with Topaz Photo AI to enhance (upscale, sharpen, denoise, etc.) images, allowing this traditionally asynchronous step to become a part of ComfyUI workflows.\nNOTE:Licensed installation of Topaz Photo AI" + }, + { + "author": "ALatentPlace", + "title": "ComfyUI_yanc", + "id": "yanc", + "reference": "https://github.com/ALatentPlace/ComfyUI_yanc", + "files": [ + "https://github.com/ALatentPlace/ComfyUI_yanc" + ], + "install_type": "git-clone", + "description": "Yet Another Node Collection. Adds some useful nodes, check out the GitHub page for more details." + }, + { + "author": "Wicloz", + "title": "ComfyUI Simply Nodes", + "reference": "https://github.com/Wicloz/ComfyUI-Simply-Nodes", + "files": [ + "https://github.com/Wicloz/ComfyUI-Simply-Nodes" + ], + "install_type": "git-clone", + "description": "Simple nodes to help clean up your workflow, mostly focussed on text operations." + }, + { + "author": "wandbrandon", + "title": "comfyui-pixel", + "id": "pixel", + "reference": "https://github.com/wandbrandon/comfyui-pixel", + "files": [ + "https://github.com/wandbrandon/comfyui-pixel" + ], + "install_type": "git-clone", + "description": "pixel art workshop nodes for comfyui." + }, + { + "author": "nullquant", + "title": "BrushNet", + "id": "brushnet", + "reference": "https://github.com/nullquant/ComfyUI-BrushNet", + "files": [ + "https://github.com/nullquant/ComfyUI-BrushNet" + ], + "install_type": "git-clone", + "description": "Custom nodes for ComfyUI allow to inpaint using Brushnet: '[a/BrushNet: A Plug-and-Play Image Inpainting Model with Decomposed Dual-Branch Diffusion](https://arxiv.org/abs/2403.06976)'." + }, + { + "author": "pamparamm", + "title": "Perturbed-Attention Guidance", + "id": "pag", + "reference": "https://github.com/pamparamm/sd-perturbed-attention", + "files": [ + "https://github.com/pamparamm/sd-perturbed-attention" + ], + "install_type": "git-clone", + "description": "Perturbed-Attention Guidance node for ComfyUI." + }, + { + "author": "pamparamm", + "title": "ComfyUI Vectorscope CC", + "id": "vectorscope", + "reference": "https://github.com/pamparamm/ComfyUI-vectorscope-cc", + "files": [ + "https://github.com/pamparamm/ComfyUI-vectorscope-cc" + ], + "install_type": "git-clone", + "description": "ComfyUI port of a wonderful extension [a/SD Webui Vectorscope CC by Haoming02](https://github.com/Haoming02/sd-webui-vectorscope-cc).\nBased on (and probably incompatible with) [a/ComfyUI Diffusion Color Grading by Haoming02](https://github.com/Haoming02/comfyui-diffusion-cg)." + }, + { + "author": "unwdef", + "title": "unwdef-nodes", + "reference": "https://github.com/unwdef/unwdef-nodes-comfyui", + "files": [ + "https://github.com/unwdef/unwdef-nodes-comfyui" + ], + "install_type": "git-clone", + "description": "Custom nodes for ComfyUI by unwdef." + }, + { + "author": "fevre27", + "title": "Self-Guidance nodes", + "id": "self-guidance", + "reference": "https://github.com/forever22777/comfyui-self-guidance", + "files": [ + "https://github.com/forever22777/comfyui-self-guidance" + ], + "install_type": "git-clone", + "description": "Unofficial ComfyUI implementation of Self-Guidance." + }, + { + "author": "aburahamu", + "title": "ComfyUI-RequestPoster", + "id": "request-poster", + "reference": "https://github.com/aburahamu/ComfyUI-RequestsPoster", + "files": [ + "https://github.com/aburahamu/ComfyUI-RequestsPoster" + ], + "install_type": "git-clone", + "description": "This extension can send HTTP Requests. You can request image generation to StableDiffusion3 and post images to X (Twitter) and Discord." + }, + { + "author": "aburahamu", + "title": "ComfyUI-IsNiceParts", + "id": "isniceparts", + "reference": "https://github.com/aburahamu/ComfyUI-IsNiceParts", + "files": [ + "https://github.com/aburahamu/ComfyUI-IsNiceParts" + ], + "install_type": "git-clone", + "description": "This custom node detects body parts (currently only hands) from the received image and outputs the image if the skeleton can be estimated." + }, + { + "author": "Sorcerio", + "title": "MBM's Music Visualizer", + "reference": "https://github.com/Sorcerio/MBM-Music-Visualizer", + "files": [ + "https://github.com/Sorcerio/MBM-Music-Visualizer" + ], + "install_type": "git-clone", + "description": "An image generation based music visualizer integrated into comfyanonymous/ComfyUI as custom nodes." + }, + { + "author": "quadmoon", + "title": "quadmoon's ComfyUI nodes", + "reference": "https://github.com/traugdor/ComfyUI-quadMoons-nodes", + "files": [ + "https://github.com/traugdor/ComfyUI-quadMoons-nodes" + ], + "install_type": "git-clone", + "description": "These are just some nodes I wanted and couldn't find where anyone else had made them yet." + }, + { + "author": "quadme7macoon", + "title": "ComfyUI-ShadertoyGL", + "reference": "https://github.com/e7mac/ComfyUI-ShadertoyGL", + "files": [ + "https://github.com/e7mac/ComfyUI-ShadertoyGL" + ], + "install_type": "git-clone", + "description": "Nodes:Shadertoy, Shader, ColorChannelOffset." + }, + { + "author": "royceschultz", + "title": "ComfyUI-TranscriptionTools", + "id": "transcription-tools", + "reference": "https://github.com/royceschultz/ComfyUI-TranscriptionTools", + "files": [ + "https://github.com/royceschultz/ComfyUI-TranscriptionTools" + ], + "install_type": "git-clone", + "description": "Transcribe audio and video files in ComfyUI." + }, + { + "author": "kunieone", + "title": "ComfyUI_alkaid", + "id": "alkadi", + "reference": "https://github.com/kunieone/ComfyUI_alkaid", + "files": [ + "https://github.com/kunieone/ComfyUI_alkaid" + ], + "install_type": "git-clone", + "description": "Nodes:A_Face3DSwapper, A_FaceCrop, A_FacePaste, A_OpenPosePreprocessor, A_EmptyLatentImageLongside, A_GetImageSize, AlkaidLoader, AdapterFaceLoader, AdapterStyleLoader, ..." + }, + { + "author": "txt2any", + "title": "ComfyUI-PromptOrganizer", + "id": "prompt-organizer", + "reference": "https://github.com/txt2any/ComfyUI-PromptOrganizer", + "files": [ + "https://github.com/txt2any/ComfyUI-PromptOrganizer" + ], + "install_type": "git-clone", + "description": "This is a custom node for ComfyUI that automatically saves your AI-generated images specifically to [a/www.txt2any.com](http://www.txt2any.com/)." + }, + { + "author": "kealiu", + "title": "ComfyUI Load and Save file to S3", + "id": "savefile-to-s3", + "reference": "https://github.com/kealiu/ComfyUI-S3-Tools", + "files": [ + "https://github.com/kealiu/ComfyUI-S3-Tools" + ], + "install_type": "git-clone", + "description": "Nodes:Load From S3, Save To S3." + }, + { + "author": "kealiu", + "title": "ComfyUI-ZeroShot-MTrans", + "id": "zeroshot-mtrans", + "reference": "https://github.com/kealiu/ComfyUI-ZeroShot-MTrans", + "files": [ + "https://github.com/kealiu/ComfyUI-ZeroShot-MTrans" + ], + "install_type": "git-clone", + "description": "An unofficial ComfyUI custom node for [a/Zero-Shot Material Transfer from a Single Image](https://ttchengab.github.io/zest), Given an input image (e.g., a photo of an apple) and a single material exemplar image (e.g., a golden bowl), ZeST can transfer the gold material from the exemplar onto the apple with accurate lighting cues while making everything else consistent." + }, + { + "author": "kealiu", + "title": "ComfyUI-Zero123-Porting", + "id": "zero123-porting", + "reference": "https://github.com/kealiu/ComfyUI-Zero123-Porting", + "files": [ + "https://github.com/kealiu/ComfyUI-Zero123-Porting" + ], + "install_type": "git-clone", + "description": "Zero-1-to-3: Zero-shot One Image to 3D Object, unofficial porting of original [Zero123](https://github.com/cvlab-columbia/zero123)" + }, + { + "author": "TashaSkyUp", + "title": "ComfyUI_LiteLLM", + "id": "litellm", + "reference": "https://github.com/Hopping-Mad-Games/ComfyUI_LiteLLM", + "files": [ + "https://github.com/Hopping-Mad-Games/ComfyUI_LiteLLM" + ], + "install_type": "git-clone", + "description": "Nodes for interfacing with LiteLLM" + }, + { + "author": "AonekoSS", + "title": "ComfyUI-SimpleCounter", + "id": "simplecounter", + "reference": "https://github.com/AonekoSS/ComfyUI-SimpleCounter", + "files": [ + "https://github.com/AonekoSS/ComfyUI-SimpleCounter" + ], + "install_type": "git-clone", + "description": "Node: utils/Simple Counter\nThis node is a simple counter, when pressing 'Queue Prompt' resets the count." + }, + { + "author": "AonekoSS", + "title": "ComfyUI-LoRA-Tuner", + "id": "lora-tuner", + "reference": "https://github.com/AonekoSS/ComfyUI-LoRA-Tuner", + "files": [ + "https://github.com/AonekoSS/ComfyUI-LoRA-Tuner" + ], + "install_type": "git-clone", + "description": "Nodes: LoRA-Tuner. For using multiple LoRA easily." + }, + { + "author": "heshengtao", + "title": "comfyui_LLM_party", + "id": "llm-party", + "reference": "https://github.com/heshengtao/comfyui_LLM_party", + "files": [ + "https://github.com/heshengtao/comfyui_LLM_party" + ], + "install_type": "git-clone", + "description": "A set of block-based LLM agent node libraries designed for ComfyUI.This project aims to develop a complete set of nodes for LLM workflow construction based on comfyui. It allows users to quickly and conveniently build their own LLM workflows and easily integrate them into their existing SD workflows." + }, + { + "author": "VAST-AI-Research", + "title": "Tripo for ComfyUI", + "id": "tripo", + "reference": "https://github.com/VAST-AI-Research/ComfyUI-Tripo", + "files": [ + "https://github.com/VAST-AI-Research/ComfyUI-Tripo" + ], + "install_type": "git-clone", + "description": "Custom nodes for using [a/Tripo](https://www.tripo3d.ai/) in ComfyUI to create 3D from text and image prompts." + }, + { + "author": "JettHu", + "title": "ComfyUI_TGate", + "id": "tgate", + "reference": "https://github.com/JettHu/ComfyUI_TGate", + "files": [ + "https://github.com/JettHu/ComfyUI_TGate" + ], + "install_type": "git-clone", + "description": "ComfyUI reference implementation for [a/T-GATE](https://github.com/HaozheLiu-ST/T-GATE)." + }, + { + "author": "JettHu", + "title": "ComfyUI-TCD", + "id": "jetthu-tcd", + "reference": "https://github.com/JettHu/ComfyUI-TCD", + "files": [ + "https://github.com/JettHu/ComfyUI-TCD" + ], + "install_type": "git-clone", + "description": "ComfyUI implementation for [a/TCD](https://github.com/jabir-zheng/TCD)." + }, + { + "author": "sugarkwork", + "title": "comfyui_tag_filter", + "id": "tag-filter", + "reference": "https://github.com/sugarkwork/comfyui_tag_fillter", + "files": [ + "https://github.com/sugarkwork/comfyui_tag_fillter" + ], + "install_type": "git-clone", + "description": "This is a custom node of ComfyUI that categorizes tags outputted by tools like WD14Tagger, filters them by each category, and returns the filtered results." + }, + { + "author": "Intersection98", + "title": "ComfyUI-MX-post-processing-nodes", + "reference": "https://github.com/Intersection98/ComfyUI_MX_post_processing-nodes", + "files": [ + "https://github.com/Intersection98/ComfyUI_MX_post_processing-nodes" + ], + "install_type": "git-clone", + "description": "A collection of post processing nodes for ComfyUI, dds image post-processing adjustment capabilities to the ComfyUI." + }, + { + "author": "TencentQQGYLab", + "title": "ComfyUI-ELLA", + "id": "ella", + "reference": "https://github.com/TencentQQGYLab/ComfyUI-ELLA", + "files": [ + "https://github.com/TencentQQGYLab/ComfyUI-ELLA" + ], + "install_type": "git-clone", + "description": "ComfyUI implementation for [a/ELLA](https://github.com/TencentQQGYLab/ELLA)." + }, + { + "author": "DarKDinDoN", + "title": "ComfyUI Checkpoint Automatic Config", + "id": "checkpoint-autoconfig", + "reference": "https://github.com/DarKDinDoN/comfyui-checkpoint-automatic-config", + "files": [ + "https://github.com/DarKDinDoN/comfyui-checkpoint-automatic-config" + ], + "install_type": "git-clone", + "description": "This node was designed to help with checkpoint configuration." + }, + { + "author": "MinusZoneAI", + "title": "ComfyUI-Prompt-MZ", + "id": "prompt-mz", + "reference": "https://github.com/MinusZoneAI/ComfyUI-Prompt-MZ", + "files": [ + "https://github.com/MinusZoneAI/ComfyUI-Prompt-MZ" + ], + "install_type": "git-clone", + "description": "Use llama.cpp to help generate some nodes for prompt word related work" + }, + { + "author": "MinusZoneAI", + "title": "ComfyUI-StylizePhoto-MZ", + "id": "stylizephoto", + "reference": "https://github.com/MinusZoneAI/ComfyUI-StylizePhoto-MZ", + "files": [ + "https://github.com/MinusZoneAI/ComfyUI-StylizePhoto-MZ" + ], + "install_type": "git-clone", + "description": "A stylized node with simple operation. The effect is achieved by I2I and lora. The clay style is currently implemented.Comes with watermark function." + }, + { + "author": "MinusZoneAI", + "title": "ComfyUI-TrainTools-MZ", + "id": "traintools", + "reference": "https://github.com/MinusZoneAI/ComfyUI-TrainTools-MZ", + "files": [ + "https://github.com/MinusZoneAI/ComfyUI-TrainTools-MZ" + ], + "install_type": "git-clone", + "description": "Nodes for fine-tuning lora in ComfyUI, dependent on training tools such as kohya-ss/sd-scripts" + }, + { + "author": "blueraincoatli", + "title": "comfyUI_SillyNodes", + "id": "silly", + "reference": "https://github.com/blueraincoatli/comfyUI_SillyNodes", + "files": [ + "https://github.com/blueraincoatli/comfyUI_SillyNodes" + ], + "install_type": "git-clone", + "description": "Using rgthree's fast_group_muter and bookmark nodes, introduce the pyautogui library to simulate clicks and hotkeys, and run groups in sequence. screen manipulation is involved" + }, + { + "author": "ty0x2333", + "title": "ComfyUI-Dev-Utils", + "id": "dev-utils", + "reference": "https://github.com/ty0x2333/ComfyUI-Dev-Utils", + "files": [ + "https://github.com/ty0x2333/ComfyUI-Dev-Utils" + ], + "install_type": "git-clone", + "description": "Execution Time Analysis, Reroute Enhancement, Node collection for developers." + }, + { + "author": "lquesada", + "title": "ComfyUI-Prompt-Combinator", + "id": "prompt-combinator", + "reference": "https://github.com/lquesada/ComfyUI-Prompt-Combinator", + "files": [ + "https://github.com/lquesada/ComfyUI-Prompt-Combinator" + ], + "install_type": "git-clone", + "description": "'🔢 Prompt Combinator' is a node that generates all possible combinations of prompts from several lists of strings.\n'🔢 Prompt Combinator Merger' is a node that enables merging the output of two different '🔢 Prompt Combinator' nodes." + }, + { + "author": "lquesada", + "title": "ComfyUI-Inpaint-CropAndStitch", + "id": "crop-and-stitch", + "reference": "https://github.com/lquesada/ComfyUI-Inpaint-CropAndStitch", + "files": [ + "https://github.com/lquesada/ComfyUI-Inpaint-CropAndStitch" + ], + "install_type": "git-clone", + "description": "'✂️ Inpaint Crop' is a node that crops an image before sampling. The context area can be specified via the mask, expand pixels and expand factor or via a separate (optional) mask.\n'✂️ Inpaint Stitch' is a node that stitches the inpainted image back into the original image without altering unmasked areas." + }, + { + "author": "randjtw", + "title": "advance-aesthetic-score", + "reference": "https://github.com/randjtw/advance-aesthetic-score", + "files": [ + "https://github.com/randjtw/advance-aesthetic-score" + ], + "install_type": "git-clone", + "description": "Nodes:Advance Aesthetic Score" + }, + { + "author": "FredBill1", + "title": "comfyui-fb-utils", + "id": "fb-utils", + "reference": "https://github.com/FredBill1/comfyui-fb-utils", + "files": [ + "https://github.com/FredBill1/comfyui-fb-utils" + ], + "install_type": "git-clone", + "description": "Nodes:FBStringJoin, FBStringSplit, FBMultilineStringList, FBMultilineString" + }, + { + "author": "jeffy5", + "title": "Faceless Node for ComfyUI", + "id": "faceless", + "reference": "https://github.com/jeffy5/comfyui-faceless-node", + "files": [ + "https://github.com/jeffy5/comfyui-faceless-node" + ], + "install_type": "git-clone", + "description": "Nodes:Load Video, Load Frames, Save Video, Face Swap, Face Restore, Face Swap (Video), Face Restore (Video)" + }, + { + "author": "TaiTair", + "title": "Simswap Node for ComfyUI", + "id": "simswap", + "reference": "https://github.com/TaiTair/comfyui-simswap", + "files": [ + "https://github.com/TaiTair/comfyui-simswap" + ], + "install_type": "git-clone", + "description": "A hacky implementation of Simswap based on [a/Comfyui ReActor Node 0.5.1](https://github.com/Gourieff/comfyui-reactor-node) and [a/Simswap](https://github.com/neuralchen/SimSwap)." + }, + { + "author": "fofr", + "title": "ComfyUI-HyperSDXL1StepUnetScheduler (ByteDance)", + "id": "hypersdxl", + "reference": "https://github.com/fofr/ComfyUI-HyperSDXL1StepUnetScheduler", + "files": [ + "https://github.com/fofr/ComfyUI-HyperSDXL1StepUnetScheduler" + ], + "install_type": "git-clone", + "description": "Original author is ByteDance.\nComfyUI sampler for HyperSDXL UNet\nPorted from: [a/https://huggingface.co/ByteDance/Hyper-SD](https://huggingface.co/ByteDance/Hyper-SD)" + }, + { + "author": "fofr", + "title": "ComfyUI-Prompter-fofrAI", + "id": "prompter-fofr", + "reference": "https://github.com/fofr/ComfyUI-Prompter-fofrAI", + "files": [ + "https://github.com/fofr/ComfyUI-Prompter-fofrAI" + ], + "install_type": "git-clone", + "description": "A prompt helper. Use templates from [a/https://prompter.fofr.ai](https://prompter.fofr.ai) in ComfyUI." + }, + { + "author": "fofr", + "title": "comfyui-replicate", + "reference": "https://github.com/fofr/comfyui-replicate", + "files": [ + "https://github.com/fofr/comfyui-replicate" + ], + "install_type": "git-clone", + "description": "Run [a/Replicate models](https://replicate.com/explore) in ComfyUI." + }, + { + "author": "cfreilich", + "title": "Virtuoso Nodes for ComfyUI", + "id": "virtuoso", + "reference": "https://github.com/chrisfreilich/virtuoso-nodes", + "files": [ + "https://github.com/chrisfreilich/virtuoso-nodes" + ], + "install_type": "git-clone", + "description": "Photoshop type functions and adjustment layers: 30 blend modes, Selective Color, Blend If, Color Balance, Solid Color Images, Black and White, Hue/Saturation, Levels, and RGB Splitting and Merging." + }, + { + "author": "da2el-ai", + "title": "D2 Steps", + "id": "d2steps", + "reference": "https://github.com/da2el-ai/ComfyUI-d2-steps", + "files": [ + "https://github.com/da2el-ai/ComfyUI-d2-steps" + ], + "install_type": "git-clone", + "description": "A handy custom node for using Refiner (switching to a different checkpoint midway) When you specify the end of the base checkpoint, you can extract refiner_start which is end + 1. The output is fixed as an INT, so it can be passed to the handy custom node, Anything Everywhere? Since it only outputs a numerical value, it can also be used for other purposes." + }, + { + "author": "da2el-ai", + "title": "D2 Size Selector", + "id": "size-selector", + "reference": "https://github.com/da2el-ai/ComfyUI-d2-size-selector", + "files": [ + "https://github.com/da2el-ai/ComfyUI-d2-size-selector" + ], + "install_type": "git-clone", + "description": "This is a custom node that allows you to easily call up and set image size presets. Settings can be made by editing the included config.yaml. It is almost identical to Comfyroll Studio's CR AspectRatio. I created it because I wanted to easily edit the presets." + }, + { + "author": "nat-chan", + "title": "ComfyUI-Transceiver📡", + "id": "transceiver", + "reference": "https://github.com/nat-chan/comfyui-transceiver", + "files": [ + "https://github.com/nat-chan/comfyui-transceiver" + ], + "install_type": "git-clone", + "description": "Transceiver is a python library that swiftly exchanges fundamental data structures, specifically numpy arrays, between processes, optimizing AI inference tasks that utilize ComfyUI." + }, + { + "author": "nat-chan", + "title": "ComfyUI-graphToPrompt", + "id": "graph2prompt", + "reference": "https://github.com/nat-chan/ComfyUI-graphToPrompt", + "files": [ + "https://github.com/nat-chan/ComfyUI-graphToPrompt" + ], + "install_type": "git-clone", + "description": "workflow.json -> workflow_api.json" + }, + { + "author": "web3nomad", + "title": "ComfyUI Invisible Watermark", + "id": "invisible-watermark", + "reference": "https://github.com/web3nomad/ComfyUI_Invisible_Watermark", + "files": [ + "https://github.com/web3nomad/ComfyUI_Invisible_Watermark" + ], + "install_type": "git-clone", + "description": "Nodes: InvisibleWatermarkEncode" + }, + { + "author": "GentlemanHu", + "title": "ComfyUI Suno API", + "id": "suno-api", + "reference": "https://github.com/GentlemanHu/ComfyUI-SunoAI", + "files": [ + "https://github.com/GentlemanHu/ComfyUI-SunoAI" + ], + "install_type": "git-clone", + "description": "An unofficial Python library for [a/Suno AI](https://www.suno.ai/) API" + }, + { + "author": "TemryL", + "title": "ComfyUI-IDM-VTON [WIP]", + "id": "idm-vton", + "reference": "https://github.com/TemryL/ComfyUI-IDM-VTON", + "files": [ + "https://github.com/TemryL/ComfyUI-IDM-VTON" + ], + "install_type": "git-clone", + "description": "ComfyUI adaptation of [a/IDM-VTON](https://github.com/yisol/IDM-VTON) for virtual try-on." + }, + { + "author": "NStor", + "title": "ComfyUI-RUS localization", + "reference": "https://github.com/Nestorchik/NStor-ComfyUI-Translation", + "files": [ + "https://github.com/Nestorchik/NStor-ComfyUI-Translation" + ], + "install_type": "git-clone", + "description": "Russian localization of ComfyUI, ComafyUI-Manager & more..." + }, + { + "author": "jax-explorer", + "title": "fast_video_comfyui", + "reference": "https://github.com/jax-explorer/fast_video_comfyui", + "files": [ + "https://github.com/jax-explorer/fast_video_comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:FastImageListToImageBatch" + }, + { + "author": "sugarkwork", + "title": "comfyui_cohere", + "id": "cohere", + "reference": "https://github.com/sugarkwork/comfyui_cohere", + "files": [ + "https://github.com/sugarkwork/comfyui_cohere" + ], + "install_type": "git-clone", + "description": "This is a node for using cohere (Command R+) from ComfyUI. You need to edit the startup .bat file of ComfyUI and describe the API key obtained from Cohere as follows." + }, + { + "author": "alessandrozonta", + "title": "Bounding Box Crop Node for ComfyUI", + "id": "bbox-crop", + "reference": "https://github.com/alessandrozonta/ComfyUI-CenterNode", + "files": [ + "https://github.com/alessandrozonta/ComfyUI-CenterNode" + ], + "install_type": "git-clone", + "description": "This extension contains a custom node for ComfyUI. The node, called 'Bounding Box Crop', is designed to compute the top-left coordinates of a cropped bounding box based on input coordinates and dimensions of the final cropped image. It does so computing the center of the cropping area and then computing where the top-left coordinates would be." + }, + { + "author": "alessandrozonta", + "title": "Save Layers Node for ComfyUI", + "id": "layers", + "reference": "https://github.com/alessandrozonta/ComfyUI-Layers", + "files": [ + "https://github.com/alessandrozonta/ComfyUI-Layers" + ], + "install_type": "git-clone", + "description": "This custom node for ComfyUI allows you to create layers of an image based on input masks and save them into a PSD file." + }, + { + "author": "alessandrozonta", + "title": "OpenPose Node", + "id": "openpose-alessandrozonta", + "reference": "https://github.com/alessandrozonta/ComfyUI-OpenPose", + "files": [ + "https://github.com/alessandrozonta/ComfyUI-OpenPose" + ], + "install_type": "git-clone", + "description": "This extension contains a custom node for ComfyUI. The node, called 'Bounding Box Crop', is designed to compute the top-left coordinates of a cropped bounding box based on input coordinates and dimensions of the final cropped image. It does so computing the center of the cropping area and then computing where the top-left coordinates would be." + }, + { + "author": "curiousjp", + "title": "ComfyUI-MaskBatchPermutations", + "id": "maskbatch-permutations", + "reference": "https://github.com/curiousjp/ComfyUI-MaskBatchPermutations", + "files": [ + "https://github.com/curiousjp/ComfyUI-MaskBatchPermutations" + ], + "install_type": "git-clone", + "description": "Permutes a mask batch to present possible additive combinations. Passing a mask batch (e.g. out of [a/SEGS to Mask Batch](https://github.com/ltdrdata/ComfyUI-Impact-Pack)) will return a new mask batch representing all the possible combinations of the included masks. So, a mask batch with two mask sections, 'A' and 'B', will return a batch containing an empty mask, an empty mask & A, an empty mask & B, and an empty mask & A & B." + }, + { + "author": "BAIS1C", + "title": "ComfyUI_RSS_Feed_Reader", + "id": "rssfeed", + "reference": "https://github.com/BAIS1C/ComfyUI_RSS_Feed_Reader", + "files": [ + "https://github.com/BAIS1C/ComfyUI_RSS_Feed_Reader" + ], + "install_type": "git-clone", + "description": "A Simple Python RSS Feed Reader to create Prompts in Comfy UI" + }, + { + "author": "runtime44", + "title": "Runtime44 ComfyUI Nodes", + "reference": "https://github.com/runtime44/comfyui_r44_nodes", + "files": [ + "https://github.com/runtime44/comfyui_r44_nodes" + ], + "install_type": "git-clone", + "description": "Nodes: Runtime44Upscaler, Runtime44ColorMatch, Runtime44DynamicKSampler, Runtime44ImageOverlay, Runtime44ImageResizer, Runtime44ImageToNoise, Runtime44MaskSampler, Runtime44TiledMaskSampler, Runtime44IterativeUpscaleFactor, Runtime44ImageEnhance, Runtime44FilmGrain" + }, + { + "author": "osiworx", + "title": "ComfyUI_Prompt-Quill", + "reference": "https://github.com/osi1880vr/prompt_quill_comfyui", + "files": [ + "https://github.com/osi1880vr/prompt_quill_comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:Use Prompt Quill in Comfyui" + }, + { + "author": "philz1337x", + "title": "✨ Clarity AI - Creative Image Upscaler and Enhancer for ComfyUI", + "reference": "https://github.com/philz1337x/ComfyUI-ClarityAI", + "files": [ + "https://github.com/philz1337x/ComfyUI-ClarityAI" + ], + "install_type": "git-clone", + "description": "[a/Clarity AI](https://clarityai.cc) is a creative image enhancer and is able to upscale to high resolution. [w/NOTE: This is a Magnific AI alternative for ComfyUI.] \nCreate an API key on [a/ClarityAI.cc/api](https://clarityai.cc/api) and add to environment variable 'CAI_API_KEY'\nAlternatively you can write your API key to file 'cai_platform_key.txt'\nYou can also use and/or override the above by entering your API key in the 'api_key_override' field of the node." + }, + { + "author": "KoreTeknology", + "title": "ComfyUI Universal Styler", + "id": "universal-styler", + "reference": "https://github.com/KoreTeknology/ComfyUI-Universal-Styler", + "files": [ + "https://github.com/KoreTeknology/ComfyUI-Universal-Styler" + ], + "install_type": "git-clone", + "description": "A research Node based project on Artificial Intelligence using ComfyUI visual editor with Stable diffusion Local processing focus in mind. This custom node is intended to serve the purpose to offer a large palette of prompting scenrarios, based on Public Checkpoint Models OR/AND Private custom Models and LoRas. It includes an integrated learning machine process as well as a set of workflows." + }, + { + "author": "ZeDarkAdam", + "title": "ComfyUI-Embeddings-Tools", + "id": "embeddings-tools", + "reference": "https://github.com/ZeDarkAdam/ComfyUI-Embeddings-Tools", + "files": [ + "https://github.com/ZeDarkAdam/ComfyUI-Embeddings-Tools" + ], + "install_type": "git-clone", + "description": "EmbeddingsNameLoader, EmbendingList" + }, + { + "author": "chenpx976", + "title": "ComfyUI-RunRunRun", + "id": "runrunrun", + "reference": "https://github.com/chenpx976/ComfyUI-RunRunRun", + "files": [ + "https://github.com/chenpx976/ComfyUI-RunRunRun" + ], + "install_type": "git-clone", + "description": "add http api http://127.0.0.1:8188/comfyui-run/run use in other llm project." + }, + { + "author": "githubYiheng", + "title": "ComfyUI_GetFileNameFromURL", + "id": "getfilename-from-url", + "reference": "https://github.com/githubYiheng/ComfyUI_GetFileNameFromURL", + "files": [ + "https://github.com/githubYiheng/ComfyUI_GetFileNameFromURL" + ], + "install_type": "git-clone", + "description": "GetFileNameFromURL is a ComfyUI custom node that extracts the filename from a URL. It can handle various URLs and is capable of handling redirects." + }, + { + "author": "githubYiheng", + "title": "comfyui_kmeans_filter", + "id": "kmeans-filter", + "reference": "https://github.com/githubYiheng/comfyui_kmeans_filter", + "files": [ + "https://github.com/githubYiheng/comfyui_kmeans_filter" + ], + "install_type": "git-clone", + "description": "Nodes:Apply Kmeans Filter" + }, + { + "author": "githubYiheng", + "title": "ComfyUI_Change_IMAGE_BOREDER", + "id": "change-image-border", + "reference": "https://github.com/githubYiheng/ComfyUI_Change_IMAGE_BOREDER", + "files": [ + "https://github.com/githubYiheng/ComfyUI_Change_IMAGE_BOREDER" + ], + "install_type": "git-clone", + "description": "Nodes:Change Image Border" + }, + { + "author": "githubYiheng", + "title": "comfyui_meanshift_filter", + "id": "meanshift-filter", + "reference": "https://github.com/githubYiheng/comfyui_meanshift_filter", + "files": [ + "https://github.com/githubYiheng/comfyui_meanshift_filter" + ], + "install_type": "git-clone", + "description": "Nodes:Apply Meanshift Filter" + }, + { + "author": "githubYiheng", + "title": "comfyui_private_postprocessor", + "id": "githubyiheng-private-postprocessor", + "reference": "https://github.com/githubYiheng/comfyui_private_postprocessor", + "files": [ + "https://github.com/githubYiheng/comfyui_private_postprocessor" + ], + "install_type": "git-clone", + "description": "Nodes:Private ImageCPostprocessor" + }, + { + "author": "Fihade", + "title": "IC-Light-ComfyUI-Node", + "reference": "https://github.com/Fihade/IC-Light-ComfyUI-Node", + "files": [ + "https://github.com/Fihade/IC-Light-ComfyUI-Node" + ], + "install_type": "git-clone", + "description": "Original repo: [a/https://github.com/lllyasviel/IC-Light](https://github.com/lllyasviel/IC-Light)\nModels: [a/https://huggingface.co/lllyasviel/ic-light/tree/main](https://huggingface.co/lllyasviel/ic-light/tree/main), [a/https://huggingface.co/digiplay/Photon_v1/tree/main](https://huggingface.co/digiplay/Photon_v1/tree/main)\nmodels go into ComfyUI/models/unet" + }, + { + "author": "KewkLW", + "title": "ComfyUI-kewky_tools", + "id": "kewky-tools", + "reference": "https://github.com/KewkLW/ComfyUI-kewky_tools", + "files": [ + "https://github.com/KewkLW/ComfyUI-kewky_tools" + ], + "install_type": "git-clone", + "description": "text_append_node, vramdebugplus, tensordebugplus, animation_schedule_output" + }, + { + "author": "ITurchenko", + "title": "ComfyUI-SizeFromArray", + "id": "sizefromarray", + "reference": "https://github.com/ITurchenko/ComfyUI-SizeFromArray", + "files": [ + "https://github.com/ITurchenko/ComfyUI-SizeFromArray" + ], + "install_type": "git-clone", + "description": "Nodes:SizeFromArray" + }, + { + "author": "Suplex", + "title": "Suplex Misc ComfyUI Nodes", + "id": "suplex", + "reference": "https://github.com/saftle/suplex_comfy_nodes", + "files": [ + "https://github.com/saftle/suplex_comfy_nodes" + ], + "install_type": "git-clone", + "description": "Misc Nodes: ControlNet Selector Node, Load Optional ControlNet Model" + }, + { + "author": "mephisto83", + "title": "petty-paint-comfyui-node", + "id": "petty-paint", + "reference": "https://github.com/mephisto83/petty-paint-comfyui-node", + "files": [ + "https://github.com/mephisto83/petty-paint-comfyui-node" + ], + "install_type": "git-clone", + "description": "An integration between comfy ui and petty paint" + }, + { + "author": "fsdymy1024", + "title": "ComfyUI_fsdymy", + "id": "fsdymy", + "reference": "https://github.com/fsdymy1024/ComfyUI_fsdymy", + "files": [ + "https://github.com/fsdymy1024/ComfyUI_fsdymy" + ], + "install_type": "git-clone", + "description": "Nodes:Save Image Without Metadata" + }, + { + "author": "ray", + "title": "Light Gradient for ComfyUI", + "id": "light-gradient", + "reference": "https://github.com/huagetai/ComfyUI_LightGradient", + "files": [ + "https://github.com/huagetai/ComfyUI_LightGradient" + ], + "install_type": "git-clone", + "description": "Nodes:Image Gradient,Mask Gradient" + }, + { + "author": "ray", + "title": "comfyui's gaffer(ComfyUI native implementation of IC-Light. )", + "id": "gaffer", + "reference": "https://github.com/huagetai/ComfyUI-Gaffer", + "files": [ + "https://github.com/huagetai/ComfyUI-Gaffer" + ], + "install_type": "git-clone", + "description": "Nodes:Load ICLight Model,Apply ICLight,Simple Light Source,Calculate Normal Map" + }, + { + "author": "YFG", + "title": "😸 YFG Comical Nodes", + "id": "comical", + "reference": "https://github.com/gonzalu/ComfyUI_YFG_Comical", + "files": [ + "https://github.com/gonzalu/ComfyUI_YFG_Comical" + ], + "install_type": "git-clone", + "description": "Image Historgram Generator - Outputs a set of images displaying the Histogram of the input image. Nodes: img2histograms, img2histogramsSelf" + }, + { + "author": "ruiqutech", + "title": "RuiquNodes for ComfyUI", + "id": "RuiquNodes", + "reference": "https://github.com/ruiqutech/ComfyUI-RuiquNodes", + "files": [ + "https://github.com/ruiqutech/ComfyUI-RuiquNodes" + ], + "install_type": "git-clone", + "description": "Nodes of EvaluateMultiple1, EvaluateMultiple3...\nSupport the execution of any fragment of Python code, generating multiple outputs from multiple inputs." + }, + { + "author": "teward", + "title": "ComfyUI-Helper-Nodes", + "id": "helper-nodes", + "reference": "https://github.com/teward/ComfyUI-Helper-Nodes", + "files": [ + "https://github.com/teward/ComfyUI-Helper-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes: HelperNodes_MultilineStringLiteral, HelperNodes_StringLiteral, HelperNodes_Steps, HelperNodes_CfgScale, HelperNodes_WidthHeight, HelperNodes_SchedulerSelector, HelperNodes_SamplerSelector, ..." + }, + { + "author": "fmatray", + "title": "ComfyUI_BattlemapGrid", + "id": "battlemap-grid", + "reference": "https://github.com/fmatray/ComfyUI_BattlemapGrid", + "files": [ + "https://github.com/fmatray/ComfyUI_BattlemapGrid" + ], + "install_type": "git-clone", + "description": "Nodes for ComfyUI in order to generate battelmaps" + }, + { + "author": "christian-byrne", + "title": "img2txt-comfyui-nodes", + "id": "img2txt-nodes", + "reference": "https://github.com/christian-byrne/img2txt-comfyui-nodes", + "files": [ + "https://github.com/christian-byrne/img2txt-comfyui-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:img2txt BLIP/Llava Multimodel Tagger" + }, + { + "author": "christian-byrne", + "title": "img2colors-comfyui-node", + "id": "img2colors-nodes", + "reference": "https://github.com/christian-byrne/img2colors-comfyui-node", + "files": [ + "https://github.com/christian-byrne/img2colors-comfyui-node" + ], + "install_type": "git-clone", + "description": "Nodes:Img2Color - Color Palette Extractor" + }, + { + "author": "christian-byrne", + "title": "Node - Size Matcher", + "id": "sizematcher", + "reference": "https://github.com/christian-byrne/size-match-compositing-nodes", + "files": [ + "https://github.com/christian-byrne/size-match-compositing-nodes" + ], + "install_type": "git-clone", + "description": "Takes two images and matches their sizes using various methods, detailed below." + }, + { + "author": "christian-byrne", + "title": "comfyui-search-navigation", + "reference": "https://github.com/christian-byrne/comfyui-search-navigation", + "files": [ + "https://github.com/christian-byrne/comfyui-search-navigation" + ], + "install_type": "git-clone", + "description": "Search navigation extension." + }, + { + "author": "christian-byrne", + "title": "audio-separation-nodes-comfyui", + "reference": "https://github.com/christian-byrne/audio-separation-nodes-comfyui", + "files": [ + "https://github.com/christian-byrne/audio-separation-nodes-comfyui" + ], + "install_type": "git-clone", + "description": "Separate audio track into stems (vocals, bass, drums, other). Along with tools to recombine, tempo match, slice/crop audio." + }, + { + "author": "christian-byrne", + "title": "comfyui-default-values-manager", + "reference": "https://github.com/christian-byrne/comfyui-default-values-manager", + "files": [ + "https://github.com/christian-byrne/comfyui-default-values-manager" + ], + "install_type": "git-clone", + "description": "comfyui-default-values-manager" + }, + { + "author": "oztrkoguz", + "title": "ComfyUI StoryCreater", + "id": "storycreater", + "reference": "https://github.com/oztrkoguz/ComfyUI_StoryCreator", + "files": [ + "https://github.com/oztrkoguz/ComfyUI_StoryCreator" + ], + "install_type": "git-clone", + "description": "Nodes:story_sampler_simple, text2, kosmos2_sampler.\nI created a dataset for generating short stories [a/Short-Story](https://huggingface.co/datasets/oztrkoguz/Short-Story) and used it to fine-tune my own model using Phi-3." + }, + { + "author": "GraftingRayman", + "title": "GraftingRayman", + "id": "graftingrayman", + "reference": "https://github.com/GraftingRayman/ComfyUI_GraftingRayman", + "files": [ + "https://github.com/GraftingRayman/ComfyUI_GraftingRayman" + ], + "install_type": "git-clone", + "description": "Image Manipulation Nodes" + }, + { + "author": "royceschultz", + "title": "ComfyUI-Notifications", + "reference": "https://github.com/royceschultz/ComfyUI-Notifications", + "files": [ + "https://github.com/royceschultz/ComfyUI-Notifications" + ], + "install_type": "git-clone", + "description": "Send notifications when a workflow completes." + }, + { + "author": "katalist-ai", + "title": "comfyUI-nsfw-detection", + "id": "nsfw-detection", + "reference": "https://github.com/katalist-ai/comfyUI-nsfw-detection", + "files": [ + "https://github.com/katalist-ai/comfyUI-nsfw-detection" + ], + "install_type": "git-clone", + "description": "Nodes: NudenetDetector" + }, + { + "author": "kaanyalova", + "title": "Extended Image Formats for ComfyUI", + "id": "extended-image-format", + "reference": "https://github.com/kaanyalova/ComfyUI_ExtendedImageFormats", + "files": [ + "https://github.com/kaanyalova/ComfyUI_ExtendedImageFormats" + ], + "install_type": "git-clone", + "description": "Adds a custom node for saving images in webp, jpeg, avif, jxl (no metadata) and supports loading workflows from saved images" + }, + { + "author": "badayvedat", + "title": "ComfyUI-fal-Connector", + "id": "fal", + "reference": "https://github.com/badayvedat/ComfyUI-fal-Connector", + "files": [ + "https://github.com/badayvedat/ComfyUI-fal-Connector" + ], + "install_type": "git-clone", + "description": "The ComfyUI-fal-Connector is a tool designed to provide an integration between ComfyUI and fal. This extension allows users to execute their ComfyUI workflows directly on [a/fal.ai](https://fal.ai/). This enables users to leverage the computational power and resources provided by fal.ai for running their ComfyUI workflows." + }, + { + "author": "TheMistoAI", + "title": "Anyline", + "id": "anyline", + "reference": "https://github.com/TheMistoAI/ComfyUI-Anyline", + "files": [ + "https://github.com/TheMistoAI/ComfyUI-Anyline" + ], + "install_type": "git-clone", + "description": "A Fast, Accurate, and Detailed Line Detection Preprocessor.\nAnyline is a ControlNet line preprocessor that accurately extracts object edges, image details, and textual content from most images. Users can input any type of image to quickly obtain line drawings with clear edges, sufficient detail preservation, and high fidelity text, which are then used as input for conditional generation in Stable Diffusion." + }, + { + "author": "mbrostami", + "title": "ComfyUI-TITrain", + "id": "titrain", + "reference": "https://github.com/mbrostami/ComfyUI-TITrain", + "files": [ + "https://github.com/mbrostami/ComfyUI-TITrain" + ], + "install_type": "git-clone", + "description": "Nodes:TextualInversionTrainingSDXL, TextualInversionTraining" + }, + { + "author": "ArcherFMY", + "title": "Diffusion360_ComfyUI", + "id": "diffusion360", + "reference": "https://github.com/ArcherFMY/Diffusion360_ComfyUI", + "files": [ + "https://github.com/ArcherFMY/Diffusion360_ComfyUI" + ], + "install_type": "git-clone", + "description": "ComfyUI plugin of [a/SD-T2I-360PanoImage](https://github.com/ArcherFMY/SD-T2I-360PanoImage).\nbase t2i-pipeline for generating 512*1024 panorama image from text input" + }, + { + "author": "Makeezi", + "title": "ComfyUI-promptLAB", + "id": "promptlab", + "reference": "https://github.com/Makeezi/ComfyUI-promptLAB", + "files": [ + "https://github.com/Makeezi/ComfyUI-promptLAB" + ], + "install_type": "git-clone", + "description": "connection nodes for api requests, fully supports promptLAB" + }, + { + "author": "portu-sim", + "title": "comfyui_bmab", + "id": "bmab", + "reference": "https://github.com/portu-sim/comfyui_bmab", + "files": [ + "https://github.com/portu-sim/comfyui_bmab" + ], + "install_type": "git-clone", + "description": "BMAB for ComfyUI\n[w/comfyui-bmab is changed to comfyui_bmab. Remove 'custom_nodes/comyui-bmab' in your directory and then reinstall this.]" + }, + { + "author": "griptape-ai", + "title": "ComfyUI Griptape Nodes", + "id": "griptape", + "reference": "https://github.com/griptape-ai/ComfyUI-Griptape", + "files": [ + "https://github.com/griptape-ai/ComfyUI-Griptape" + ], + "install_type": "git-clone", + "description": "This repo creates a series of nodes that enable you to utilize the [a/Griptape Python Framework](https://github.com/griptape-ai/griptape/) with ComfyUI, integrating AI into your workflow. This repo creates a series of nodes that enable you to utilize the Griptape Python Framework with ComfyUI, integrating AI into your workflow." + }, + { + "author": "cavinHuang", + "title": "comfyui-nodes-docs", + "id": "nodedocs", + "reference": "https://github.com/CavinHuang/comfyui-nodes-docs", + "files": [ + "https://github.com/CavinHuang/comfyui-nodes-docs" + ], + "install_type": "git-clone", + "description": "This is a plugin for displaying documentation for each comfyui node. " + }, + { + "author": "icesun963", + "title": "HFDownLoad Node for ComfyUI", + "id": "HFDownLoad-ic", + "reference": "https://github.com/icesun963/ComfyUI_HFDownLoad", + "files": [ + "https://github.com/icesun963/ComfyUI_HFDownLoad" + ], + "install_type": "git-clone", + "description": "Download the model from huggingface and put it in any directory." + }, + { + "author": "conquestace", + "title": "Image Uploader", + "id": "image-uploader", + "reference": "https://github.com/conquestace/ComfyUI-ImageUploader", + "files": [ + "https://github.com/conquestace/ComfyUI-ImageUploader" + ], + "install_type": "git-clone", + "description": "Upload images automatically to image hosting sites." + }, + { + "author": "chandlergis", + "title": "ComfyUI-IMG_Query", + "id": "img-query", + "reference": "https://github.com/chandlergis/ComfyUI-IMG_Query", + "files": [ + "https://github.com/chandlergis/ComfyUI-IMG_Query" + ], + "install_type": "git-clone", + "description": "Nodes:ImageRequestNode" + }, + { + "author": "Isaac Emesowum", + "title": "Isaac's Nodes", + "id": "isaac", + "reference": "https://github.com/iemesowum/ComfyUI_IsaacNodes", + "files": [ + "https://github.com/iemesowum/ComfyUI_IsaacNodes" + ], + "install_type": "git-clone", + "description": "This extension offers automatic drums extraction from audio files, as well as a few helper nodes to support my audio synchronization AnimateDiff workflows." + }, + { + "author": "fexploit", + "title": "ComfyUI-AutoTrimBG", + "id": "autotrimbg", + "reference": "https://github.com/fexploit/ComfyUI-AutoTrimBG", + "files": [ + "https://github.com/fexploit/ComfyUI-AutoTrimBG" + ], + "install_type": "git-clone", + "description": "ComfyUI-AutoCropBgTrim is a powerful tool designed to automatically clean up the background of your images. This tool trims unnecessary spaces and pixels, leaving only the main subject of the image. It generates both a mask and an image output, making it easy to focus on the essential elements. Perfect for enhancing your photos and preparing them for professional use." + }, + { + "author": "fexploit", + "title": "ComfyUI-AutoLabel", + "id": "autolabel", + "reference": "https://github.com/fexploit/ComfyUI-AutoLabel", + "files": [ + "https://github.com/fexploit/ComfyUI-AutoLabel" + ], + "install_type": "git-clone", + "description": "ComfyUI-AutoLabel is a custom node for ComfyUI that uses BLIP (Bootstrapping Language-Image Pre-training) to generate detailed descriptions of the main object in an image. This node leverages the power of BLIP to provide accurate and context-aware captions for images." + }, + { + "author": "fexploit", + "title": "ComfyUI-Classifier", + "id": "classifier", + "reference": "https://github.com/fexploit/ComfyUI-Classifier", + "files": [ + "https://github.com/fexploit/ComfyUI-Classifier" + ], + "install_type": "git-clone", + "description": "ComfyUI-Classifier is a custom node for ComfyUI that uses a zero-shot classification model to classify text inputs based on a set of candidate labels. This node leverages the power of Hugging Face Transformers to provide accurate and flexible text classification." + }, + { + "author": "linshier", + "title": "comfyui-remote-tools", + "id": "remote-tools", + "reference": "https://github.com/linshier/comfyui-remote-tools", + "files": [ + "https://github.com/linshier/comfyui-remote-tools" + ], + "install_type": "git-clone", + "description": "Node:SendBase64ToRemote. To connect to another ComfyUI server." + }, + { + "author": "Fantaxico", + "title": "ComfyUI-GCP-Storage", + "id": "gcp-storage", + "reference": "https://github.com/Fantaxico/ComfyUI-GCP-Storage", + "files": [ + "https://github.com/Fantaxico/ComfyUI-GCP-Storage" + ], + "install_type": "git-clone", + "description": "Node:GCP Storage Node. Support google-cloud-storage." + }, + { + "author": "daniabib", + "title": "ComfyUI ProPainter Nodes", + "id": "propainter", + "reference": "https://github.com/daniabib/ComfyUI_ProPainter_Nodes", + "files": [ + "https://github.com/daniabib/ComfyUI_ProPainter_Nodes" + ], + "install_type": "git-clone", + "description": "ComfyUI custom node implementation of [a/ProPainter](https://github.com/sczhou/ProPainter) framework for video inpainting." + }, + { + "author": "iFREEGROUP", + "title": "comfyui-undistort", + "id": "undistort", + "reference": "https://github.com/iFREEGROUP/comfyui-undistort", + "files": [ + "https://github.com/iFREEGROUP/comfyui-undistort" + ], + "install_type": "git-clone", + "description": "Node:Load Checkerboard Images for Calibrate Camera, Matrix and distortion coefficient to text, Undistort" + }, + { + "author": "Auttasak-L", + "title": "ComfyUI-ImageCropper", + "id": "imagecropper", + "reference": "https://github.com/Auttasak-L/ComfyUI-ImageCropper", + "files": [ + "https://github.com/Auttasak-L/ComfyUI-ImageCropper" + ], + "install_type": "git-clone", + "description": "Nodes:Image cropping tool" + }, + { + "author": "muzi12888", + "title": "PoseKeypoint Mask", + "id": "posekeypoint-mask", + "reference": "https://github.com/muzi12888/ComfyUI-PoseKeypoint-Mask", + "files": [ + "https://github.com/muzi12888/ComfyUI-PoseKeypoint-Mask" + ], + "install_type": "git-clone", + "description": "Convert PoseKeypoint to mask, please refer to the example workflow for usage instructions." + }, + { + "author": "muzi12888", + "title": "m9-prompts-comfyui", + "id": "m9-prompts", + "reference": "https://github.com/MarcusNyne/m9-prompts-comfyui", + "files": [ + "https://github.com/MarcusNyne/m9-prompts-comfyui" + ], + "install_type": "git-clone", + "description": "Two custom nodes are included for modifying a prompt to create prompt variations.\nScramblePrompts [m9]: Reorder prompts, remove prompts, modify weights\nTweakWeights [m9]: Modify the weights of prompts matching keywords" + }, + { + "author": "xuhongming251", + "title": "ComfyUI-GPEN", + "id": "gpen", + "reference": "https://github.com/xuhongming251/ComfyUI-GPEN", + "files": [ + "https://github.com/xuhongming251/ComfyUI-GPEN" + ], + "install_type": "git-clone", + "description": "Nodes:FaceEnhancement. Based on modelscope pipeline." + }, + { + "author": "xuhongming251", + "title": "ComfyUI-MuseTalkUtils", + "id": "musetalk-utils", + "reference": "https://github.com/xuhongming251/ComfyUI-MuseTalkUtils", + "files": [ + "https://github.com/xuhongming251/ComfyUI-MuseTalkUtils" + ], + "install_type": "git-clone", + "description": "MuseTalk ComfyUI Preprocess and Postprocess Nodes" + }, + { + "author": "Thomas Ward", + "title": "TW-CUI-Util", + "id": "tw-cui-util", + "reference": "https://github.com/TW-CUI/TW-CUI-Util", + "files": [ + "https://github.com/TW-CUI/TW-CUI-Util" + ], + "install_type": "git-clone", + "description": "A collection of custom nodes to help with saving images, providing generation parameters, static literal nodes, and other useful nodes." + }, + { + "author": "lks-ai", + "title": "ComfyUI AnyNode: Any Node you ask for", + "id": "anynode", + "reference": "https://github.com/lks-ai/anynode", + "files": [ + "https://github.com/lks-ai/anynode" + ], + "install_type": "git-clone", + "description": "Nodes: AnyNode. Nodes that can be anything you ask. Auto-Generate functional nodes using LLMs. Create impossible workflows. API Compatibility: (OpenAI, LocalLLMs, Gemini)." + }, + { + "author": "lks-ai", + "title": "ComfyUI Stable Audio Open 1.0 Sampler", + "id": "stableaudiosampler", + "reference": "https://github.com/lks-ai/ComfyUI-StableAudioSampler", + "files": [ + "https://github.com/lks-ai/ComfyUI-StableAudioSampler" + ], + "install_type": "git-clone", + "description": "Nodes: StableAudioSampler. Wraps the new Stable Audio Open Model in the sampler that dropped Jun 5th. See Github for Features" + }, + { + "author": "SayanoAI", + "title": "Comfy-RVC", + "id": "sayano-rvc", + "reference": "https://github.com/SayanoAI/Comfy-RVC", + "files": [ + "https://github.com/SayanoAI/Comfy-RVC" + ], + "install_type": "git-clone", + "description": "ComfyUI custom nodes for RVC related inference and image generation" + }, + { + "author": "nirbhay-faaya", + "title": "ImgProcessing_ComfyUI", + "id": "imgprocessing", + "reference": "https://github.com/nirbhay-faaya/ImgProcessing_ComfyUI", + "files": [ + "https://github.com/nirbhay-faaya/ImgProcessing_ComfyUI" + ], + "install_type": "git-clone", + "description": "Custom Image processing ComfyUI Nodes" + }, + { + "author": "larsupb", + "title": "LoRA Power-Merger ComfyUI", + "id": "lora-powermerger", + "reference": "https://github.com/larsupb/LoRA-Merger-ComfyUI", + "files": [ + "https://github.com/larsupb/LoRA-Merger-ComfyUI" + ], + "install_type": "git-clone", + "description": "An extension for merging LoRAs. Offers a wide range of LoRA merge techniques (including dare) and XY plots. XY plots require efficiency nodes." + }, + { + "author": "Mason-McGough", + "title": "Mosaica", + "id": "mosaica", + "reference": "https://github.com/Mason-McGough/ComfyUI-Mosaica", + "files": [ + "https://github.com/Mason-McGough/ComfyUI-Mosaica" + ], + "install_type": "git-clone", + "description": "Create colorful mosaic images in ComfyUI by computing label images and applying lookup tables." + }, + { + "author": "cuongloveit", + "title": "comfy_http_request", + "reference": "https://github.com/cuongloveit/comfy_http_request", + "files": [ + "https://github.com/cuongloveit/comfy_http_request" + ], + "install_type": "git-clone", + "description": "Nodes:Send Http Request. You can use this node to save full size images through the websocket." + }, + { + "author": "Ron-Digital", + "title": "ComfyUI-SceneGenerator", + "id": "scenegenerator", + "reference": "https://github.com/Ron-Digital/ComfyUI-SceneGenerator", + "files": [ + "https://github.com/Ron-Digital/ComfyUI-SceneGenerator" + ], + "install_type": "git-clone", + "description": "ComfyUI-SceneGenerator is a ComfyUI plugin used to generate scene preview photos from JSON files. This plugin creates scenes based on the provided JSON configuration and produces two different image outputs: one containing only the products and the other containing both the products and the props." + }, + { + "author": "xliry", + "title": "ComfyUI_SendDiscord", + "id": "senddiscord", + "reference": "https://github.com/xliry/ComfyUI_SendDiscord", + "files": [ + "https://github.com/xliry/ComfyUI_SendDiscord" + ], + "install_type": "git-clone", + "description": "Nodes:Send Video to Discord" + }, + { + "author": "xliry", + "title": "color2rgb", + "reference": "https://github.com/vxinhao/color2rgb", + "files": [ + "https://github.com/vxinhao/color2rgb/raw/main/color2rgb.py" + ], + "install_type": "copy", + "description": "Nodes:color2RGB" + }, + { + "author": "moyi7712", + "title": "ComfyUI_Seamless_Patten", + "id": "seamless-pattern", + "reference": "https://github.com/moyi7712/ComfyUI_Seamless_Patten", + "files": [ + "https://github.com/moyi7712/ComfyUI_Seamless_Patten" + ], + "install_type": "git-clone", + "description": "It make any text2image create seamless patten" + }, + { + "author": "nirex0", + "title": "ComfyUI_pytorch_openpose", + "id": "pytorch-openpose", + "reference": "https://github.com/nirex0/ComfyUI_pytorch_openpose", + "files": [ + "https://github.com/nirex0/ComfyUI_pytorch_openpose" + ], + "install_type": "git-clone", + "description": "All Credits go to the original Repo: [a/Hzzone/pytorch-openpose](https://github.com/Hzzone/pytorch-openpose)." + }, + { + "author": "AshMartian", + "title": "Dir Gir", + "id": "dir-gir", + "reference": "https://github.com/AshMartian/ComfyUI-DirGir", + "files": [ + "https://github.com/AshMartian/ComfyUI-DirGir" + ], + "install_type": "git-clone", + "description": "A collection of ComfyUI directory automation utility nodes. Directory Get It Right adds a GUI directory browser, and smart directory loop/iteration node that supports regex and file extension filtering." + }, + { + "author": "SozeInc", + "title": "ComfyUI-Mobile", + "id": "comfyui-mobile", + "reference": "https://github.com/SozeInc/ComfyUI-Mobile", + "files": [ + "https://github.com/SozeInc/ComfyUI-Mobile" + ], + "install_type": "git-clone", + "description": "Nodes: Ultimate Concat (Mobile), Send Notification (Mobile), Settings Launcher (Mobile), Settings Launcher Outputs (Mobile)" + }, + { + "author": "audioscavenger", + "title": "ComfyUI Thumbnails", + "id": "thumbnails", + "reference": "https://github.com/audioscavenger/ComfyUI-Thumbnails", + "files": [ + "https://github.com/audioscavenger/ComfyUI-Thumbnails" + ], + "install_type": "git-clone", + "description": "Load Image thumbnails for ComfyUI" + }, + { + "author": "goktug", + "title": "Save Image Plus for ComfyUI", + "id": "saveimage-plus", + "reference": "https://github.com/Goktug/comfyui-saveimage-plus", + "files": [ + "https://github.com/Goktug/comfyui-saveimage-plus" + ], + "install_type": "git-clone", + "description": "Save Image Plus is a custom node for ComfyUI that allows you to save images in JPEG and WEBP formats with optional metadata embedding." + }, + { + "author": "wujm424606", + "title": "ComfyUi-Ollama-YN", + "id": "ollama-YN", + "reference": "https://github.com/wujm424606/ComfyUi-Ollama-YN", + "files": [ + "https://github.com/wujm424606/ComfyUi-Ollama-YN" + ], + "install_type": "git-clone", + "description": "Custom ComfyUI Nodes for interacting with [a/Ollama](https://ollama.com/) using the [a/ollama python client](https://github.com/ollama/ollama-python).\n Meanwhile it will provide better prompt descriptor for stable diffusion." + }, + { + "author": "tmagara", + "title": "ComfyUI-Prediction-Boost", + "id": "prediction-boost", + "reference": "https://github.com/tmagara/ComfyUI-Prediction-Boost", + "files": [ + "https://github.com/tmagara/ComfyUI-Prediction-Boost" + ], + "install_type": "git-clone", + "description": "prediction boost custom node for ComfyUI" + }, + { + "author": "chesnokovivan", + "title": "ComfyUI-Novakid", + "id": "novakid", + "reference": "https://github.com/chesnokovivan/ComfyUI-Novakid", + "files": [ + "https://github.com/chesnokovivan/ComfyUI-Novakid" + ], + "install_type": "git-clone", + "description": "ComfyUI: Novakid. A node." + }, + { + "author": "Jin Liu", + "title": "ComfyUI-Photopea", + "id": "photopea", + "reference": "https://github.com/coolzilj/ComfyUI-Photopea", + "files": [ + "https://github.com/coolzilj/ComfyUI-Photopea" + ], + "install_type": "git-clone", + "description": "Edit images in the Photopea editor directly within ComfyUI." + }, + { + "author": "bitaffinity", + "title": "ComfyUI_HF_Inference", + "id": "hf-inference", + "reference": "https://github.com/bitaffinity/ComfyUI_HF_Inference", + "files": [ + "https://github.com/bitaffinity/ComfyUI_HF_Inference" + ], + "install_type": "git-clone", + "description": "Unofficial support for Hugging Face's hosted inference." + }, + { + "author": "claussteinmassl", + "title": "CS Transform Node for ComfyUI", + "id": "cs-transform", + "reference": "https://github.com/claussteinmassl/ComfyUI-CS-CustomNodes", + "files": [ + "https://github.com/claussteinmassl/ComfyUI-CS-CustomNodes" + ], + "install_type": "git-clone", + "description": "The CS Transform node is a custom node for ComfyUI that applies a series of transformations to an input image and mask. The transformations include scaling, rotation, and translation, all centered around a specified pivot point. The node ensures that the transformed image is properly accommodated within a canvas, which can be expanded if needed." + }, + { + "author": "MariusKM", + "title": "ComfyUI-BadmanNodes", + "id": "badman", + "reference": "https://github.com/MariusKM/ComfyUI-BadmanNodes", + "files": [ + "https://github.com/MariusKM/ComfyUI-BadmanNodes" + ], + "install_type": "git-clone", + "description": "Nodes:Badman_Blend, Badman_HexGenerator, Badman_String, Badman_Concat_String, Badman_Print, BadmanIO, BadmanIntUtil" + }, + { + "author": "TMElyralab", + "title": "Comfyui-MusePose", + "id": "musepose", + "reference": "https://github.com/TMElyralab/Comfyui-MusePose", + "files": [ + "https://github.com/TMElyralab/Comfyui-MusePose" + ], + "install_type": "git-clone", + "description": "[a/MusePose](https://github.com/TMElyralab/MusePose) is an image-to-video generation framework for virtual human under control signal such as pose.\nNOTE: You need to download weigths manually from: [a/https://huggingface.co/TMElyralab/MusePose](https://huggingface.co/TMElyralab/MusePose).[w/The repository name has changed. If you are not receiving updates, please delete the existing node and reinstall it.]" + }, + { + "author": "PnthrLeo", + "title": "comfyUI-image-search", + "id": "image-search", + "reference": "https://github.com/PnthrLeo/comfyUI-image-search", + "files": [ + "https://github.com/PnthrLeo/comfyUI-image-search" + ], + "install_type": "git-clone", + "description": "Nodes:Close Images Searcher" + }, + { + "author": "l20richo", + "title": "ComfyUI-Azure-Blob-Storage", + "id": "azure-blob-storage", + "reference": "https://github.com/l20richo/ComfyUI-Azure-Blob-Storage", + "files": [ + "https://github.com/l20richo/ComfyUI-Azure-Blob-Storage" + ], + "install_type": "git-clone", + "description": "ComfyUI-Azure-Blob-Storage seamlessly integrates with [a/Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs/) in ComfyUI. This open-source project provides custom nodes for effortless loading and saving of images, videos, and checkpoint models directly from Azure blob containers within the ComfyUI graph interface." + }, + { + "author": "AARG-FAN", + "title": "Image-vector-for-ComfyUI", + "id": "image-vector", + "reference": "https://github.com/AARG-FAN/Image-Raster-for-ComfyUI", + "files": [ + "https://github.com/AARG-FAN/Image-Raster-for-ComfyUI" + ], + "install_type": "git-clone", + "description": "a wrap-up of ComfyUI nodes for converting pixels to raster, sent out to [a/Vtracer](https://github.com/visioncortex/vtracer)!" + }, + { + "author": "Smirnov75", + "title": "ComfyUI-mxToolkit", + "id": "mxtoolkit", + "reference": "https://github.com/Smirnov75/ComfyUI-mxToolkit", + "files": [ + "https://github.com/Smirnov75/ComfyUI-mxToolkit" + ], + "install_type": "git-clone", + "description": "A set of useful nodes for convenient use of ComfyUI, including: Seed randomization before the generation process starts, with saving of the last used values and the ability to automatically interrupt the current generation; A function to pause the generation process; Slider nodes for convenient control of input parameters; An alternative version of the standard Reroute node." + }, + { + "author": "humgate", + "title": "simplecomfy", + "reference": "https://github.com/humgate/simplecomfy", + "files": [ + "https://github.com/humgate/simplecomfy" + ], + "install_type": "git-clone", + "description": "Simple JS application based on ComfyUI which takes prompt and style picture from user and runs hardcoded workflow inference returning generated image to user." + }, + { + "author": "vanche1212", + "title": "ZMG PLUGIN", + "id": "zmg", + "reference": "https://github.com/vanche1212/ComfyUI-ZMG-Nodes", + "files": [ + "https://github.com/vanche1212/ComfyUI-ZMG-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:ApiRequestNode, LoadVideoNode, JsonParserNode, OllamaRequestNode, OldPhotoColorizationNode." + }, + { + "author": "hben35096", + "title": "ComfyUI-ToolBox", + "id": "hben-toolbox", + "reference": "https://github.com/hben35096/ComfyUI-ToolBox", + "files": [ + "https://github.com/hben35096/ComfyUI-ToolBox" + ], + "install_type": "git-clone", + "description": "Nodes:commonly_node." + }, + { + "author": "tiankuan93", + "title": "V-Express: Conditional Dropout for Progressive Training of Portrait Video Generation", + "id": "v-express", + "reference": "https://github.com/tiankuan93/ComfyUI-V-Express", + "files": [ + "https://github.com/tiankuan93/ComfyUI-V-Express" + ], + "install_type": "git-clone", + "description": "[Original] In the field of portrait video generation, the use of single images to generate portrait videos has become increasingly prevalent. A common approach involves leveraging generative models to enhance adapters for controlled generation. However, control signals can vary in strength, including text, audio, image reference, pose, depth map, etc. Among these, weaker conditions often struggle to be effective due to interference from stronger conditions, posing a challenge in balancing these conditions. In our work on portrait video generation, we identified audio signals as particularly weak, often overshadowed by stronger signals such as pose and original image. However, direct training with weak signals often leads to difficulties in convergence. To address this, we propose V-Express, a simple method that balances different control signals through a series of progressive drop operations. Our method gradually enables effective control by weak conditions, thereby achieving generation capabilities that simultaneously take into account pose, input image, and audio.\nNOTE: You need to downdload [a/model_ckpts](https://huggingface.co/tk93/V-Express/tree/main) manually." + }, + { + "author": "CMonk", + "title": "Stable Projectorz Bridge", + "id": "projectorz", + "reference": "https://github.com/tianlang0704/ComfyUI-StableProjectorzBridge", + "files": [ + "https://github.com/tianlang0704/ComfyUI-StableProjectorzBridge" + ], + "install_type": "git-clone", + "description": "This custom nodes enables Stable Projectorz to work with ComfyUI Directly." + }, + { + "author": "Scorpinaus", + "title": "Loaders for Diffusers-format checkpoints", + "id": "diffusersloader", + "reference": "https://github.com/Scorpinaus/ComfyUI-DiffusersLoader", + "files": [ + "https://github.com/Scorpinaus/ComfyUI-DiffusersLoader" + ], + "install_type": "git-clone", + "description": "This node pack allows loading of CLIP, MODEL, VAE aspects for both SD1.5 and SDXL checkpoints that is converted to diffusers format." + }, + { + "author": "chakib-belgaid", + "title": "ComfyUI Style Plugin", + "id": "style-plugin", + "reference": "https://github.com/chakib-belgaid/Comfyui_Prompt_styler", + "files": [ + "https://github.com/chakib-belgaid/Comfyui_Prompt_styler" + ], + "install_type": "git-clone", + "description": "This is a simple plugin for ComfyUI that allows you to import A1111 CSV styles into ComfyUI prompts." + }, + { + "author": "chakib-belgaid", + "title": "ComfyUI-autosize", + "id": "autosize", + "reference": "https://github.com/chakib-belgaid/ComfyUI-autosize", + "files": [ + "https://github.com/chakib-belgaid/ComfyUI-autosize" + ], + "install_type": "git-clone", + "description": "A ComfyUI utility plugin designed to optimize the latent space for generating high-quality results. It approximates the closest size model for better generation results." + }, + { + "author": "ThereforeGames", + "title": "ComfyUI-Unprompted", + "id": "unprompted", + "reference": "https://github.com/ThereforeGames/ComfyUI-Unprompted", + "files": [ + "https://github.com/ThereforeGames/ComfyUI-Unprompted" + ], + "install_type": "git-clone", + "description": "This is a ComfyUI node that processes your input text with the [a/Unprompted templating language](https://github.com/ThereforeGames/unprompted). Early alpha release.\n" + }, + { + "author": "Tool Of North america", + "title": "Easy automatic (square) image cropper using Yolo", + "id": "tooldigital", + "reference": "https://github.com/tooldigital/ComfyUI-Yolo-Cropper", + "files": [ + "https://github.com/tooldigital/ComfyUI-Yolo-Cropper" + ], + "install_type": "git-clone", + "description": "A very simple and easy to use node to automaticaaly create (square) image crops and masks using YoloV8. This can be very useful when using controlnet and ip adapters" + }, + { + "author": "luandev", + "title": "ComfyUI CrewAI", + "id": "crewai", + "reference": "https://github.com/luandev/ComfyUI-CrewAI", + "files": [ + "https://github.com/luandev/ComfyUI-CrewAI" + ], + "install_type": "git-clone", + "description": "ComfyUI-CrewAI aims to integrate Crew AI's multi-agent collaboration framework into the ComfyUI environment. By combining the strengths of Crew AI's role-based, collaborative AI agent system with ComfyUI's intuitive interface, we will create a robust platform for managing and executing complex AI tasks seamlessly" + }, + { + "author": "chandlergis", + "title": "ComfyUI_EmojiOverlay", + "id": "emoji-overlay", + "reference": "https://github.com/chandlergis/ComfyUI_EmojiOverlay", + "files": [ + "https://github.com/chandlergis/ComfyUI_EmojiOverlay" + ], + "install_type": "git-clone", + "description": "Nodes:Image Emoji Overlay" + }, + { + "author": "JayLyu", + "title": "ComfyUI_BaiKong_Node", + "id": "baikong", + "reference": "https://github.com/JayLyu/ComfyUI_BaiKong_Node", + "files": [ + "https://github.com/JayLyu/ComfyUI_BaiKong_Node" + ], + "install_type": "git-clone", + "description": "Nodes:BK Img To Color, BK Color Selector" + }, + { + "author": "risunobushi", + "title": "comfyUI_FrequencySeparation_RGB-HSV", + "id": "freq-sep", + "reference": "https://github.com/risunobushi/comfyUI_FrequencySeparation_RGB-HSV", + "files": [ + "https://github.com/risunobushi/comfyUI_FrequencySeparation_RGB-HSV" + ], + "install_type": "git-clone", + "description": "A collection of simple nodes for Frequency Separation / Frequency Recombine with RGB and HSV methods" + }, + { + "author": "zohac", + "title": "ComfyUI_ZC_DrawShape", + "id": "drawshape", + "reference": "https://github.com/zohac/ComfyUI_ZC_DrawShape", + "files": [ + "https://github.com/zohac/ComfyUI_ZC_DrawShape" + ], + "install_type": "git-clone", + "description": "Nodes:ZC DrawShape Node" + }, + { + "author": "DataCTE", + "title": "Prompt Injection Node for ComfyUI", + "id": "prompt-injection", + "reference": "https://github.com/DataCTE/prompt_injection", + "files": [ + "https://github.com/DataCTE/prompt_injection" + ], + "install_type": "git-clone", + "description": "This custom node for ComfyUI allows you to inject specific prompts at specific blocks of the Stable Diffusion UNet, providing fine-grained control over the generated image. It is based on the concept that the content/subject understanding of the model is primarily contained within the MID0 and MID1 blocks, as demonstrated in the B-Lora (Content Style implicit separation) paper. Features.\nInject different prompts into specific UNet blocks Three different node variations for flexible workflow integration Customize the learning rate of specific blocks to focus on content, lighting, style, or other aspects Potential for developing a 'Mix of Experts' approach by swapping blocks on-the-fly based on prompt content" + }, + { + "author": "FrankChieng", + "title": "ComfyUI_llm_easyanimiate", + "id": "llm-easyanimate", + "nodename_pattern": "^FrankChiengEasyAnimate", + "reference": "https://github.com/frankchieng/ComfyUI_llm_easyanimiate", + "files": [ + "https://github.com/frankchieng/ComfyUI_llm_easyanimiate" + ], + "install_type": "git-clone", + "description": "implementation easyanimate with llama3-8b-6bit instruction LLM generation prompt help" + }, + { + "author": "nuanarchy", + "title": "ComfyUI-NuA-FlashFace", + "id": "nua-flashface", + "reference": "https://github.com/nuanarchy/ComfyUI-NuA-FlashFace", + "files": [ + "https://github.com/nuanarchy/ComfyUI-NuA-FlashFace" + ], + "install_type": "git-clone", + "description": "ComfyUI implementation of [a/FlashFace: Human Image Personalization with High-fidelity Identity Preservation](https://github.com/ali-vilab/FlashFace)\nNOTE: You need to downalod models manually." + }, + { + "author": "nuanarchy", + "title": "ComfyUI-NuA-BIRD", + "id": "nua-bird", + "reference": "https://github.com/nuanarchy/ComfyUI-NuA-BIRD", + "files": [ + "https://github.com/nuanarchy/ComfyUI-NuA-BIRD" + ], + "install_type": "git-clone", + "description": "ComfyUI implementation of '[a/Blind Image Restoration via Fast Diffusion Inversion](https://github.com/hamadichihaoui/BIRD)' Original [a/article](https://arxiv.org/abs/2405.19572)" + }, + { + "author": "denfrost", + "title": "Den_ComfyUI_Workflows", + "id": "den", + "reference": "https://github.com/denfrost/Den_ComfyUI_Workflow", + "files": [ + "https://github.com/denfrost/Den_ComfyUI_Workflow" + ], + "install_type": "git-clone", + "description": "Custom nodes make easy Advanced Workflows. Focus on Image/Video and ControlNet efficiency and performances. Manipulation of Latent Space, Automatic pipeline with a bit efforts." + }, + { + "author": "marduk191", + "title": "marduk191 workflow settings", + "id": "marnodes", + "reference": "https://github.com/marduk191/comfyui-marnodes", + "files": [ + "https://github.com/marduk191/comfyui-marnodes" + ], + "install_type": "git-clone", + "description": "A node to set workflow settings." + }, + { + "author": "haohaocreates", + "title": "ComfyUI-HH-Image-Selector", + "id": "hh-image-selector", + "reference": "https://github.com/haohaocreates/ComfyUI-HH-Image-Selector", + "files": [ + "https://github.com/haohaocreates/ComfyUI-HH-Image-Selector" + ], + "install_type": "git-clone", + "description": "comfy ui custom node that returns an image from a batch based on selected criteria such as RGB value, brightness, etc (credits to chris goringe's custom nodes tutorial )." + }, + { + "author": "exdysa", + "title": "comfyui-selector", + "reference": "https://github.com/exdysa/comfyui-selector", + "files": [ + "https://github.com/exdysa/comfyui-selector" + ], + "install_type": "git-clone", + "description": "Nodes:Selector. Quick and dirty parameter generator node for ComfyUI." + }, + { + "author": "Jin Liu", + "title": "ComfyUI-LJNodes", + "id": "ComfyUI-LJNodes", + "reference": "https://github.com/coolzilj/ComfyUI-LJNodes", + "files": [ + "https://github.com/coolzilj/ComfyUI-LJNodes" + ], + "install_type": "git-clone", + "description": "A variety of custom nodes to enhance ComfyUI for a buttery smooth experience." + }, + { + "author": "GavChap", + "title": "ComfyUI-SD3LatentSelectRes", + "id": "sd3latent-select-res", + "reference": "https://github.com/GavChap/ComfyUI-SD3LatentSelectRes", + "files": [ + "https://github.com/GavChap/ComfyUI-SD3LatentSelectRes" + ], + "install_type": "git-clone", + "description": "You'll get a new node called SD3 Latent Select Resolution, you can pick the x and y sizes from a list." + }, + { + "author": "BenNarum", + "title": "SigmaWaveFormNodes", + "id": "sigmawaveform", + "reference": "https://github.com/BenNarum/SigmaWaveFormNode", + "files": [ + "https://github.com/BenNarum/SigmaWaveFormNode" + ], + "install_type": "git-clone", + "description": "A set of tools for generating and altering sigmas in ComfyUI." + }, + { + "author": "shobhitic", + "title": "PlusMinusTextClip - Single node for Positive and Negative Prompts", + "id": "plusminustextclip", + "reference": "https://github.com/shobhitic/ComfyUI-PlusMinusTextClip", + "files": [ + "https://github.com/shobhitic/ComfyUI-PlusMinusTextClip" + ], + "install_type": "git-clone", + "description": "This adds a node that has both the positive and negative prompts as input in one node. You can just add one node and be done with both Positive and Negative prompts, in place of adding two different nodes for them." + }, + { + "author": "Late Night Labs", + "title": "LNL Frame Selector", + "id": "lnlframeselector", + "reference": "https://github.com/latenightlabs/ComfyUI-LNL", + "files": [ + "https://github.com/latenightlabs/ComfyUI-LNL" + ], + "install_type": "git-clone", + "description": "Frame Selector & Sequence Selection Node for ComfyUI." + }, + { + "author": "Michael Standen", + "title": "Ollama Prompt Encode", + "id": "ollamapromptencode", + "reference": "https://github.com/ScreamingHawk/comfyui-ollama-prompt-encode", + "files": [ + "https://github.com/ScreamingHawk/comfyui-ollama-prompt-encode" + ], + "install_type": "git-clone", + "description": "A prompt generator and CLIP encoder using AI provided by Ollama." + }, + { + "author": "toxicwind", + "title": "TTools for ComfyUI", + "id": "ttools", + "reference": "https://github.com/toxicwind/ComfyUI-TTools", + "files": [ + "https://github.com/toxicwind/ComfyUI-TTools" + ], + "install_type": "git-clone", + "description": "Text Randomization and Formatting, JSON Extraction and Processing, SD3 Resolution Solver" + }, + { + "author": "Yanick112", + "title": "ComfyUI-ToSVG", + "id": "tosvg", + "reference": "https://github.com/Yanick112/ComfyUI-ToSVG", + "files": [ + "https://github.com/Yanick112/ComfyUI-ToSVG" + ], + "install_type": "git-clone", + "description": "This project converts raster images into SVG format using the [a/VTracer](https://github.com/visioncortex/vtracer) library. It's a handy tool for designers and developers who need to work with vector graphics programmatically." + }, + { + "author": "dicksondickson", + "title": "ComfyUI-Dickson-Nodes", + "id": "dicksonnodes", + "reference": "https://github.com/dicksondickson/ComfyUI-Dickson-Nodes", + "files": [ + "https://github.com/dicksondickson/ComfyUI-Dickson-Nodes" + ], + "install_type": "git-clone", + "description": "Custom nodes for ComfyUI by DicksonDickson." + }, + { + "author": "juehackr", + "title": "comfyui_fk_server", + "id": "fk-server", + "reference": "https://github.com/juehackr/comfyui_fk_server", + "files": [ + "https://github.com/juehackr/comfyui_fk_server" + ], + "install_type": "git-clone", + "description": "🤗🤗🤗Comfyui Universal Translation Plugin (no longer requires adding various nodes, directly add translation function on the existing nodes), allowing Comfyui to support Chinese input and automatic translation for any long text input box, while adding error translation function (calling Baidu Translate), achieving translation freedom!" + }, + { + "author": "G-370", + "title": "ComfyUI-SD3-Powerlab", + "id": "sd3-powerlab", + "reference": "https://github.com/G-370/ComfyUI-SD3-Powerlab", + "files": [ + "https://github.com/G-370/ComfyUI-SD3-Powerlab" + ], + "install_type": "git-clone", + "description": "Nodes:Render SD3 Attention, SD3 Attention To Image, SD3 Image Into Attention." + }, + { + "author": "TylerZoro", + "title": "SD3-Scaling", + "id": "sd3-scaling", + "reference": "https://github.com/TylerZoro/SD3-Scaling", + "files": [ + "https://github.com/TylerZoro/SD3-Scaling" + ], + "install_type": "git-clone", + "description": "Tools for scaling images and latents appropriate to SD3 in ComfyUI." + }, + { + "author": "baicai99", + "title": "ComfyUI-FrameSkipping", + "id": "FrameSkipping", + "reference": "https://github.com/baicai99/ComfyUI-FrameSkipping", + "files": [ + "https://github.com/baicai99/ComfyUI-FrameSkipping" + ], + "install_type": "git-clone", + "description": "Used to process video redrawing, frame skipping, frame ending early, etc." + }, + { + "author": "SuperMasterBlasterLaser", + "title": "ComfyUI_YOLO_Classifiers", + "id": "yolo-classifier", + "reference": "https://github.com/SuperMasterBlasterLaser/ComfyUI_YOLO_Classifiers", + "files": [ + "https://github.com/SuperMasterBlasterLaser/ComfyUI_YOLO_Classifiers" + ], + "install_type": "git-clone", + "description": "Nodes:YOLO Classifier Model Loader, YOLO Classify." + }, + { + "author": "SamKhoze", + "title": "DeepFuze", + "id": "deepfuze", + "reference": "https://github.com/SamKhoze/ComfyUI-DeepFuze", + "files": [ + "https://github.com/SamKhoze/ComfyUI-DeepFuze" + ], + "install_type": "git-clone", + "description": "DeepFuze is a state-of-the-art deep learning tool that seamlessly integrates with ComfyUI to revolutionize facial transformations, lipsyncing, video generation, voice cloning, face swapping, and lipsync translation. Leveraging advanced algorithms, DeepFuze enables users to combine audio and video with unparalleled realism, ensuring perfectly synchronized facial movements. This innovative solution is ideal for content creators, animators, developers, and anyone seeking to elevate their video editing projects with sophisticated AI-driven features." + }, + { + "author": "superyoman", + "title": "comfyui_lumaAPI", + "id": "luma", + "reference": "https://github.com/superyoman/comfyui_lumaAPI", + "files": [ + "https://github.com/superyoman/comfyui_lumaAPI" + ], + "install_type": "git-clone", + "description": "Unofficial Luma API-ComfyUI version.[w/WARN: This project is for learning purpose only!]" + }, + { + "author": "chris-the-wiz", + "title": "EmbeddingsCurveEditor_ComfyUI", + "id": "embeddings-curve-editor", + "reference": "https://github.com/chris-the-wiz/EmbeddingsCurveEditor_ComfyUI", + "files": [ + "https://github.com/chris-the-wiz/EmbeddingsCurveEditor_ComfyUI" + ], + "install_type": "git-clone", + "description": "Edit embeddings with a curve. Actually should work on any 1D input tensor. Tested with IPAdapter-Plus." + }, + { + "author": "zhulu111", + "title": "ComfyUI_Bxb", + "id": "ComfyUI_Bxb", + "reference": "https://github.com/zhulu111/ComfyUI_Bxb", + "files": [ + "https://github.com/zhulu111/ComfyUI_Bxb" + ], + "install_type": "git-clone", + "description": "sdBxb, a tool that converts ComfyUI workflows into WeChat Mini Program, Douyin Mini Program, and H5 with one click, and supports payments." + }, + { + "author": "lordgasmic", + "title": "comfyui_wildcards", + "reference": "https://github.com/lordgasmic/comfyui_wildcards", + "files": [ + "https://github.com/lordgasmic/comfyui_wildcards" + ], + "install_type": "git-clone", + "description": "This is an attempt to recreate the wildcards plugin for Automatic1111 but for ComfyUI." + }, + { + "author": "lordgasmic", + "title": "comfyui_save_image_with_options", + "reference": "https://github.com/lordgasmic/comfyui_save_image_with_options", + "files": [ + "https://github.com/lordgasmic/comfyui_save_image_with_options" + ], + "install_type": "git-clone", + "description": "Nodes:Save Image with Options" + }, + { + "author": "opvelll", + "title": "Comfy UI Text List Product", + "id": "listproduct", + "reference": "https://github.com/opvelll/ComfyUI_TextListProduct", + "files": [ + "https://github.com/opvelll/ComfyUI_TextListProduct" + ], + "install_type": "git-clone", + "description": "This is a custom node for Comfy UI. It mainly wraps itertools.product and can be used to create patterns by combining prompts. It is recommended to install this custom node in combination with the nodes from the WAS Node Suite." + }, + { + "author": "jakechai", + "title": "ComfyUI-JakeUpgrade", + "id": "jkupgrade", + "reference": "https://github.com/jakechai/ComfyUI-JakeUpgrade", + "files": [ + "https://github.com/jakechai/ComfyUI-JakeUpgrade" + ], + "install_type": "git-clone", + "description": "A ComfyUI workflow customization by Jake." + }, + { + "author": "celsojr2013", + "title": "ComfyUI SimpleTools Suit", + "reference": "https://github.com/celsojr2013/comfyui_simpletools", + "files": [ + "https://github.com/celsojr2013/comfyui_simpletools" + ], + "install_type": "git-clone", + "description": "Nodes:Simple Google Translator, Simple Resolution Solver.\nThis is a small set of simple nodes that help your workflow on ComfyUI." + }, + { + "author": "celsojr2013", + "title": "comfyui_jamworks_client", + "reference": "https://github.com/celsojr2013/comfyui_jamworks_client", + "files": [ + "https://github.com/celsojr2013/comfyui_jamworks_client" + ], + "install_type": "git-clone", + "description": "Nodes:Jamworks_Login, Jamworks_Download, Shell_Command.\nA Simple Client for Jamworks Platform DAM Integration" + }, + { + "author": "fablestudio", + "title": "ComfyUI-Showrunner-Utils", + "reference": "https://github.com/fablestudio/ComfyUI-Showrunner-Utils", + "files": [ + "https://github.com/fablestudio/ComfyUI-Showrunner-Utils" + ], + "install_type": "git-clone", + "description": "Comfyui Custom Nodes for Showrunner" + }, + { + "author": "MilitantHitchhiker", + "title": "Militant Hitchhiker's Switchblade Pack", + "id": "hitchhiker", + "reference": "https://github.com/MilitantHitchhiker/MilitantHitchhiker-SwitchbladePack", + "files": [ + "https://github.com/MilitantHitchhiker/MilitantHitchhiker-SwitchbladePack" + ], + "install_type": "git-clone", + "description": "Militant Hitchhiker's Switchblade Pack is a collection of custom nodes for ComfyUI that provide various multi-function capabilities." + }, + { + "author": "slyt", + "title": "comfyui-ollama-nodes", + "reference": "https://github.com/slyt/comfyui-ollama-nodes", + "files": [ + "https://github.com/slyt/comfyui-ollama-nodes" + ], + "install_type": "git-clone", + "description": "ComfyUI custom nodes for working with [a/Ollama](https://github.com/ollama/ollama).\nNOTE:Assumes that an Ollama server is running at http://127.0.0.1:11434 and accessible by the ComfyUI backend." + }, + { + "author": "zwng", + "title": "ComfyUI_Zwng_Nodes", + "id": "zwng", + "reference": "https://github.com/za-wa-n-go/ComfyUI_Zwng_Nodes", + "files": [ + "https://github.com/za-wa-n-go/ComfyUI_Zwng_Nodes" + ], + "install_type": "git-clone", + "description": "Simple nodes for loading image files.Nodes that include a simple remote connection to Photoshop, a node that can overlay and preview an image with a mask, and a node that can load images directly from a file path." + }, + { + "author": "RedRayz", + "title": "ComfyUI-Danbooru-To-WD", + "id": "danbooru2wd", + "reference": "https://github.com/RedRayz/ComfyUI-Danbooru-To-WD", + "files": [ + "https://github.com/RedRayz/ComfyUI-Danbooru-To-WD" + ], + "install_type": "git-clone", + "description": "Converts booru tags to a format suitable for Waifu Diffusion(or Danbooru based models)." + }, + { + "author": "Shibiko-AI", + "title": "Shibiko AI ComfyUI Tools", + "id": "shibiko-ai-tools", + "reference": "https://github.com/Shibiko-AI/ShibikoAI-ComfyUI-Tools", + "files": [ + "https://github.com/Shibiko-AI/ShibikoAI-ComfyUI-Tools" + ], + "install_type": "git-clone", + "description": "This is a collection of tools that I use to make my life easier when developing ComfyUI applications. It is a collection of tools that I have created to help me with my development process. I have decided to share these tools with the community in the hopes that they will be useful to others as well. I use this tools to further develop features for [a/https://shibiko.ai](https://shibiko.ai)" + }, + { + "author": "SaltAI", + "title": "SaltAI_AudioViz", + "id": "saltai-audioviz", + "reference": "https://github.com/get-salt-AI/SaltAI_AudioViz", + "files": [ + "https://github.com/get-salt-AI/SaltAI_AudioViz" + ], + "install_type": "git-clone", + "description": "SaltAI AudioViz contains ComfyUI nodes for generating complex audio reactive visualizations" + }, + { + "author": "SherryXieYuchen", + "title": "ComfyUI-Image-Inpainting", + "id": "image-inpainting", + "reference": "https://github.com/SherryXieYuchen/ComfyUI-Image-Inpainting", + "files": [ + "https://github.com/SherryXieYuchen/ComfyUI-Image-Inpainting" + ], + "install_type": "git-clone", + "description": "Nodes:VAE Encode Inpaint, VAE Decode Inpaint, ColorCorrection Inpaint, ImagePreprocess Inpaint, ImagePostprocess Inpaint, Load Model Inpaint, Inpainting (using Model)" + }, + { + "author": "zeroxoxo", + "title": "ComfyUI-Fast-Style-Transfer", + "id": "fast-style-transfer", + "reference": "https://github.com/zeroxoxo/ComfyUI-Fast-Style-Transfer", + "files": [ + "https://github.com/zeroxoxo/ComfyUI-Fast-Style-Transfer" + ], + "install_type": "git-clone", + "description": "ComfyUI node for fast neural style transfer. This is a simple conversion based on this: [a/https://github.com/rrmina/fast-neural-style-pytorch](https://github.com/rrmina/fast-neural-style-pytorch) Only basic inference functionality is ported for now." + }, + { + "author": "iwanders", + "title": "iwanders/ComfyUI_nodes", + "id": "iwanders-nodes", + "reference": "https://github.com/iwanders/ComfyUI_nodes", + "files": [ + "https://github.com/iwanders/ComfyUI_nodes" + ], + "install_type": "git-clone", + "description": "Nodes:IW SaveString, IW PrintString, IW ReplaceString, IW StringNode, IW StringConcat, IW TokenizerVocab, IW JsonPickItem." + }, + { + "author": "rhdunn", + "title": "comfyui-bus-plugin", + "id": "bus", + "reference": "https://github.com/rhdunn/comfyui-bus-plugin", + "files": [ + "https://github.com/rhdunn/comfyui-bus-plugin" + ], + "install_type": "git-clone", + "description": "A collection of nodes for rerouting multiple I/O lines together in a bus." + }, + { + "author": "hyunamy", + "title": "Comfy-UI on-complete-email-me", + "id": "hyunamy", + "reference": "https://github.com/hyunamy/comfy-ui-on-complete-email-me", + "files": [ + "https://github.com/hyunamy/comfy-ui-on-complete-email-me" + ], + "install_type": "git-clone", + "description": "A feature that sends an email via Gmail once image generation is completed in Comfy-ui." + }, + { + "author": "veighnsche", + "title": "comfyui_gr85", + "id": "gr85", + "reference": "https://github.com/veighnsche/comfyui_gr85", + "files": [ + "https://github.com/veighnsche/comfyui_gr85" + ], + "install_type": "git-clone", + "description": "Nodes:Image Dimension Resizer, Image Sizer, Random Ratio, Show Text, Random Title Character, Random Wildcard Tag Picker, Random Show Atm Loc Outfit, Contains Word, Elements Concatenator, ..." + }, + { + "author": "leiweiqiang", + "title": "ComfyUI-TRA", + "id": "tra", + "reference": "https://github.com/leiweiqiang/ComfyUI-TRA", + "files": [ + "https://github.com/leiweiqiang/ComfyUI-TRA" + ], + "install_type": "git-clone", + "description": "Nodes:TCL EbSynth, TCL Extract Frames (From File), TCL Extract Frames (From Video), TCL Combine Frames, TCL Save Video (From Frames)" + }, + { + "author": "hwhaocool", + "title": "ComfyUI-Select-Any", + "id": "select-any", + "reference": "https://github.com/hwhaocool/ComfyUI-Select-Any", + "files": [ + "https://github.com/hwhaocool/ComfyUI-Select-Any" + ], + "install_type": "git-clone", + "description": "a comfyui custom node, which can select value from inputs" + }, + { + "author": "mingqizhang", + "title": "ComfyUI_InSPyResNet_zmq", + "id": "inspy", + "reference": "https://github.com/mingqizhang/ComfyUI_InSPyResNet_zmq", + "files": [ + "https://github.com/mingqizhang/ComfyUI_InSPyResNet_zmq" + ], + "install_type": "git-clone", + "description": "Nodes:INSPY removebg ModelLoader, INSPY RMBG" + }, + { + "author": "GreenLandisaLie", + "title": "AuraSR-ComfyUI", + "id": "aurasr-greenlandisalie", + "reference": "https://github.com/GreenLandisaLie/AuraSR-ComfyUI", + "files": [ + "https://github.com/GreenLandisaLie/AuraSR-ComfyUI" + ], + "install_type": "git-clone", + "description": "ComfyUI implementation of [a/Aura-SR](https://github.com/fal-ai/aura-sr)" + }, + { + "author": "licyk", + "title": "ComfyUI-Restart-Sampler", + "id": "restart-sampler-licyk", + "reference": "https://github.com/licyk/ComfyUI-Restart-Sampler", + "files": [ + "https://github.com/licyk/ComfyUI-Restart-Sampler" + ], + "install_type": "git-clone", + "description": "This extension is a node that directly expands the functionality of KSampler, rather than being in the form of a custom node. [w/Workflows created using this feature are not compatible with other users.]" + }, + { + "author": "Fuou Marinas", + "title": "ComfyUI-FirstOrderMM", + "id": "fomm", + "reference": "https://github.com/FuouM/ComfyUI-FirstOrderMM", + "files": [ + "https://github.com/FuouM/ComfyUI-FirstOrderMM" + ], + "install_type": "git-clone", + "description": "Run [a/First Order Motion Model](https://github.com/AliaksandrSiarohin/first-order-model) for Image Animation in ComfyUI." + }, + { + "author": "my-opencode", + "title": "ComfyUI_IndustrialMagick", + "id": "industrialmagick", + "reference": "https://github.com/my-opencode/ComfyUI_IndustrialMagick", + "files": [ + "https://github.com/my-opencode/ComfyUI_IndustrialMagick" + ], + "install_type": "git-clone", + "description": "[a/ImageMagick](https://imagemagick.org/index.php) nodes for ComfyUI. Adds nodes to call ImageMagick subprocesses from ComfyUI.\nRequirements: [a/ImagMagick7](https://imagemagick.org/script/download.php), 'magick' command in your CLI environment." + }, + { + "author": "my-opencode", + "title": "ComfyUI_KSamplerTimer", + "id": "ksamplertimer", + "reference": "https://github.com/my-opencode/ComfyUI_KSamplerTimer", + "files": [ + "https://github.com/my-opencode/ComfyUI_KSamplerTimer" + ], + "install_type": "git-clone", + "description": "A custom node that returns the generation time of the KSampler. Intended for benchmarking or debugging." + }, + { + "author": "SEkINVR", + "title": "ComfyUI SaveAS", + "id": "saveas", + "reference": "https://github.com/SEkINVR/ComfyUI-SaveAs", + "files": [ + "https://github.com/SEkINVR/ComfyUI-SaveAs" + ], + "install_type": "git-clone", + "description": "This custom node for ComfyUI allows you to save images in multiple formats, including PNG, JPG, WebP, and ICO.\n[w/ComfyUI-Save-Multi-Format is renamed to SaveAs. Remove previous one and reinstall to this.]" + }, + { + "author": "MrSamSeen", + "title": "ComfyUI_SSStereoscope", + "id": "ssstereoscope", + "reference": "https://github.com/MrSamSeen/ComfyUI_SSStereoscope", + "files": [ + "https://github.com/MrSamSeen/ComfyUI_SSStereoscope" + ], + "install_type": "git-clone", + "description": "Side by Side 3D Stereoscope generation node for ComfyUI by SamSeen." + }, + { + "author": "jroc22", + "title": "ComfyUI-CSV-prompt-builder", + "id": "csv-prompt-builder", + "reference": "https://github.com/jroc22/ComfyUI-CSV-prompt-builder", + "files": [ + "https://github.com/jroc22/ComfyUI-CSV-prompt-builder" + ], + "install_type": "git-clone", + "description": "This is a simple node for creating prompts using a .csv file. I created this node as an easy way to output different prompts each time a workflow is run." + }, + { + "author": "DeJoker", + "title": "Pipeline Parallel ComfyUI", + "reference": "https://github.com/DeJoker/pipeline-parallel-comfy", + "files": [ + "https://github.com/DeJoker/pipeline-parallel-comfy" + ], + "install_type": "git-clone", + "description": "provide extra api to run prompt request with parallel execution of independent node" + }, + { + "author": "yiwangsimple", + "title": "comfy-groqchat", + "reference": "https://github.com/yiwangsimple/ComfyUI_GroqChat", + "files": [ + "https://github.com/yiwangsimple/ComfyUI_GroqChat" + ], + "install_type": "git-clone", + "description": "Content generation with open source models in comfyui via graq api implementation." + }, + { + "author": "Tritant", + "title": "ComfyUI-CreaPrompt", + "id": "creaprompt", + "reference": "https://github.com/tritant/ComfyUI_CreaPrompt", + "files": [ + "https://github.com/tritant/ComfyUI_CreaPrompt" + ], + "install_type": "git-clone", + "description": "Generate random prompts easily." + }, + { + "author": "metncelik", + "title": "comfyui_met_suite", + "reference": "https://github.com/metncelik/comfyui_met_suite", + "files": [ + "https://github.com/metncelik/comfyui_met_suite" + ], + "install_type": "git-clone", + "description": "Nodes: Primitive BBOX, BBOX Padding, BBOX Resize, ImageResize KeepRatio." + }, + { + "author": "Smuzzies", + "title": "comfyui_meme_maker", + "reference": "https://github.com/Smuzzies/comfyui_meme_maker", + "files": [ + "https://github.com/Smuzzies/comfyui_meme_maker" + ], + "install_type": "git-clone", + "description": "Meme Maker Node for ComfyUI." + }, + { + "author": "bluevisor", + "title": "ComfyUI_PS_Blend_Node", + "reference": "https://github.com/bluevisor/ComfyUI_PS_Blend_Node", + "files": [ + "https://github.com/bluevisor/ComfyUI_PS_Blend_Node" + ], + "install_type": "git-clone", + "description": "This repository contains a simple custom node for ComfyUI that implements familiar PS-style blend modes using PyTorch. The PSBlendNode allows you to blend two images together using a variety of blend modes and an opacity parameter." + }, + { + "author": "Grant-CP", + "title": "ComfyUI-LivePortraitKJ-MPS", + "reference": "https://github.com/Grant-CP/ComfyUI-LivePortraitKJ-MPS", + "files": [ + "https://github.com/Grant-CP/ComfyUI-LivePortraitKJ-MPS" + ], + "install_type": "git-clone", + "description": "If you wish to incorporate these changes into your repo, feel free to open an issue and ask. The commits should be pretty clear, and I also label almost all changes with #HACK so a full text search will work too.\nPlease let me know if you decide to incorporate any of these changes into your LivePortrait implementation so I can direct people to you repository. I do not intend to maintain this repo.\nSome operations are simply not supported on MPS and I didn't rewrite them. Most of my changes are just to .cuda calls and that sort of thing. Many operations are still done on CPU, so don't expect awesome performance." + }, + { + "author": "wTechArtist", + "title": "ComfyUI-CustomNodes", + "reference": "https://github.com/wTechArtist/ComfyUI-CustomNodes", + "files": [ + "https://github.com/wTechArtist/ComfyUI-CustomNodes" + ], + "install_type": "git-clone", + "description": "Nodes:Image Blending Mode Mask" + }, + { + "author": "mullakhmetov", + "title": "comfyui_dynamic_util_nodes", + "reference": "https://github.com/mullakhmetov/comfyui_dynamic_util_nodes", + "files": [ + "https://github.com/mullakhmetov/comfyui_dynamic_util_nodes" + ], + "install_type": "git-clone", + "description": "ComfyS3 helpful util nodes for dynamic workflows" + }, + { + "author": "HECer", + "title": "ComfyUI-FilePathCreator", + "reference": "https://github.com/HECer/ComfyUI-FilePathCreator", + "files": [ + "https://github.com/HECer/ComfyUI-FilePathCreator" + ], + "install_type": "git-clone", + "description": "The ComfyUI-FilePathCreator is a custom node extension for ComfyUI designed to generate dynamic filenames based on user-defined parameters. This node helps streamline the process of creating organized and timestamped filenames, ideal for saving output files in a structured manner." + }, + { + "author": "adigayung", + "title": "ComfyUI-Translator", + "reference": "https://github.com/adigayung/ComfyUI-Translator", + "files": [ + "https://github.com/adigayung/ComfyUI-Translator" + ], + "install_type": "git-clone", + "description": "Auto translate all languages ​​to english" + }, + { + "author": "ZZXYWQ", + "title": "ZZX Nodes", + "id": "ZZXYWQ", + "reference": "https://github.com/ZZXYWQ/ComfyUI-ZZXYWQ", + "files": [ + "https://github.com/ZZXYWQ/ComfyUI-ZZXYWQ" + ], + "install_type": "git-clone", + "description": "Node(s): VideoFormatConverter(VFC)" + }, + + + + + + + + { + "author": "Ser-Hilary", + "title": "SDXL_sizing", + "reference": "https://github.com/Ser-Hilary/SDXL_sizing", + "files": [ + "https://github.com/Ser-Hilary/SDXL_sizing/raw/main/conditioning_sizing_for_SDXL.py" + ], + "install_type": "copy", + "description": "Nodes:sizing_node. Size calculation node related to image size in prompts supported by SDXL." + }, + { + "author": "ailex000", + "title": "Image Gallery", + "reference": "https://github.com/ailex000/ComfyUI-Extensions", + "js_path": "image-gallery", + "files": [ + "https://github.com/ailex000/ComfyUI-Extensions/raw/main/image-gallery/imageGallery.js" + ], + "install_type": "copy", + "description": "Custom javascript extensions for better UX for ComfyUI. Supported nodes: PreviewImage, SaveImage. Double click on image to open." + }, + { + "author": "rock-land", + "title": "graphNavigator", + "reference": "https://github.com/rock-land/graphNavigator", + "js_path": "graphNavigator", + "files": [ + "https://github.com/rock-land/graphNavigator/raw/main/graphNavigator/graphNavigator.js" + ], + "install_type": "copy", + "description": "ComfyUI Web Extension for saving views and navigating graphs." + }, + { + "author": "diffus3", + "title": "diffus3/ComfyUI-extensions", + "reference": "https://github.com/diffus3/ComfyUI-extensions", + "js_path": "diffus3", + "files": [ + "https://github.com/diffus3/ComfyUI-extensions/raw/main/multiReroute/multireroute.js", + "https://github.com/diffus3/ComfyUI-extensions/raw/main/setget/setget.js" + ], + "install_type": "copy", + "description": "Extensions: subgraph, setget, multiReroute" + }, + { + "author": "m957ymj75urz", + "title": "m957ymj75urz/ComfyUI-Custom-Nodes", + "reference": "https://github.com/m957ymj75urz/ComfyUI-Custom-Nodes", + "js_path": "m957ymj75urz", + "files": [ + "https://github.com/m957ymj75urz/ComfyUI-Custom-Nodes/raw/main/clip-text-encode-split/clip_text_encode_split.py", + "https://github.com/m957ymj75urz/ComfyUI-Custom-Nodes/raw/main/colors/colors.js" + ], + "install_type": "copy", + "description": "Nodes: RawText, RawTextCLIPEncode, RawTextCombine, RawTextReplace, Extension: m957ymj75urz.colors" + }, + { + "author": "Bikecicle", + "title": "Waveform Extensions", + "reference": "https://github.com/Bikecicle/ComfyUI-Waveform-Extensions", + "files": [ + "https://github.com/Bikecicle/ComfyUI-Waveform-Extensions/raw/main/EXT_AudioManipulation.py", + "https://github.com/Bikecicle/ComfyUI-Waveform-Extensions/raw/main/EXT_VariationUtils.py" + ], + "install_type": "copy", + "description": "Some additional audio utilites for use on top of Sample Diffusion ComfyUI Extension" + }, + { + "author": "dawangraoming", + "title": "KSampler GPU", + "reference": "https://github.com/dawangraoming/ComfyUI_ksampler_gpu", + "files": [ + "https://github.com/dawangraoming/ComfyUI_ksampler_gpu/raw/main/ksampler_gpu.py" + ], + "install_type": "copy", + "description": "KSampler is provided, based on GPU random noise" + }, + { + "author": "fitCorder", + "title": "fcSuite", + "reference": "https://github.com/fitCorder/fcSuite", + "files": [ + "https://github.com/fitCorder/fcSuite/raw/main/fcSuite.py" + ], + "install_type": "copy", + "description": "fcFloatMatic is a custom module, that when configured correctly will increment through the lines generating you loras at different strengths. The JSON file will load the config." + }, + { + "author": "lrzjason", + "title": "ComfyUIJasonNode", + "reference": "https://github.com/lrzjason/ComfyUIJasonNode", + "files": [ + "https://github.com/lrzjason/ComfyUIJasonNode/raw/main/SDXLMixSampler.py", + "https://github.com/lrzjason/ComfyUIJasonNode/raw/main/LatentByRatio.py", + "" + ], + "install_type": "copy", + "description": "Nodes:SDXLMixSampler, LatentByRatio" + }, + { + "author": "lordgasmic", + "title": "Wildcards", + "reference": "https://github.com/lordgasmic/ComfyUI-Wildcards", + "files": [ + "https://github.com/lordgasmic/ComfyUI-Wildcards/raw/master/wildcards.py" + ], + "install_type": "copy", + "description": "Nodes:CLIPTextEncodeWithWildcards. This wildcard node is a wildcard node that operates based on the seed." + }, + { + "author": "throttlekitty", + "title": "SDXLCustomAspectRatio", + "reference": "https://github.com/throttlekitty/SDXLCustomAspectRatio", + "files": [ + "https://raw.githubusercontent.com/throttlekitty/SDXLCustomAspectRatio/main/SDXLAspectRatio.py" + ], + "install_type": "copy", + "description": "A quick and easy ComfyUI custom node for setting SDXL-friendly aspect ratios." + }, + { + "author": "s1dlx", + "title": "comfy_meh", + "reference": "https://github.com/s1dlx/comfy_meh", + "files": [ + "https://github.com/s1dlx/comfy_meh/raw/main/meh.py" + ], + "install_type": "copy", + "description": "Advanced merging methods." + }, + { + "author": "tudal", + "title": "Hakkun-ComfyUI-nodes", + "reference": "https://github.com/tudal/Hakkun-ComfyUI-nodes", + "files": [ + "https://github.com/tudal/Hakkun-ComfyUI-nodes/raw/main/hakkun_nodes.py" + ], + "install_type": "copy", + "description": "Nodes: Prompt parser. ComfyUI extra nodes. Mostly prompt parsing." + }, + { + "author": "SadaleNet", + "title": "ComfyUI A1111-like Prompt Custom Node Solution", + "reference": "https://github.com/SadaleNet/CLIPTextEncodeA1111-ComfyUI", + "files": [ + "https://github.com/SadaleNet/CLIPTextEncodeA1111-ComfyUI/raw/master/custom_nodes/clip_text_encoder_a1111.py" + ], + "install_type": "copy", + "description": "Nodes: CLIPTextEncodeA1111, RerouteTextForCLIPTextEncodeA1111." + }, + { + "author": "wsippel", + "title": "SDXLResolutionPresets", + "reference": "https://github.com/wsippel/comfyui_ws", + "files": [ + "https://github.com/wsippel/comfyui_ws/raw/main/sdxl_utility.py" + ], + "install_type": "copy", + "description": "Nodes: SDXLResolutionPresets. Easy access to the officially supported resolutions, in both horizontal and vertical formats: 1024x1024, 1152x896, 1216x832, 1344x768, 1536x640" + }, + { + "author": "nicolai256", + "title": "comfyUI_Nodes_nicolai256", + "id": "nicoali256", + "reference": "https://github.com/nicolai256/comfyUI_Nodes_nicolai256", + "files": [ + "https://github.com/nicolai256/comfyUI_Nodes_nicolai256/raw/main/yugioh-presets.py" + ], + "install_type": "copy", + "description": "Nodes: yugioh_Presets. by Nicolai256 inspired by throttlekitty SDXLAspectRatio" + }, + { + "author": "Onierous", + "title": "QRNG_Node_ComfyUI", + "id": "qrng", + "reference": "https://github.com/Onierous/QRNG_Node_ComfyUI", + "files": [ + "https://github.com/Onierous/QRNG_Node_ComfyUI/raw/main/qrng_node.py" + ], + "install_type": "copy", + "description": "Nodes: QRNG Node CSV. A node that takes in an array of random numbers from the ANU QRNG API and stores them locally for generating quantum random number noise_seeds in ComfyUI" + }, + { + "author": "ntdviet", + "title": "ntdviet/comfyui-ext", + "reference": "https://github.com/ntdviet/comfyui-ext", + "files": [ + "https://github.com/ntdviet/comfyui-ext/raw/main/custom_nodes/gcLatentTunnel/gcLatentTunnel.py" + ], + "install_type": "copy", + "description": "Nodes:LatentGarbageCollector. This ComfyUI custom node flushes the GPU cache and empty cuda interprocess memory. It's helpfull for low memory environment such as the free Google Colab, especially when the workflow VAE decode latents of the size above 1500x1500." + }, + { + "author": "alkemann", + "title": "alkemann nodes", + "id": "alkemann", + "reference": "https://gist.github.com/alkemann/7361b8eb966f29c8238fd323409efb68", + "files": [ + "https://gist.github.com/alkemann/7361b8eb966f29c8238fd323409efb68/raw/f9605be0b38d38d3e3a2988f89248ff557010076/alkemann.py" + ], + "install_type": "copy", + "description": "Nodes:Int to Text, Seed With Text, Save A1 Image." + }, + { + "author": "catscandrive", + "title": "Image loader with subfolders", + "id": "imgsubfolders", + "reference": "https://github.com/catscandrive/comfyui-imagesubfolders", + "files": [ + "https://github.com/catscandrive/comfyui-imagesubfolders/raw/main/loadImageWithSubfolders.py" + ], + "install_type": "copy", + "description": "Adds an Image Loader node that also shows images in subfolders of the default input directory" + }, + { + "author": "Smuzzies", + "title": "Chatbox Overlay node for ComfyUI", + "id": "chatbox-overlay", + "reference": "https://github.com/Smuzzies/comfyui_chatbox_overlay", + "files": [ + "https://github.com/Smuzzies/comfyui_chatbox_overlay/raw/main/chatbox_overlay.py" + ], + "install_type": "copy", + "description": "Nodes: Chatbox Overlay. Custom node for ComfyUI to add a text box over a processed image before save node." + }, + { + "author": "CaptainGrock", + "title": "ComfyUIInvisibleWatermark", + "id": "invisible-watermark-grock", + "reference": "https://github.com/CaptainGrock/ComfyUIInvisibleWatermark", + "files": [ + "https://github.com/CaptainGrock/ComfyUIInvisibleWatermark/raw/main/Invisible%20Watermark.py" + ], + "install_type": "copy", + "description": "Nodes:Apply Invisible Watermark, Extract Watermark. Adds up to 12 characters encoded into an image that can be extracted." + }, + { + "author": "fearnworks", + "title": "Fearnworks Custom Nodes", + "id": "fearnworks", + "reference": "https://github.com/fearnworks/ComfyUI_FearnworksNodes", + "files": [ + "https://github.com/fearnworks/ComfyUI_FearnworksNodes/raw/main/fw_nodes.py" + ], + "install_type": "copy", + "description": "A collection of ComfyUI nodes. These nodes are tailored for specific tasks, such as counting files in directories and sorting text segments based on token counts. Currently this is only tested on SDXL 1.0 models. An additional swich is needed to hand 1.x" + }, + { + "author": "LZC", + "title": "Hayo comfyui nodes", + "id": "lzcnodes", + "reference": "https://github.com/1shadow1/hayo_comfyui_nodes", + "files": [ + "https://github.com/1shadow1/hayo_comfyui_nodes/raw/main/LZCNodes.py" + ], + "install_type": "copy", + "description": "Nodes:tensor_trans_pil, Make Transparent mask, MergeImages, words_generatee, load_PIL image" + }, + { + "author": "underclockeddev", + "title": "Preview Subselection Node for ComfyUI", + "id": "preview-subselection", + "reference": "https://github.com/underclockeddev/ComfyUI-PreviewSubselection-Node", + "files": [ + "https://github.com/underclockeddev/ComfyUI-PreviewSubselection-Node/raw/master/preview_subselection.py" + ], + "install_type": "copy", + "description": "A node which takes in x, y, width, height, total width, and total height, in order to accurately represent the area of an image which is covered by area-based conditioning." + }, + { + "author": "underclockeddev", + "title": "BrevImage", + "id": "brevimage", + "reference": "https://github.com/bkunbargi/BrevImage", + "files": [ + "https://github.com/bkunbargi/BrevImage/raw/main/BrevLoadImage.py" + ], + "install_type": "copy", + "description": "Nodes:BrevImage. ComfyUI Load Image From URL" + }, + { + "author": "jw782cn", + "title": "ComfyUI-Catcat", + "id": "catcat", + "reference": "https://github.com/jw782cn/ComfyUI-Catcat", + "files": [ + "https://github.com/jw782cn/ComfyUI-Catcat" + ], + "install_type": "copy", + "description": "Extension to show random cat GIFs while queueing prompt." + }, + { + "author": "barckley75", + "title": "comfyUI_DaVinciResolve", + "reference": "https://github.com/barckley75/comfyUI_DaVinciResolve", + "files": [ + "https://github.com/barckley75/comfyUI_DaVinciResolve/raw/main/custom_nodes/node_text_to_speech.py", + "https://github.com/barckley75/comfyUI_DaVinciResolve/raw/main/custom_nodes/nodes_phy_3_contitioning.py", + "https://github.com/barckley75/comfyUI_DaVinciResolve/raw/main/custom_nodes/save_audio_to_davinci.py", + "https://github.com/barckley75/comfyUI_DaVinciResolve/raw/main/custom_nodes/save_image_to_davinci.py" + ], + "install_type": "copy", + "description": "Nodes:TextToSpeech, phy_3_conditioning, SaveAudioToDaVinci, SaveImageToDaVinci.\nNOTE:In order to use DaVinci node you must have DaVinci Resolve Studio connected to the API. For more information check the help seciton in DaVinci Resolve Studio HELP>DOCUMENTATION>DEVELOPER. It will open a folder, search for scripting and the for README.txt file, the API documentation." + }, + { + "author": "DannyStone1999", + "title": "ComfyUI-Depth2Mask", + "reference": "https://github.com/DannyStone1999/ComfyUI-Depth2Mask", + "files": [ + "https://github.com/DannyStone1999/ComfyUI-Depth2Mask/raw/main/Depth2Mask.py" + ], + "install_type": "copy", + "description": "Nodes:Depth2Mask" + }, + { + "author": "Limbicnation", + "title": "ComfyUIDepthEstimation", + "reference": "https://github.com/Limbicnation/ComfyUIDepthEstimation", + "files": [ + "https://github.com/Limbicnation/ComfyUIDepthEstimation/raw/main/depth_estimation_node.py" + ], + "pip": ["transformers"], + "install_type": "copy", + "description": "A custom depth estimation node for ComfyUI using transformer models. It integrates depth estimation with automatic gamma correction, contrast adjustment, and edge detection, based on the [a/TransformDepth](https://github.com/Limbicnation/TransformDepth) repository." + }, + { + "author": "seghier", + "title": "ComfyUI_LibreTranslate", + "reference": "https://github.com/seghier/ComfyUI_LibreTranslate", + "files": [ + "https://github.com/seghier/ComfyUI_LibreTranslate/raw/main/translate_node.py" + ], + "install_type": "copy", + "description": "Use LibreTranslation in ComfyUI [a/https://github.com/LibreTranslate/LibreTranslate](https://github.com/LibreTranslate/LibreTranslate)" + }, + { + "author": "ImmortalPie", + "title": "PonySwitch Node", + "reference": "https://github.com/ImmortalPie/ComfyUI-PonySwitch", + "files": [ + "https://github.com/ImmortalPie/ComfyUI-PonySwitch/raw/main/PonySwitch.py" + ], + "install_type": "copy", + "description": "The PonySwitch node is a custom node for ComfyUI that modifies prompts based on a toggle switch and adds configurable pony tags." + }, + { + "author": "theally", + "title": "TheAlly's Custom Nodes", + "id": "ally", + "reference": "https://civitai.com/models/19625?modelVersionId=23296", + "files": [ + "https://civitai.com/api/download/models/25114", + "https://civitai.com/api/download/models/24679", + "https://civitai.com/api/download/models/24154", + "https://civitai.com/api/download/models/23884", + "https://civitai.com/api/download/models/23649", + "https://civitai.com/api/download/models/23467", + "https://civitai.com/api/download/models/23296" + ], + "install_type": "unzip", + "description": "Custom nodes for ComfyUI by TheAlly." + }, + { + "author": "xss", + "title": "Custom Nodes by xss", + "id": "xss", + "reference": "https://civitai.com/models/24869/comfyui-custom-nodes-by-xss", + "files": [ + "https://civitai.com/api/download/models/32717", + "https://civitai.com/api/download/models/47776", + "https://civitai.com/api/download/models/29772", + "https://civitai.com/api/download/models/31618", + "https://civitai.com/api/download/models/31591", + "https://civitai.com/api/download/models/29773", + "https://civitai.com/api/download/models/29774", + "https://civitai.com/api/download/models/29755", + "https://civitai.com/api/download/models/29750" + ], + "install_type": "unzip", + "description": "Various image processing nodes." + }, + { + "author": "aimingfail", + "title": "Image2Halftone Node for ComfyUI", + "id": "img2halftone", + "reference": "https://civitai.com/models/143293/image2halftone-node-for-comfyui", + "files": [ + "https://civitai.com/api/download/models/158997" + ], + "install_type": "unzip", + "description": "This is a node to convert an image into a CMYK Halftone dot image." + } + ] +} diff --git a/custom_nodes/ComfyUI-Manager/docs/en/cm-cli.md b/custom_nodes/ComfyUI-Manager/docs/en/cm-cli.md new file mode 100644 index 000000000..e5158be84 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/docs/en/cm-cli.md @@ -0,0 +1,146 @@ +# `cm-cli`: ComfyUI-Manager CLI + +`cm-cli` is a tool that allows you to use various functions of ComfyUI-Manager from the command line without launching ComfyUI. + + +``` +-= ComfyUI-Manager CLI (V2.24) =- + + +python cm-cli.py [OPTIONS] + +OPTIONS: + [install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel ] ?[--mode [remote|local|cache]] + [update|disable|enable|fix] all ?[--channel ] ?[--mode [remote|local|cache]] + [simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel ] ?[--mode [remote|local|cache]] + save-snapshot ?[--output ] + restore-snapshot ?[--pip-non-url] ?[--pip-non-local-url] ?[--pip-local-url] + cli-only-mode [enable|disable] + restore-dependencies + clear +``` + +## How To Use? +* You can execute it via `python cm-cli.py`. +* For example, if you want to update all custom nodes: + * In the ComfyUI-Manager directory, you can execute the command `python cm-cli.py update all`. + * If running from the ComfyUI directory, you can specify the path to cm-cli.py like this: `python custom_nodes/ComfyUI-Manager/cm-cli.py update all`. + +## Prerequisite +* It must be run in the same Python environment as the one running ComfyUI. + * If using a venv, you must run it with the venv activated. + * If using a portable version, and you are in the directory with the run_nvidia_gpu.bat file, you should execute the command as follows: + `.\python_embeded\python.exe ComfyUI\custom_nodes\ComfyUI-Manager\cm-cli.py update all` +* The path for ComfyUI can be set with the COMFYUI_PATH environment variable. If omitted, a warning message will appear, and the path will be set relative to the installed location of ComfyUI-Manager: + ``` + WARN: The `COMFYUI_PATH` environment variable is not set. Assuming `custom_nodes/ComfyUI-Manager/../../` as the ComfyUI path. + ``` + +## Features + +### 1. --channel, --mode +* For viewing information and managing custom nodes, you can set the information database through --channel and --mode. +* For instance, executing the command `python cm-cli.py update all --channel recent --mode remote` will operate based on the latest information from remote rather than local data embedded in the current ComfyUI-Manager repo and will only target the list in the recent channel. +* --channel, --mode are only available with the commands `simple-show, show, install, uninstall, update, disable, enable, fix`. + +### 2. Viewing Management Information + +`[simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel ] ?[--mode [remote|local|cache]]` + +* `[show|simple-show]` - `show` provides detailed information, while `simple-show` displays information more simply. + +Executing a command like `python cm-cli.py show installed` will display detailed information about the installed custom nodes. + +``` +-= ComfyUI-Manager CLI (V2.24) =- + +FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json +[ ENABLED ] ComfyUI-Manager (author: Dr.Lt.Data) +[ ENABLED ] ComfyUI-Impact-Pack (author: Dr.Lt.Data) +[ ENABLED ] ComfyUI-Inspire-Pack (author: Dr.Lt.Data) +[ ENABLED ] ComfyUI_experiments (author: comfyanonymous) +[ ENABLED ] ComfyUI-SAI_API (author: Stability-AI) +[ ENABLED ] stability-ComfyUI-nodes (author: Stability-AI) +[ ENABLED ] comfyui_controlnet_aux (author: Fannovel16) +[ ENABLED ] ComfyUI-Frame-Interpolation (author: Fannovel16) +[ DISABLED ] ComfyUI-Loopchain (author: Fannovel16) +``` + +Using a command like `python cm-cli.py simple-show installed` will simply display information about the installed custom nodes. + +``` +-= ComfyUI-Manager CLI (V2.24) =- + +FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json +ComfyUI-Manager +ComfyUI-Impact-Pack +ComfyUI-Inspire-Pack +ComfyUI_experiments +ComfyUI-SAI_API +stability-ComfyUI-nodes +comfyui_controlnet_aux +ComfyUI-Frame-Interpolation +ComfyUI-Loopchain +``` + +`[installed|enabled|not-installed|disabled|all|snapshot|snapshot-list]` + * `enabled`, `disabled`: Shows nodes that have been enabled or disabled among the installed custom nodes. + * `installed`: Shows all nodes that have been installed, regardless of whether they are enabled or disabled. + * `not-installed`: Shows a list of custom nodes that have not been installed. + * `all`: Shows a list of all custom nodes. + * `snapshot`: Displays snapshot information of the currently installed custom nodes. When viewed with `show`, it is displayed in JSON format, and with `simple-show`, it is displayed simply, along with the commit hash. + * `snapshot-list`: Shows a list of snapshot files stored in ComfyUI-Manager/snapshots. + +### 3. Managing Custom Nodes + +`[install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel ] ?[--mode [remote|local|cache]]` + +* You can apply management functions by listing the names of custom nodes, such as `python cm-cli.py install ComfyUI-Impact-Pack ComfyUI-Inspire-Pack ComfyUI_experiments`. +* The names of the custom nodes are as shown by `show` and are the names of the git repositories. +(Plans are to update the use of nicknames in the future.) + +`[update|disable|enable|fix] all ?[--channel ] ?[--mode [remote|local|cache]]` + +* The `update, disable, enable, fix` functions can be specified for all. + +* Detailed Operations + * `install`: Installs the specified custom nodes. + * `reinstall`: Removes and then reinstalls the specified custom nodes. + * `uninstall`: Uninstalls the specified custom nodes. + * `update`: Updates the specified custom nodes. + * `disable`: Disables the specified custom nodes. + * `enable`: Enables the specified custom nodes. + * `fix`: Attempts to fix dependencies for the specified custom nodes. + + +### 4. Snapshot Management +* `python cm-cli.py save-snapshot [--output ]`: Saves the current snapshot. + * With `--output`, you can save a file in .yaml format to any specified path. +* `python cm-cli.py restore-snapshot `: Restores to the specified snapshot. + * If a file exists at the snapshot path, that snapshot is loaded. + * If no file exists at the snapshot path, it is implicitly assumed to be in ComfyUI-Manager/snapshots. + * `--pip-non-url`: Restore for pip packages registered on PyPI. + * `--pip-non-local-url`: Restore for pip packages registered at web URLs. + * `--pip-local-url`: Restore for pip packages specified by local paths. + + +### 5. CLI Only Mode + +You can set whether to use ComfyUI-Manager solely via CLI. + +`cli-only-mode [enable|disable]` + +* This mode can be used if you want to restrict the use of ComfyUI-Manager through the GUI for security or policy reasons. + * When CLI only mode is enabled, ComfyUI-Manager is loaded in a very restricted state, the internal web API is disabled, and the Manager button is not displayed in the main menu. + +### 6. Dependency Restoration + +`restore-dependencies` + +* This command can be used if custom nodes are installed under the `ComfyUI/custom_nodes` path but their dependencies are not installed. +* It is useful when starting a new cloud instance, like colab, where dependencies need to be reinstalled and installation scripts re-executed. +* It can also be utilized if ComfyUI is reinstalled and only the custom_nodes path has been backed up and restored. + +### 7. Clear + +In the GUI, installations, updates, or snapshot restorations are scheduled to execute the next time ComfyUI is launched. The `clear` command clears this scheduled state, ensuring no pre-execution actions are applied. \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/docs/en/use_aria2.md b/custom_nodes/ComfyUI-Manager/docs/en/use_aria2.md new file mode 100644 index 000000000..10a7c6dd5 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/docs/en/use_aria2.md @@ -0,0 +1,40 @@ +# Use `aria2` as downloader + +Two environment variables are needed to use `aria2` as the downloader. + +```bash +export COMFYUI_MANAGER_ARIA2_SERVER=http://127.0.0.1:6800 +export COMFYUI_MANAGER_ARIA2_SECRET=__YOU_MUST_CHANGE_IT__ +``` + +An example `docker-compose.yml` + +```yaml +services: + + aria2: + container_name: aria2 + image: p3terx/aria2-pro + environment: + - PUID=1000 + - PGID=1000 + - UMASK_SET=022 + - RPC_SECRET=__YOU_MUST_CHANGE_IT__ + - RPC_PORT=5080 + - DISK_CACHE=64M + - IPV6_MODE=false + - UPDATE_TRACKERS=false + - CUSTOM_TRACKER_URL= + volumes: + - ./config:/config + - ./downloads:/downloads + - ~/ComfyUI/models:/models + - ~/ComfyUI/custom_nodes:/custom_nodes + ports: + - 6800:6800 + restart: unless-stopped + logging: + driver: json-file + options: + max-size: 1m +``` diff --git a/custom_nodes/ComfyUI-Manager/docs/ko/cm-cli.md b/custom_nodes/ComfyUI-Manager/docs/ko/cm-cli.md new file mode 100644 index 000000000..33860f6b2 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/docs/ko/cm-cli.md @@ -0,0 +1,149 @@ +# `cm-cli`: ComfyUI-Manager CLI + +`cm-cli` 는 ComfyUI를 실행시키지 않고 command line에서 ComfyUI-Manager의 여러가지 기능을 사용할 수 있도록 도와주는 도구입니다. + + +``` +-= ComfyUI-Manager CLI (V2.24) =- + + +python cm-cli.py [OPTIONS] + +OPTIONS: + [install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel ] ?[--mode [remote|local|cache]] + [update|disable|enable|fix] all ?[--channel ] ?[--mode [remote|local|cache]] + [simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel ] ?[--mode [remote|local|cache]] + save-snapshot ?[--output ] + restore-snapshot ?[--pip-non-url] ?[--pip-non-local-url] ?[--pip-local-url] + cli-only-mode [enable|disable] + restore-dependencies + clear +``` + +## How To Use? +* `python cm-cli.py` 를 통해서 실행 시킬 수 있습니다. +* 예를 들어 custom node를 모두 업데이트 하고 싶다면 + * ComfyUI-Manager경로 에서 `python cm-cli.py update all` 를 command를 실행할 수 있습니다. + * ComfyUI 경로에서 실행한다면, `python custom_nodes/ComfyUI-Manager/cm-cli.py update all` 와 같이 cm-cli.py 의 경로를 지정할 수도 있습니다. + +## Prerequisite +* ComfyUI 를 실행하는 python과 동일한 python 환경에서 실행해야 합니다. + * venv를 사용할 경우 해당 venv를 activate 한 상태에서 실행해야 합니다. + * portable 버전을 사용할 경우 run_nvidia_gpu.bat 파일이 있는 경로인 경우, 다음과 같은 방식으로 코맨드를 실행해야 합니다. + `.\python_embeded\python.exe ComfyUI\custom_nodes\ComfyUI-Manager\cm-cli.py update all` +* ComfyUI 의 경로는 COMFYUI_PATH 환경 변수로 설정할 수 있습니다. 만약 생략할 경우 다음과 같은 경고 메시지가 나타나며, ComfyUI-Manager가 설치된 경로를 기준으로 상대 경로로 설정됩니다. + ``` + WARN: The `COMFYUI_PATH` environment variable is not set. Assuming `custom_nodes/ComfyUI-Manager/../../` as the ComfyUI path. + ``` + +## Features + +### 1. --channel, --mode +* 정보 보기 기능과 커스텀 노드 관리 기능의 경우는 --channel과 --mode를 통해 정보 DB를 설정할 수 있습니다. +* 예들 들어 `python cm-cli.py update all --channel recent --mode remote`와 같은 command를 실행할 경우, 현재 ComfyUI-Manager repo에 내장된 로컬의 정보가 아닌 remote의 최신 정보를 기준으로 동작하며, recent channel에 있는 목록을 대상으로만 동작합니다. +* --channel, --mode 는 `simple-show, show, install, uninstall, update, disable, enable, fix` command에서만 사용 가능합니다. + +### 2. 관리 정보 보기 + +`[simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel ] ?[--mode [remote|local|cache]]` + + +* `[show|simple-show]` - `show`는 상세하게 정보를 보여주며, `simple-show`는 간단하게 정보를 보여줍니다. + + +`python cm-cli.py show installed` 와 같은 코맨드를 실행하면 설치된 커스텀 노드의 정보를 상세하게 보여줍니다. +``` +-= ComfyUI-Manager CLI (V2.24) =- + +FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json +[ ENABLED ] ComfyUI-Manager (author: Dr.Lt.Data) +[ ENABLED ] ComfyUI-Impact-Pack (author: Dr.Lt.Data) +[ ENABLED ] ComfyUI-Inspire-Pack (author: Dr.Lt.Data) +[ ENABLED ] ComfyUI_experiments (author: comfyanonymous) +[ ENABLED ] ComfyUI-SAI_API (author: Stability-AI) +[ ENABLED ] stability-ComfyUI-nodes (author: Stability-AI) +[ ENABLED ] comfyui_controlnet_aux (author: Fannovel16) +[ ENABLED ] ComfyUI-Frame-Interpolation (author: Fannovel16) +[ DISABLED ] ComfyUI-Loopchain (author: Fannovel16) +``` + +`python cm-cli.py simple-show installed` 와 같은 코맨드를 이용해서 설치된 커스텀 노드의 정보를 간단하게 보여줍니다. + +``` +-= ComfyUI-Manager CLI (V2.24) =- + +FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json +ComfyUI-Manager +ComfyUI-Impact-Pack +ComfyUI-Inspire-Pack +ComfyUI_experiments +ComfyUI-SAI_API +stability-ComfyUI-nodes +comfyui_controlnet_aux +ComfyUI-Frame-Interpolation +ComfyUI-Loopchain +``` + +* `[installed|enabled|not-installed|disabled|all|snapshot|snapshot-list]` + * `enabled`, `disabled`: 설치된 커스텀 노드들 중 enable 되었거나, disable된 노드들을 보여줍니다. + * `installed`: enable, disable 여부와 상관없이 설치된 모든 노드를 보여줍니다 + * `not-installed`: 설치되지 않은 커스텀 노드의 목록을 보여줍니다. + * `all`: 모든 커스텀 노드의 목록을 보여줍니다. + * `snapshot`: 현재 설치된 커스텀 노드의 snapshot 정보를 보여줍니다. `show`롤 통해서 볼 경우는 json 출력 형태로 보여주며, `simple-show`를 통해서 볼 경우는 간단하게, 커밋 해시와 함께 보여줍니다. + * `snapshot-list`: ComfyUI-Manager/snapshots 에 저장된 snapshot 파일의 목록을 보여줍니다. + +### 3. 커스텀 노드 관리 하기 + +`[install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel ] ?[--mode [remote|local|cache]]` + +* `python cm-cli.py install ComfyUI-Impact-Pack ComfyUI-Inspire-Pack ComfyUI_experiments` 와 같이 커스텀 노드의 이름을 나열해서 관리 기능을 적용할 수 있습니다. +* 커스텀 노드의 이름은 `show`를 했을 때 보여주는 이름이며, git repository의 이름입니다. +(추후 nickname 을 사용가능하돌고 업데이트 할 예정입니다.) + +`[update|disable|enable|fix] all ?[--channel ] ?[--mode [remote|local|cache]]` + +* `update, disable, enable, fix` 기능은 all 로 지정 가능합니다. + +* 세부 동작 + * `install`: 지정된 커스텀 노드들을 설치합니다 + * `reinstall`: 지정된 커스텀 노드를 삭제하고 재설치 합니다. + * `uninstall`: 지정된 커스텀 노드들을 삭제합니다. + * `update`: 지정된 커스텀 노드들을 업데이트합니다. + * `disable`: 지정된 커스텀 노드들을 비활성화합니다. + * `enable`: 지정된 커스텀 노드들을 활성화합니다. + * `fix`: 지정된 커스텀 노드의 의존성을 고치기 위한 시도를 합니다. + + +### 4. 스냅샷 관리 기능 +* `python cm-cli.py save-snapshot ?[--output ]`: 현재의 snapshot을 저장합니다. + * --output 으로 임의의 경로에 .yaml 파일과 format으로 저장할 수 있습니다. +* `python cm-cli.py restore-snapshot `: 지정된 snapshot으로 복구합니다. + * snapshot 경로에 파일이 존재하는 경우 해당 snapshot을 로드합니다. + * snapshot 경로에 파일이 존재하지 않는 경우 묵시적으로, ComfyUI-Manager/snapshots 에 있다고 가정합니다. + * `--pip-non-url`: PyPI 에 등록된 pip 패키지들에 대해서 복구를 수행 + * `--pip-non-local-url`: web URL에 등록된 pip 패키지들에 대해서 복구를 수행 + * `--pip-local-url`: local 경로를 지정하고 있는 pip 패키지들에 대해서 복구를 수행 + + +### 5. CLI only mode + +ComfyUI-Manager를 CLI로만 사용할 것인지를 설정할 수 있습니다. + +`cli-only-mode [enable|disable]` + +* security 혹은 policy 의 이유로 GUI 를 통한 ComfyUI-Manager 사용을 제한하고 싶은 경우 이 모드를 사용할 수 있습니다. + * CLI only mode를 적용할 경우 ComfyUI-Manager 가 매우 제한된 상태로 로드되어, 내부적으로 제공하는 web API가 비활성화 되며, 메인 메뉴에서도 Manager 버튼이 표시되지 않습니다. + + +### 6. 의존성 설치 + +`restore-dependencies` + +* `ComfyUI/custom_nodes` 하위 경로에 커스텀 노드들이 설치되어 있긴 하지만, 의존성이 설치되지 않은 경우 사용할 수 있습니다. +* colab 과 같이 cloud instance를 새로 시작하는 경우 의존성 재설치 및 설치 스크립트가 재실행 되어야 하는 경우 사용합니다. +* ComfyUI을 재설치할 경우, custom_nodes 경로만 백업했다가 재설치 할 경우 활용 가능합니다. + + +### 7. clear + +GUI에서 install, update를 하거나 snapshot 을 restore하는 경우 예약을 통해서 다음번 ComfyUI를 실행할 경우 실행되는 구조입니다. `clear` 는 이런 예약 상태를 clear해서, 아무런 사전 실행이 적용되지 않도록 합니다. \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/extension-node-map.json b/custom_nodes/ComfyUI-Manager/extension-node-map.json new file mode 100644 index 000000000..8843576b5 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/extension-node-map.json @@ -0,0 +1,15962 @@ +{ + "https://gist.github.com/alkemann/7361b8eb966f29c8238fd323409efb68/raw/f9605be0b38d38d3e3a2988f89248ff557010076/alkemann.py": [ + [ + "Int to Text", + "Save A1 Image", + "Seed With Text" + ], + { + "title_aux": "alkemann nodes" + } + ], + "https://git.mmaker.moe/mmaker/sd-webui-color-enhance": [ + [ + "MMakerColorBlend", + "MMakerColorEnhance" + ], + { + "title_aux": "Color Enhance" + } + ], + "https://github.com/0xbitches/ComfyUI-LCM": [ + [ + "LCM_Sampler", + "LCM_Sampler_Advanced", + "LCM_img2img_Sampler", + "LCM_img2img_Sampler_Advanced" + ], + { + "title_aux": "Latent Consistency Model for ComfyUI" + } + ], + "https://github.com/1038lab/ComfyUI-GPT2P": [ + [ + "GPT2PNode" + ], + { + "title_aux": "ComfyUI-GPT2P" + } + ], + "https://github.com/1038lab/ComfyUI_LatentSizeSelector": [ + [ + "LatentSizeSelector" + ], + { + "title_aux": "ComfyUI-latentSizeSelector" + } + ], + "https://github.com/11dogzi/ComfUI-EGAdapterMadAssistant": [ + [ + "EGIPAdapter_Mad_Assistant", + "EGIPAdapter_Mad_AssistantV1", + "EGIPAdapter_Mad_AssistantV2", + "EGIPAdapter_Mad_AssistantV3", + "EGIPAdapter_Mad_AssistantV4", + "EGIPAdapter_Mad_AssistantV5" + ], + { + "title_aux": "ComfUI-EGAdapterMadAssistant" + } + ], + "https://github.com/11dogzi/Comfyui-ergouzi-Nodes": [ + [ + "EG-YSZT-ZT", + "EG_CPSYTJ", + "EG_FX_BDAPI", + "EG_HT_YSTZ", + "EG_JF_ZZSC", + "EG_JXFZ_node", + "EG_K_LATENT", + "EG_RY_HT", + "EG_SCQY_BHDQY", + "EG_SCQY_QBQY", + "EG_SCQY_SXQY", + "EG_SJ", + "EG_SJPJ_Node", + "EG_SS_RYZH", + "EG_SZ_JDYS", + "EG_TC_Node", + "EG_TSCDS_CJ", + "EG_TSCDS_DG", + "EG_TSCDS_FG", + "EG_TSCDS_JT", + "EG_TSCDS_QT", + "EG_TSCDS_RW", + "EG_TSCDS_WP", + "EG_TSCDS_ZL", + "EG_TSCMB_GL", + "EG_TXZZ_ZH", + "EG_TX_CCHQ", + "EG_TX_CJPJ", + "EG_TX_JZRY", + "EG_TX_LJ", + "EG_TX_LJBC", + "EG_TX_SFBLS", + "EG_TX_WHLJ", + "EG_WB_KSH", + "EG_WXZ_QH", + "EG_XZ_QH", + "EG_YSQY_BBLLD", + "EG_YSQY_BLLD", + "EG_ZY_WBK", + "EG_ZZHBCJ", + "EG_ZZKZ_HT_node", + "EG_ZZ_BSYH", + "EG_ZZ_BYYH", + "EG_ZZ_HSYH", + "EG_ZZ_SSKZ", + "ER_JBCH", + "ER_TX_ZZCJ" + ], + { + "title_aux": "Comfyui-ergouzi-Nodes" + } + ], + "https://github.com/11dogzi/Comfyui-ergouzi-samplers": [ + [ + "EGBYZZCYQ", + "EGCYQJB", + "EGCYQJBCJ" + ], + { + "title_aux": "Comfyui-ergouzi-samplers" + } + ], + "https://github.com/1mckw/Comfyui-Gelbooru": [ + [ + "Gelbooru (ID)", + "Gelbooru (Random)" + ], + { + "title_aux": "Comfyui-Gelbooru" + } + ], + "https://github.com/1shadow1/hayo_comfyui_nodes/raw/main/LZCNodes.py": [ + [ + "LoadPILImages", + "MergeImages", + "make_transparentmask", + "tensor_trans_pil", + "words_generatee" + ], + { + "title_aux": "Hayo comfyui nodes" + } + ], + "https://github.com/42lux/ComfyUI-safety-checker": [ + [ + "Safety Checker" + ], + { + "title_aux": "ComfyUI-safety-checker" + } + ], + "https://github.com/438443467/ComfyUI-GPT4V-Image-Captioner": [ + [ + "GPT4VCaptioner", + "Image Load with Metadata", + "SAMIN String Attribute Selector", + "SANMIN Adapt Coordinates", + "SANMIN AdjustTransparency", + "SANMIN BlurMaskArea", + "SANMIN ChineseToCharacter", + "SANMIN ClothingWildcards", + "SANMIN ConvertToEnglish", + "SANMIN EditWildcards", + "SANMIN Float", + "SANMIN LoadPathImagesPreview", + "SANMIN SCALE AND FILL BLACK", + "SANMIN SanmiSaveImageToLocal", + "SANMIN SimpleWildcards", + "SANMIN Upscale And Original Size", + "Samin Counter", + "Samin Load Image Batch" + ], + { + "title_aux": "ComfyUI-GPT4V-Image-Captioner" + } + ], + "https://github.com/54rt1n/ComfyUI-DareMerge": [ + [ + "DM_AdvancedDareModelMerger", + "DM_AdvancedModelMerger", + "DM_AttentionGradient", + "DM_BlockGradient", + "DM_BlockModelMerger", + "DM_DareClipMerger", + "DM_DareModelMergerBlock", + "DM_DareModelMergerElement", + "DM_DareModelMergerMBW", + "DM_GradientEdit", + "DM_GradientOperations", + "DM_GradientReporting", + "DM_InjectNoise", + "DM_LoRALoaderTags", + "DM_LoRAReporting", + "DM_MBWGradient", + "DM_MagnitudeMasker", + "DM_MaskEdit", + "DM_MaskOperations", + "DM_MaskReporting", + "DM_ModelReporting", + "DM_NormalizeModel", + "DM_QuadMasker", + "DM_ShellGradient", + "DM_SimpleMasker" + ], + { + "title_aux": "ComfyUI-DareMerge" + } + ], + "https://github.com/80sVectorz/ComfyUI-Static-Primitives": [ + [ + "FloatStaticPrimitive", + "IntStaticPrimitive", + "StringMlStaticPrimitive", + "StringStaticPrimitive" + ], + { + "title_aux": "ComfyUI-Static-Primitives" + } + ], + "https://github.com/A4P7J1N7M05OT/ComfyUI-AutoColorGimp": [ + [ + "AutoColorGimp" + ], + { + "title_aux": "ComfyUI-AutoColorGimp" + } + ], + "https://github.com/A4P7J1N7M05OT/ComfyUI-PixelOE": [ + [ + "PixelOE" + ], + { + "title_aux": "ComfyUI-PixelOE" + } + ], + "https://github.com/AARG-FAN/Image-Raster-for-ComfyUI": [ + [ + "AIraster" + ], + { + "title_aux": "Image-vector-for-ComfyUI" + } + ], + "https://github.com/AIFSH/ComfyUI-3d-photo-inpainting": [ + [ + "LoadImagePath", + "PreViewVideo", + "TreeDNode" + ], + { + "title_aux": "ComfyUI-3d-photo-inpainting" + } + ], + "https://github.com/AIFSH/ComfyUI-AuraSR": [ + [ + "AuraSRNode" + ], + { + "title_aux": "AIFSH/ComfyUI-AuraSR" + } + ], + "https://github.com/AIFSH/ComfyUI-DiffSynth-Studio": [ + [ + "ControlNetPathLoader", + "DiffTextNode", + "DiffutoonNode", + "ExVideoNode", + "LoadVideo", + "PreViewVideo", + "SDPathLoader" + ], + { + "title_aux": "ComfyUI-DiffSynth-Studio" + } + ], + "https://github.com/AIFSH/ComfyUI-FishSpeech": [ + [ + "FishSpeech_INFER", + "FishSpeech_INFER_SRT", + "LoadAudio", + "LoadSRT", + "PreViewAudio" + ], + { + "title_aux": "ComfyUI-FishSpeech" + } + ], + "https://github.com/AIFSH/ComfyUI-GPT_SoVITS": [ + [ + "GPT_SOVITS_FT", + "GPT_SOVITS_INFER", + "GPT_SOVITS_TTS", + "LoadAudio", + "LoadSRT", + "PreViewAudio" + ], + { + "title_aux": "ComfyUI-GPT_SoVITS" + } + ], + "https://github.com/AIFSH/ComfyUI-Hallo": [ + [ + "HalloNode", + "LoadAudioPath", + "LoadImagePath", + "PreViewVideo" + ], + { + "title_aux": "ComfyUI-Hallo" + } + ], + "https://github.com/AIFSH/ComfyUI-I2V-Adapter": [ + [ + "I2V_AdapterNode", + "LoraPathLoader", + "MotionLoraLoader", + "PreViewVideo", + "PromptNode" + ], + { + "title_aux": "ComfyUI-I2V-Adapter" + } + ], + "https://github.com/AIFSH/ComfyUI-IP_LAP": [ + [ + "CombineAudioVideo", + "IP_LAP", + "LoadVideo", + "PreViewVideo" + ], + { + "title_aux": "ComfyUI-IP_LAP" + } + ], + "https://github.com/AIFSH/ComfyUI-Live2DViewer": [ + [ + "Live2DViewer", + "LoadAudio" + ], + { + "title_aux": "ComfyUI-Live2DViewer" + } + ], + "https://github.com/AIFSH/ComfyUI-MARS5-TTS": [ + [ + "LoadAudioPath", + "MARS5TTS_Node", + "PreViewAudio", + "TTSTextEncode" + ], + { + "title_aux": "ComfyUI-MARS5-TTS" + } + ], + "https://github.com/AIFSH/ComfyUI-MimicBrush": [ + [ + "MimicBrushNode" + ], + { + "title_aux": "ComfyUI-MimicBrush" + } + ], + "https://github.com/AIFSH/ComfyUI-MimicMotion": [ + [ + "LoadVideo", + "MimicMotionNode", + "PreViewVideo" + ], + { + "title_aux": "ComfyUI-MimicMotion" + } + ], + "https://github.com/AIFSH/ComfyUI-MuseTalk_FSH": [ + [ + "CombineAudioVideo", + "LoadVideo", + "MuseTalk", + "MuseTalkRealTime", + "PreViewVideo" + ], + { + "title_aux": "ComfyUI-MuseTalk_FSH" + } + ], + "https://github.com/AIFSH/ComfyUI-RVC": [ + [ + "CombineAudio", + "LoadAudio", + "PreViewAudio", + "RVC_Infer", + "RVC_Train" + ], + { + "title_aux": "ComfyUI-RVC" + } + ], + "https://github.com/AIFSH/ComfyUI-UVR5": [ + [ + "LoadAudioPath", + "PreViewAudio", + "UVR5_Node" + ], + { + "title_aux": "ComfyUI-UVR5" + } + ], + "https://github.com/AIFSH/ComfyUI-UniAnimate": [ + [ + "LoadImagePath", + "LoadVideo", + "PoseAlignNode", + "PreViewVideo", + "UniAnimateNode" + ], + { + "title_aux": "ComfyUI-UniAnimate" + } + ], + "https://github.com/AIFSH/ComfyUI-WhisperX": [ + [ + "LoadAudio", + "PreViewSRT", + "WhisperX" + ], + { + "title_aux": "ComfyUI-WhisperX" + } + ], + "https://github.com/AIFSH/ComfyUI-XTTS": [ + [ + "LoadAudioPath", + "LoadSRT", + "PreViewAudio", + "XTTS_INFER", + "XTTS_INFER_SRT" + ], + { + "title_aux": "ComfyUI-XTTS" + } + ], + "https://github.com/AIFSH/ComfyUI_V-Express": [ + [ + "LoadAudioPath", + "LoadImagePath", + "LoadVideo", + "PreViewVideo", + "VExpress" + ], + { + "title_aux": "ComfyUI_V-Express" + } + ], + "https://github.com/AIGCTeam/ComfyUI_kkTranslator_nodes": [ + [ + "LoadMarianMTCheckPoint", + "PromptBaiduFanyiToText", + "PromptTranslateToText" + ], + { + "title_aux": "ComfyUI_kkTranslator_nodes" + } + ], + "https://github.com/AIGODLIKE/ComfyUI-CUP": [ + [ + "Mask", + "OpenPose", + "OpenPoseCanny", + "OpenPoseDepth", + "OpenPoseFace", + "OpenPoseFull", + "OpenPoseFullExtraLimb", + "OpenPoseHand", + "OpenPoseKeyPose", + "OpenPoseLineart", + "OpenPoseMediaPipeFace", + "PreviewAudio", + "SaveAudioBL", + "\u5b58\u50a8", + "\u5bfc\u5165", + "\u622a\u56fe", + "\u6750\u8d28\u56fe", + "\u8f93\u5165\u56fe\u50cf", + "\u9884\u89c8" + ], + { + "title_aux": "ComfyUI-CUP" + } + ], + "https://github.com/AIGODLIKE/ComfyUI-ToonCrafter": [ + [ + "ToonCrafterNode" + ], + { + "title_aux": "ComfyUI-ToonCrafter" + } + ], + "https://github.com/AInseven/ComfyUI-fastblend": [ + [ + "FillDarkMask", + "InterpolateKeyFrame", + "MaskListcaptoBatch", + "Merge_Image_List", + "MyOpenPoseNode", + "SmoothVideo", + "alert_when_finished", + "reBatchImage" + ], + { + "title_aux": "ComfyUI-fastblend" + } + ], + "https://github.com/AIrjen/OneButtonPrompt": [ + [ + "AutoNegativePrompt", + "CreatePromptVariant", + "OneButtonArtify", + "OneButtonFlufferize", + "OneButtonPreset", + "OneButtonPrompt", + "OneButtonSuperPrompt", + "SavePromptToFile" + ], + { + "title_aux": "One Button Prompt" + } + ], + "https://github.com/ALatentPlace/ComfyUI_yanc": [ + [ + "> Clear Text", + "> Float to Int", + "> Get Mean Color", + "> Int", + "> Int to Text", + "> Layer Weights (for IPAMS)", + "> Light Source Mask", + "> Load Image", + "> Load Image From Folder", + "> Mask Curves", + "> NIKSampler", + "> Noise From Image", + "> Normal Map Lighting", + "> RGB Color", + "> Resolution by Aspect Ratio", + "> Rotate Image", + "> Save Image", + "> Scale Image to Side", + "> Text", + "> Text Combine", + "> Text Pick Random Line", + "> Text Random Weights", + "> Text Replace" + ], + { + "title_aux": "ComfyUI_yanc" + } + ], + "https://github.com/AbdullahAlfaraj/Comfy-Photoshop-SD": [ + [ + "APS_LatentBatch", + "APS_Seed", + "ContentMaskLatent", + "ControlNetScript", + "ControlnetUnit", + "GaussianLatentImage", + "GetConfig", + "LoadImageBase64", + "LoadImageWithMetaData", + "LoadLorasFromPrompt", + "MaskExpansion" + ], + { + "title_aux": "Comfy-Photoshop-SD" + } + ], + "https://github.com/AbyssYuan0/ComfyUI_BadgerTools": [ + [ + "ApplyMaskToImage-badger", + "CropImageByMask-badger", + "ExpandImageWithColor-badger", + "FindThickLinesFromCanny-badger", + "FloatToInt-badger", + "FloatToString-badger", + "FrameToVideo-badger", + "GETRequset-badger", + "GarbageCollect-badger", + "GetColorFromBorder-badger", + "GetDirName-badger", + "GetUUID-badger", + "IdentifyBorderColorToMask-badger", + "IdentifyColorToMask-badger", + "ImageNormalization-badger", + "ImageOverlap-badger", + "ImageScaleToSide-badger", + "IntToString-badger", + "IntToStringAdvanced-badger", + "LoadImageAdvanced-badger", + "LoadImagesFromDirListAdvanced-badger", + "SegmentToMaskByPoint-badger", + "SimpleBoolean-badger", + "StringToFizz-badger", + "TextListToString-badger", + "ToPixel-badger", + "TrimTransparentEdges-badger", + "VideoCutFromDir-badger", + "VideoToFrame-badger", + "deleteDir-badger", + "findCenterOfMask-badger", + "getImageSide-badger", + "getParentDir-badger", + "mkdir-badger" + ], + { + "title_aux": "ComfyUI_BadgerTools" + } + ], + "https://github.com/Acly/comfyui-inpaint-nodes": [ + [ + "INPAINT_ApplyFooocusInpaint", + "INPAINT_DenoiseToCompositingMask", + "INPAINT_ExpandMask", + "INPAINT_InpaintWithModel", + "INPAINT_LoadFooocusInpaint", + "INPAINT_LoadInpaintModel", + "INPAINT_MaskedBlur", + "INPAINT_MaskedFill", + "INPAINT_VAEEncodeInpaintConditioning" + ], + { + "title_aux": "ComfyUI Inpaint Nodes" + } + ], + "https://github.com/Acly/comfyui-tooling-nodes": [ + [ + "ETN_ApplyMaskToImage", + "ETN_AttentionMask", + "ETN_BackgroundRegion", + "ETN_CropImage", + "ETN_DefineRegion", + "ETN_ExtractImageTile", + "ETN_ExtractMaskTile", + "ETN_GenerateTileMask", + "ETN_ListRegionMasks", + "ETN_LoadImageBase64", + "ETN_LoadMaskBase64", + "ETN_MergeImageTile", + "ETN_SendImageWebSocket", + "ETN_TileLayout" + ], + { + "title_aux": "ComfyUI Nodes for External Tooling" + } + ], + "https://github.com/AiMiDi/ComfyUI-Aimidi-nodes": [ + [ + "Add Tag", + "Clear Tag", + "Load Images Pair Batch", + "Merge Tag", + "Move Tag To Top", + "Reserve Tag", + "Save Images Pair" + ], + { + "title_aux": "ComfyUI-Aimidi-nodes" + } + ], + "https://github.com/AlekPet/ComfyUI_Custom_Nodes_AlekPet": [ + [ + "ArgosTranslateCLIPTextEncodeNode", + "ArgosTranslateTextNode", + "ColorsCorrectNode", + "DeepTranslatorCLIPTextEncodeNode", + "DeepTranslatorTextNode", + "GoogleTranslateCLIPTextEncodeNode", + "GoogleTranslateTextNode", + "HexToHueNode", + "PainterNode", + "PoseNode", + "PreviewTextNode" + ], + { + "title_aux": "AlekPet/ComfyUI_Custom_Nodes_AlekPet" + } + ], + "https://github.com/Amorano/Jovimetrix": [ + [ + "ADJUST (JOV) \ud83d\udd78\ufe0f", + "AKASHIC (JOV) \ud83d\udcd3", + "ARRAY (JOV) \ud83d\udcda", + "BLEND (JOV) \u2697\ufe0f", + "COLOR BLIND (JOV) \ud83d\udc41\u200d\ud83d\udde8", + "COLOR MATCH (JOV) \ud83d\udc9e", + "COLOR THEORY (JOV) \ud83d\udede", + "COMPARISON (JOV) \ud83d\udd75\ud83c\udffd", + "CONSTANT (JOV) \ud83d\udfea", + "CROP (JOV) \u2702\ufe0f", + "DELAY (JOV) \u270b\ud83c\udffd", + "EXPORT (JOV) \ud83d\udcfd", + "FILTER MASK (JOV) \ud83e\udd3f", + "FLATTEN (JOV) \u2b07\ufe0f", + "GLSL (JOV) \ud83c\udf69", + "GRADIENT MAP (JOV) \ud83c\uddf2\ud83c\uddfa", + "GRAPH (JOV) \ud83d\udcc8", + "LERP (JOV) \ud83d\udd30", + "MIDI FILTER (JOV) \u2733\ufe0f", + "MIDI FILTER EZ (JOV) \u2747\ufe0f", + "MIDI MESSAGE (JOV) \ud83c\udf9b\ufe0f", + "MIDI READER (JOV) \ud83c\udfb9", + "OP BINARY (JOV) \ud83c\udf1f", + "OP UNARY (JOV) \ud83c\udfb2", + "PIXEL MERGE (JOV) \ud83e\udec2", + "PIXEL SPLIT (JOV) \ud83d\udc94", + "PIXEL SWAP (JOV) \ud83d\udd03", + "QUEUE (JOV) \ud83d\uddc3", + "ROUTE (JOV) \ud83d\ude8c", + "SAVE OUTPUT (JOV) \ud83d\udcbe", + "SHAPE GEN (JOV) \u2728", + "SPOUT WRITER (JOV) \ud83c\udfa5", + "STACK (JOV) \u2795", + "STEREOGRAM (JOV) \ud83d\udcfb", + "STEREOSCOPIC (JOV) \ud83d\udd76\ufe0f", + "STREAM READER (JOV) \ud83d\udcfa", + "STREAM WRITER (JOV) \ud83c\udf9e\ufe0f", + "SWIZZLE (JOV) \ud83d\ude35", + "TEXT GEN (JOV) \ud83d\udcdd", + "THRESHOLD (JOV) \ud83d\udcc9", + "TICK (JOV) \u23f1", + "TRANSFORM (JOV) \ud83c\udfdd\ufe0f", + "VALUE (JOV) \ud83e\uddec", + "WAVE GEN (JOV) \ud83c\udf0a", + "WAVE GRAPH (JOV) \u25b6 \u0131l\u0131\u0131l\u0131" + ], + { + "author": "amorano", + "description": "Jovimetrix integrates Webcam, MIDI, Spout and GLSL shader support.", + "nodename_pattern": " \\(JOV\\)$", + "title": "Jovimetrix", + "title_aux": "Jovimetrix Composition Nodes" + } + ], + "https://github.com/AonekoSS/ComfyUI-LoRA-Tuner": [ + [ + "LoraTuner" + ], + { + "title_aux": "ComfyUI-LoRA-Tuner" + } + ], + "https://github.com/AonekoSS/ComfyUI-SimpleCounter": [ + [ + "Simple Counter" + ], + { + "title_aux": "ComfyUI-SimpleCounter" + } + ], + "https://github.com/ArcherFMY/Diffusion360_ComfyUI": [ + [ + "Diffusion360LoaderImage2Pano", + "Diffusion360LoaderText2Pano", + "Diffusion360Sampler", + "Diffusion360SamplerImage2Pano", + "Diffusion360SamplerText2Pano", + "InputImage", + "InputText", + "VAEDecodeTiledBlended" + ], + { + "title_aux": "Diffusion360_ComfyUI" + } + ], + "https://github.com/ArdeniusAI/CPlus_Ardenius": [ + [ + "Control_Box" + ], + { + "author": "initials AMA", + "description": "CPlus control box is designed to gather workflow variables into 1 node for easier control of your workflow.", + "nickname": "Ardenius", + "title": "Ardenius", + "title_aux": "CPlus_Ardenius ComfyUI Control Box" + } + ], + "https://github.com/ArtBot2023/CharacterFaceSwap": [ + [ + "Color Blend", + "Crop Face", + "Exclude Facial Feature", + "Generation Parameter Input", + "Generation Parameter Output", + "Image Full BBox", + "Load BiseNet", + "Load RetinaFace", + "Mask Contour", + "Segment Face", + "Uncrop Face" + ], + { + "title_aux": "Character Face Swap" + } + ], + "https://github.com/ArtVentureX/comfyui-animatediff": [ + [ + "AnimateDiffCombine", + "AnimateDiffLoraLoader", + "AnimateDiffModuleLoader", + "AnimateDiffSampler", + "AnimateDiffSlidingWindowOptions", + "ImageSizeAndBatchSize", + "LoadVideo" + ], + { + "title_aux": "AnimateDiff" + } + ], + "https://github.com/AshMartian/ComfyUI-DirGir": [ + [ + "Dir_Gir_Looper", + "Dir_Gir_Picker", + "Gir_Image_Nabber" + ], + { + "title_aux": "Dir Gir" + } + ], + "https://github.com/AuroBit/ComfyUI-AnimateAnyone-reproduction": [ + [ + "AnimateAnyone" + ], + { + "title_aux": "ComfyUI-AnimateAnyone-reproduction" + } + ], + "https://github.com/AustinMroz/ComfyUI-DynamicOversampling": [ + [ + "DynamicSampler", + "MeasuredSampler", + "ResolveMaskPromise" + ], + { + "title_aux": "DynamicOversampling" + } + ], + "https://github.com/AustinMroz/ComfyUI-SpliceTools": [ + [ + "LogSigmas", + "RerangeSigmas", + "SpliceDenoised", + "SpliceLatents", + "TemporalSplice" + ], + { + "title_aux": "SpliceTools" + } + ], + "https://github.com/Auttasak-L/ComfyUI-ImageCropper": [ + [ + "ImageCropper" + ], + { + "title_aux": "ComfyUI-ImageCropper" + } + ], + "https://github.com/BAIS1C/ComfyUI_RSS_Feed_Reader": [ + [ + "RSSFeedNode" + ], + { + "title_aux": "ComfyUI_RSS_Feed_Reader" + } + ], + "https://github.com/BXYMartin/ComfyUI-InstantIDUtils": [ + [ + "ListOfImages", + "MultiControlNetConverter", + "NHWC2NCHWTensor", + "NHWCTensor2PIL", + "PIL2NHWCTensor" + ], + { + "title_aux": "ComfyUI-InstantIDUtils" + } + ], + "https://github.com/BadCafeCode/masquerade-nodes-comfyui": [ + [ + "Blur", + "Change Channel Count", + "Combine Masks", + "Constant Mask", + "Convert Color Space", + "Create QR Code", + "Create Rect Mask", + "Cut By Mask", + "Get Image Size", + "Image To Mask", + "Make Image Batch", + "Mask By Text", + "Mask Morphology", + "Mask To Region", + "MasqueradeIncrementer", + "Mix Color By Mask", + "Mix Images By Mask", + "Paste By Mask", + "Prune By Mask", + "Separate Mask Components", + "Unary Image Op", + "Unary Mask Op" + ], + { + "title_aux": "Masquerade Nodes" + } + ], + "https://github.com/Beinsezii/bsz-cui-extras": [ + [ + "BSZAbsoluteHires", + "BSZAspectHires", + "BSZColoredLatentImageXL", + "BSZCombinedHires", + "BSZHueChromaXL", + "BSZInjectionKSampler", + "BSZLatentDebug", + "BSZLatentFill", + "BSZLatentGradient", + "BSZLatentHSVAImage", + "BSZLatentOffsetXL", + "BSZLatentRGBAImage", + "BSZLatentbuster", + "BSZPixelbuster", + "BSZPixelbusterHelp", + "BSZPrincipledConditioning", + "BSZPrincipledSampler", + "BSZPrincipledScale", + "BSZStrangeResample" + ], + { + "title_aux": "bsz-cui-extras" + } + ], + "https://github.com/BenNarum/SigmaWaveFormNode": [ + [ + "AttenuatorNode", + "FourierFilterNode", + "PhaseLockedLoopNode", + "SigmaWaveFormNode", + "SigmaWaveFormNodeAdvanced", + "SigmaWaveFormNodeSimple" + ], + { + "title_aux": "SigmaWaveFormNodes" + } + ], + "https://github.com/BennyKok/comfyui-deploy": [ + [ + "ComfyDeployWebscoketImageInput", + "ComfyDeployWebscoketImageOutput", + "ComfyUIDeployExternalBoolean", + "ComfyUIDeployExternalCheckpoint", + "ComfyUIDeployExternalImage", + "ComfyUIDeployExternalImageAlpha", + "ComfyUIDeployExternalImageBatch", + "ComfyUIDeployExternalLora", + "ComfyUIDeployExternalNumber", + "ComfyUIDeployExternalNumberInt", + "ComfyUIDeployExternalNumberSlider", + "ComfyUIDeployExternalText", + "ComfyUIDeployExternalVid", + "ComfyUIDeployExternalVideo" + ], + { + "author": "BennyKok", + "description": "", + "nickname": "Comfy Deploy", + "title": "comfyui-deploy", + "title_aux": "ComfyUI Deploy" + } + ], + "https://github.com/Big-Idea-Technology/ComfyUI-Book-Tools": [ + [ + "BTPromptSchedule", + "BTPromptSelector", + "EndQueue", + "ImageTextOverlay", + "Loop", + "LoopEnd", + "LoopStart" + ], + { + "title_aux": "ComfyUI-Book-Tools Nodes for ComfyUI" + } + ], + "https://github.com/Big-Idea-Technology/ComfyUI_LLM_Node": [ + [ + "AdvOptions_Node", + "CodingOptionsNode", + "LLM_Node", + "Output_Node", + "QuantizationConfig_Node" + ], + { + "title_aux": "LLM Node for ComfyUI" + } + ], + "https://github.com/Bikecicle/ComfyUI-Waveform-Extensions/raw/main/EXT_AudioManipulation.py": [ + [ + "BatchJoinAudio", + "CutAudio", + "DuplicateAudio", + "JoinAudio", + "ResampleAudio", + "ReverseAudio", + "StretchAudio" + ], + { + "title_aux": "Waveform Extensions" + } + ], + "https://github.com/Billius-AI/ComfyUI-Path-Helper": [ + [ + "Add File Name Prefix", + "Add File Name Prefix Advanced", + "Add Folder", + "Add Folder Advanced", + "Create Project Root", + "Join Variables", + "Show Path", + "Show String" + ], + { + "title_aux": "ComfyUI-Path-Helper" + } + ], + "https://github.com/BlakeOne/ComfyUI-CustomScheduler": [ + [ + "CustomScheduler" + ], + { + "title_aux": "ComfyUI CustomScheduler" + } + ], + "https://github.com/BlakeOne/ComfyUI-SchedulerMixer": [ + [ + "SchedulerMixer" + ], + { + "title_aux": "ComfyUI SchedulerMixer" + } + ], + "https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb": [ + [ + "BNK_AddCLIPSDXLParams", + "BNK_AddCLIPSDXLRParams", + "BNK_CLIPTextEncodeAdvanced", + "BNK_CLIPTextEncodeSDXLAdvanced" + ], + { + "title_aux": "Advanced CLIP Text Encode" + } + ], + "https://github.com/BlenderNeko/ComfyUI_Cutoff": [ + [ + "BNK_CutoffBasePrompt", + "BNK_CutoffRegionsToConditioning", + "BNK_CutoffRegionsToConditioning_ADV", + "BNK_CutoffSetRegions" + ], + { + "title_aux": "ComfyUI Cutoff" + } + ], + "https://github.com/BlenderNeko/ComfyUI_Noise": [ + [ + "BNK_DuplicateBatchIndex", + "BNK_GetSigma", + "BNK_InjectNoise", + "BNK_NoisyLatentImage", + "BNK_SlerpLatent", + "BNK_Unsampler" + ], + { + "title_aux": "ComfyUI Noise" + } + ], + "https://github.com/BlenderNeko/ComfyUI_SeeCoder": [ + [ + "ConcatConditioning", + "SEECoderImageEncode" + ], + { + "title_aux": "SeeCoder [WIP]" + } + ], + "https://github.com/BlenderNeko/ComfyUI_TiledKSampler": [ + [ + "BNK_TiledKSampler", + "BNK_TiledKSamplerAdvanced" + ], + { + "title_aux": "Tiled sampling for ComfyUI" + } + ], + "https://github.com/CC-BryanOttho/ComfyUI_API_Manager": [ + [ + "APIRequestNode", + "PostImageToAPI", + "TextPromptCombinerNode" + ], + { + "title_aux": "ComfyUI_API_Manager" + } + ], + "https://github.com/CYBERLOOM-INC/ComfyUI-nodes-hnmr": [ + [ + "CLIPIter", + "Dict2Model", + "GridImage", + "ImageBlend2", + "KSamplerOverrided", + "KSamplerSetting", + "KSamplerXYZ", + "LatentToHist", + "LatentToImage", + "ModelIter", + "RandomLatentImage", + "SaveStateDict", + "SaveText", + "StateDictLoader", + "StateDictMerger", + "StateDictMergerBlockWeighted", + "StateDictMergerBlockWeightedMulti", + "VAEDecodeBatched", + "VAEEncodeBatched", + "VAEIter" + ], + { + "title_aux": "ComfyUI-nodes-hnmr" + } + ], + "https://github.com/CaptainGrock/ComfyUIInvisibleWatermark/raw/main/Invisible%20Watermark.py": [ + [ + "Apply Invisible Watermark", + "Extract Watermark" + ], + { + "title_aux": "ComfyUIInvisibleWatermark" + } + ], + "https://github.com/Chan-0312/ComfyUI-EasyDeforum": [ + [ + "Easy2DDeforum" + ], + { + "title_aux": "ComfyUI-EasyDeforum" + } + ], + "https://github.com/Chan-0312/ComfyUI-IPAnimate": [ + [ + "IPAdapterAnimate" + ], + { + "title_aux": "ComfyUI-IPAnimate" + } + ], + "https://github.com/Chan-0312/ComfyUI-Prompt-Preview": [ + [ + "SDXLPromptStylerAdvancedPreview", + "SDXLPromptStylerPreview" + ], + { + "title_aux": "ComfyUI-Prompt-Preview" + } + ], + "https://github.com/Chaoses-Ib/ComfyUI_Ib_CustomNodes": [ + [ + "ImageToPIL", + "LoadImageFromPath", + "PILToImage", + "PILToMask" + ], + { + "title_aux": "ComfyUI_Ib_CustomNodes" + } + ], + "https://github.com/Clybius/ComfyUI-Extra-Samplers": [ + [ + "GeometricCFGGuider", + "ImageAssistedCFGGuider", + "MegaCFGGuider", + "SamplerCLYB_4M_SDE_Momentumized", + "SamplerCustomModelMixtureDuo", + "SamplerCustomNoise", + "SamplerCustomNoiseDuo", + "SamplerDPMPP_3M_SDE_DynETA", + "SamplerDPMPP_DualSDE_Momentumized", + "SamplerEulerAncestralDancing_Experimental", + "SamplerLCMCustom", + "SamplerRES_Momentumized", + "SamplerSupreme", + "SamplerTTM", + "ScaledCFGGuider", + "SimpleExponentialScheduler", + "WarmupDecayCFGGuider" + ], + { + "title_aux": "ComfyUI Extra Samplers" + } + ], + "https://github.com/Clybius/ComfyUI-Latent-Modifiers": [ + [ + "Latent Diffusion Mega Modifier" + ], + { + "title_aux": "ComfyUI-Latent-Modifiers" + } + ], + "https://github.com/CosmicLaca/ComfyUI_Primere_Nodes": [ + [ + "PrimereAestheticCKPTScorer", + "PrimereAnyDetailer", + "PrimereAnyOutput", + "PrimereCKPT", + "PrimereCKPTLoader", + "PrimereCLIPEncoder", + "PrimereClearPrompt", + "PrimereConceptDataTuple", + "PrimereDynamicParser", + "PrimereEmbedding", + "PrimereEmbeddingHandler", + "PrimereEmbeddingKeywordMerger", + "PrimereEmotionsStyles", + "PrimereHypernetwork", + "PrimereImageSegments", + "PrimereKSampler", + "PrimereLCMSelector", + "PrimereLORA", + "PrimereLYCORIS", + "PrimereLatentNoise", + "PrimereLoraKeywordMerger", + "PrimereLoraStackMerger", + "PrimereLycorisKeywordMerger", + "PrimereLycorisStackMerger", + "PrimereMetaCollector", + "PrimereMetaDistributor", + "PrimereMetaDistributorStage2", + "PrimereMetaHandler", + "PrimereMetaRead", + "PrimereMetaSave", + "PrimereMidjourneyStyles", + "PrimereModelConceptSelector", + "PrimereModelKeyword", + "PrimereNetworkTagLoader", + "PrimerePreviewImage", + "PrimerePrompt", + "PrimerePromptOrganizer", + "PrimerePromptSwitch", + "PrimereRefinerPrompt", + "PrimereResolution", + "PrimereResolutionCoordinatorMPX", + "PrimereResolutionMultiplier", + "PrimereResolutionMultiplierMPX", + "PrimereSamplers", + "PrimereSamplersSteps", + "PrimereSeed", + "PrimereStepsCfg", + "PrimereStyleLoader", + "PrimereStylePile", + "PrimereTextOutput", + "PrimereUpscaleModel", + "PrimereVAE", + "PrimereVAELoader", + "PrimereVAESelector", + "PrimereVisualCKPT", + "PrimereVisualEmbedding", + "PrimereVisualHypernetwork", + "PrimereVisualLORA", + "PrimereVisualLYCORIS", + "PrimereVisualStyle" + ], + { + "title_aux": "Primere nodes for ComfyUI" + } + ], + "https://github.com/Danand/ComfyUI-ComfyCouple": [ + [ + "Attention couple", + "Comfy Couple" + ], + { + "author": "Rei D.", + "description": "If you want to draw two different characters together without blending their features, so you could try to check out this custom node.", + "nickname": "Danand", + "title": "Comfy Couple", + "title_aux": "Comfy Couple" + } + ], + "https://github.com/DannyStone1999/ComfyUI-Depth2Mask/raw/main/Depth2Mask.py": [ + [ + "Depth2Mask" + ], + { + "title_aux": "ComfyUI-Depth2Mask" + } + ], + "https://github.com/DarKDinDoN/comfyui-checkpoint-automatic-config": [ + [ + "CheckpointAutomaticConfig", + "ConfigPipe" + ], + { + "title_aux": "ComfyUI Checkpoint Automatic Config" + } + ], + "https://github.com/DataCTE/prompt_injection": [ + [ + "AdvancedPromptInjection", + "PromptInjection", + "SVDPromptInjection", + "SimplePromptInjection" + ], + { + "title_aux": "Prompt Injection Node for ComfyUI" + } + ], + "https://github.com/DeJoker/pipeline-parallel-comfy": [ + [ + "PipelineParallel" + ], + { + "title_aux": "Pipeline Parallel ComfyUI" + } + ], + "https://github.com/Derfuu/Derfuu_ComfyUI_ModdedNodes": [ + [], + { + "author": "Derfuu", + "description": "Pack of simple (or not) and modded nodes for scaling images/latents, editing numbers or text. Automate calculations depending on image sizes or any other thing you want. Or randomize any number in your workflow. Debug node included.", + "nickname": "Derfuu simple/modded Nodes", + "nodename_pattern": "^DF_", + "title": "Derfuu simple/modded Nodes", + "title_aux": "Derfuu_ComfyUI_ModdedNodes" + } + ], + "https://github.com/DonBaronFactory/ComfyUI-Cre8it-Nodes": [ + [ + "ApplySerialPrompter", + "ImageSizer", + "SerialPrompter" + ], + { + "author": "CRE8IT GmbH", + "description": "This extension offers various nodes.", + "nickname": "cre8Nodes", + "title": "cr8SerialPrompter", + "title_aux": "ComfyUI-Cre8it-Nodes" + } + ], + "https://github.com/DrMWeigand/ComfyUI_ColorImageDetection": [ + [ + "LABColorDetection", + "RGBColorDetection" + ], + { + "title_aux": "ComfyUI Color Detection Nodes" + } + ], + "https://github.com/Electrofried/ComfyUI-OpenAINode": [ + [ + "OpenAINode" + ], + { + "title_aux": "OpenAINode" + } + ], + "https://github.com/EllangoK/ComfyUI-post-processing-nodes": [ + [ + "ArithmeticBlend", + "AsciiArt", + "Blend", + "Blur", + "CannyEdgeMask", + "ChromaticAberration", + "ColorCorrect", + "ColorTint", + "Dissolve", + "Dither", + "DodgeAndBurn", + "FilmGrain", + "Glow", + "HSVThresholdMask", + "KMeansQuantize", + "KuwaharaBlur", + "Parabolize", + "PencilSketch", + "PixelSort", + "Pixelize", + "Quantize", + "Sharpen", + "SineWave", + "Solarize", + "Vignette" + ], + { + "title_aux": "ComfyUI-post-processing-nodes" + } + ], + "https://github.com/ExponentialML/ComfyUI_ModelScopeT2V": [ + [ + "ModelScopeT2VLoader" + ], + { + "title_aux": "ComfyUI_ModelScopeT2V" + } + ], + "https://github.com/ExponentialML/ComfyUI_Native_DynamiCrafter": [ + [ + "DynamiCrafterLoader", + "DynamiCrafterProcessor" + ], + { + "title_aux": "ComfyUI - Native DynamiCrafter" + } + ], + "https://github.com/ExponentialML/ComfyUI_VisualStylePrompting": [ + [ + "ApplyVisualStyle" + ], + { + "title_aux": "ComfyUI_VisualStylePrompting" + } + ], + "https://github.com/Extraltodeus/ComfyUI-AutomaticCFG": [ + [ + "Automatic CFG", + "Automatic CFG - Advanced", + "Automatic CFG - Attention modifiers", + "Automatic CFG - Attention modifiers tester", + "Automatic CFG - Custom attentions", + "Automatic CFG - Excellent attention", + "Automatic CFG - Negative", + "Automatic CFG - Post rescale only", + "Automatic CFG - Preset Loader", + "Automatic CFG - Unpatch function", + "Automatic CFG - Warp Drive", + "SAG delayed activation", + "Temperature separate settings CLIP SDXL", + "Temperature settings CLIP", + "Temperature settings SD 1.5", + "Temperature settings SDXL", + "Zero Uncond CFG - standalone patch (incompatible with the others)" + ], + { + "title_aux": "ComfyUI-AutomaticCFG" + } + ], + "https://github.com/Extraltodeus/LoadLoraWithTags": [ + [ + "LoraLoaderTagsQuery" + ], + { + "title_aux": "LoadLoraWithTags" + } + ], + "https://github.com/Extraltodeus/Stable-Diffusion-temperature-settings": [ + [ + "CLIP Temperature", + "Unet Temperature" + ], + { + "title_aux": "Stable-Diffusion-temperature-settings" + } + ], + "https://github.com/Extraltodeus/Uncond-Zero-for-ComfyUI": [ + [ + "Conditioning combine positive and negative", + "Conditioning crop or fill", + "Uncond Zero", + "interrupt on NaN" + ], + { + "title_aux": "Uncond-Zero-for-ComfyUI" + } + ], + "https://github.com/Extraltodeus/Vector_Sculptor_ComfyUI": [ + [ + "CLIP Vector Sculptor text encode", + "Conditioning (Average keep magnitude)", + "Conditioning (Slerp)", + "Conditioning SDXL merge clip_g / clip_l", + "Conditioning normalize magnitude to empty" + ], + { + "title_aux": "Vector_Sculptor_ComfyUI" + } + ], + "https://github.com/Extraltodeus/noise_latent_perlinpinpin": [ + [ + "NoisyLatentPerlin" + ], + { + "title_aux": "noise latent perlinpinpin" + } + ], + "https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI": [ + [ + "Pre CFG automatic scale", + "Pre CFG consensus sharpening", + "Pre CFG exponentiation", + "Pre CFG perp-neg", + "Pre CFG sharpening" + ], + { + "title_aux": "pre_cfg_comfy_nodes_for_ComfyUI" + } + ], + "https://github.com/Extraltodeus/sigmas_tools_and_the_golden_scheduler": [ + [ + "Aligned Scheduler", + "Gaussian Tail Scheduler", + "Get sigmas as float", + "Graph sigmas", + "Manual scheduler", + "Merge many sigmas by average", + "Merge sigmas by average", + "Merge sigmas gradually", + "Multiply sigmas", + "Output min/max sigmas", + "Split and concatenate sigmas", + "The Golden Scheduler" + ], + { + "title_aux": "sigmas_tools_and_the_golden_scheduler" + } + ], + "https://github.com/Fannovel16/ComfyUI-Frame-Interpolation": [ + [ + "AMT VFI", + "CAIN VFI", + "FILM VFI", + "FLAVR VFI", + "GMFSS Fortuna VFI", + "IFRNet VFI", + "IFUnet VFI", + "KSampler Gradually Adding More Denoise (efficient)", + "M2M VFI", + "Make Interpolation State List", + "RIFE VFI", + "STMFNet VFI", + "Sepconv VFI", + "VFI FloatToInt" + ], + { + "title_aux": "ComfyUI Frame Interpolation" + } + ], + "https://github.com/Fannovel16/ComfyUI-Loopchain": [ + [ + "EmptyLatentImageLoop", + "FolderToImageStorage", + "ImageStorageExportLoop", + "ImageStorageImport", + "ImageStorageReset", + "LatentStorageExportLoop", + "LatentStorageImport", + "LatentStorageReset" + ], + { + "title_aux": "ComfyUI Loopchain" + } + ], + "https://github.com/Fannovel16/ComfyUI-MagickWand": [ + [ + "ImageMagick Adaptive Blur", + "ImageMagick Adaptive Resize", + "ImageMagick Adaptive Sharpen", + "ImageMagick Adaptive Threshold", + "ImageMagick Auto Gamma", + "ImageMagick Auto Level", + "ImageMagick Auto Orient", + "ImageMagick Auto Threshold", + "ImageMagick Blue Shift", + "ImageMagick Blur", + "ImageMagick Brightness Contrast", + "ImageMagick Canny", + "ImageMagick Charcoal", + "ImageMagick Chop", + "ImageMagick Clahe", + "ImageMagick Clamp", + "ImageMagick Coalesce", + "ImageMagick Color Decision List", + "ImageMagick Color Matrix", + "ImageMagick Combine", + "ImageMagick Concat", + "ImageMagick Contrast", + "ImageMagick Contrast Stretch", + "ImageMagick Crop", + "ImageMagick Cycle Color Map", + "ImageMagick Decipher", + "ImageMagick Despeckle", + "ImageMagick Distort", + "ImageMagick Edge", + "ImageMagick Emboss", + "ImageMagick Encipher", + "ImageMagick Enhance", + "ImageMagick Equalize", + "ImageMagick Evaluate", + "ImageMagick Extent", + "ImageMagick Flip", + "ImageMagick Flop", + "ImageMagick Forward Fourier Transform", + "ImageMagick Function", + "ImageMagick Gamma", + "ImageMagick Gaussian Blur", + "ImageMagick Hough Lines", + "ImageMagick Implode", + "ImageMagick Kmeans", + "ImageMagick Kuwahara", + "ImageMagick Level", + "ImageMagick Levelize", + "ImageMagick Linear Stretch", + "ImageMagick Liquid Rescale", + "ImageMagick Local Contrast", + "ImageMagick Magnify", + "ImageMagick Mean Shift", + "ImageMagick Merge Layers", + "ImageMagick Mode", + "ImageMagick Modulate", + "ImageMagick Morphology", + "ImageMagick Motion Blur", + "ImageMagick Negate", + "ImageMagick Noise", + "ImageMagick Normalize", + "ImageMagick Oil Paint", + "ImageMagick Ordered Dither", + "ImageMagick Polynomial", + "ImageMagick Posterize", + "ImageMagick Quantize", + "ImageMagick Random Threshold", + "ImageMagick Range Threshold", + "ImageMagick Resample", + "ImageMagick Resize", + "ImageMagick Roll", + "ImageMagick Rotational Blur", + "ImageMagick Sample", + "ImageMagick Scale", + "ImageMagick Selective Blur", + "ImageMagick Sepia Tone", + "ImageMagick Shade", + "ImageMagick Shadow", + "ImageMagick Sharpen", + "ImageMagick Shave", + "ImageMagick Sigmoidal Contrast", + "ImageMagick Sketch", + "ImageMagick Smush", + "ImageMagick Solarize", + "ImageMagick Splice", + "ImageMagick Spread", + "ImageMagick Statistic", + "ImageMagick Swirl", + "ImageMagick Threshold", + "ImageMagick Thumbnail", + "ImageMagick Transform", + "ImageMagick Transform Colorspace", + "ImageMagick Transparentize", + "ImageMagick Transpose", + "ImageMagick Transverse", + "ImageMagick Unsharp Mask", + "ImageMagick Vignette", + "ImageMagick Wave", + "ImageMagick Wavelet Denoise", + "ImageMagick White Balance" + ], + { + "title_aux": "ComfyUI-MagickWand" + } + ], + "https://github.com/Fannovel16/ComfyUI-MotionDiff": [ + [ + "EmptyMotionData", + "ExportSMPLTo3DSoftware", + "Export_SMPLMultipleSubjects_To_3DSoftware", + "Human4D_Img2SMPL", + "Humans4DLoader", + "MotionCLIPTextEncode", + "MotionDataVisualizer", + "MotionDiffLoader", + "MotionDiffSimpleSampler", + "RenderMultipleSubjectsSMPLMesh", + "RenderSMPLMesh", + "Render_OpenPose_From_SMPL_Mesh_Multiple_Subjects", + "SMPLLoader", + "SMPLShapeParameters", + "SaveSMPL", + "SmplifyMotionData", + "SpectreFaceReconLoader", + "SpectreImg2SMPL", + "mgpt_model_loader", + "mgpt_t2m" + ], + { + "title_aux": "ComfyUI MotionDiff" + } + ], + "https://github.com/Fannovel16/ComfyUI-Video-Matting": [ + [ + "BRIAAI Matting", + "Robust Video Matting" + ], + { + "title_aux": "ComfyUI-Video-Matting" + } + ], + "https://github.com/Fannovel16/comfyui_controlnet_aux": [ + [ + "AIO_Preprocessor", + "AnimalPosePreprocessor", + "AnimeFace_SemSegPreprocessor", + "AnimeLineArtPreprocessor", + "AnyLineArtPreprocessor_aux", + "BAE-NormalMapPreprocessor", + "BinaryPreprocessor", + "CannyEdgePreprocessor", + "ColorPreprocessor", + "ControlNetPreprocessorSelector", + "DSINE-NormalMapPreprocessor", + "DWPreprocessor", + "DensePosePreprocessor", + "DepthAnythingPreprocessor", + "DepthAnythingV2Preprocessor", + "DiffusionEdge_Preprocessor", + "FacialPartColoringFromPoseKps", + "FakeScribblePreprocessor", + "HEDPreprocessor", + "HintImageEnchance", + "ImageGenResolutionFromImage", + "ImageGenResolutionFromLatent", + "ImageIntensityDetector", + "ImageLuminanceDetector", + "InpaintPreprocessor", + "LeReS-DepthMapPreprocessor", + "LineArtPreprocessor", + "LineartStandardPreprocessor", + "M-LSDPreprocessor", + "Manga2Anime_LineArt_Preprocessor", + "MaskOptFlow", + "MediaPipe-FaceMeshPreprocessor", + "MeshGraphormer+ImpactDetector-DepthMapPreprocessor", + "MeshGraphormer-DepthMapPreprocessor", + "Metric3D-DepthMapPreprocessor", + "Metric3D-NormalMapPreprocessor", + "Metric_DepthAnythingV2Preprocessor", + "MiDaS-DepthMapPreprocessor", + "MiDaS-NormalMapPreprocessor", + "OneFormer-ADE20K-SemSegPreprocessor", + "OneFormer-COCO-SemSegPreprocessor", + "OpenposePreprocessor", + "PiDiNetPreprocessor", + "PixelPerfectResolution", + "RenderAnimalKps", + "RenderPeopleKps", + "SAMPreprocessor", + "SavePoseKpsAsJsonFile", + "ScribblePreprocessor", + "Scribble_PiDiNet_Preprocessor", + "Scribble_XDoG_Preprocessor", + "SemSegPreprocessor", + "ShufflePreprocessor", + "TEEDPreprocessor", + "TTPlanet_TileGF_Preprocessor", + "TTPlanet_TileSimple_Preprocessor", + "TilePreprocessor", + "UniFormer-SemSegPreprocessor", + "Unimatch_OptFlowPreprocessor", + "UpperBodyTrackingFromPoseKps", + "Zoe-DepthMapPreprocessor", + "Zoe_DepthAnythingPreprocessor" + ], + { + "author": "tstandley", + "preemptions": [ + "AIO_Preprocessor", + "AnimalPosePreprocessor", + "AnimeFace_SemSegPreprocessor", + "AnimeLineArtPreprocessor", + "BAE-NormalMapPreprocessor", + "BinaryPreprocessor", + "CannyEdgePreprocessor", + "ColorPreprocessor", + "DSINE-NormalMapPreprocessor", + "DWPreprocessor", + "DensePosePreprocessor", + "DepthAnythingPreprocessor", + "DiffusionEdge_Preprocessor", + "FacialPartColoringFromPoseKps", + "FakeScribblePreprocessor", + "HEDPreprocessor", + "HintImageEnchance", + "ImageGenResolutionFromImage", + "ImageGenResolutionFromLatent", + "ImageIntensityDetector", + "ImageLuminanceDetector", + "InpaintPreprocessor", + "LeReS-DepthMapPreprocessor", + "LineArtPreprocessor", + "LineartStandardPreprocessor", + "M-LSDPreprocessor", + "Manga2Anime_LineArt_Preprocessor", + "MaskOptFlow", + "MediaPipe-FaceMeshPreprocessor", + "MeshGraphormer-DepthMapPreprocessor", + "MiDaS-DepthMapPreprocessor", + "MiDaS-NormalMapPreprocessor", + "OneFormer-ADE20K-SemSegPreprocessor", + "OneFormer-COCO-SemSegPreprocessor", + "OpenposePreprocessor", + "PiDiNetPreprocessor", + "PixelPerfectResolution", + "SAMPreprocessor", + "SavePoseKpsAsJsonFile", + "ScribblePreprocessor", + "Scribble_XDoG_Preprocessor", + "SemSegPreprocessor", + "ShufflePreprocessor", + "TEEDPreprocessor", + "TilePreprocessor", + "UniFormer-SemSegPreprocessor", + "Unimatch_OptFlowPreprocessor", + "Zoe-DepthMapPreprocessor", + "Zoe_DepthAnythingPreprocessor" + ], + "title_aux": "ComfyUI's ControlNet Auxiliary Preprocessors" + } + ], + "https://github.com/Fantaxico/ComfyUI-GCP-Storage": [ + [ + "GCPStorageNode" + ], + { + "title_aux": "ComfyUI-GCP-Storage" + } + ], + "https://github.com/Feidorian/feidorian-ComfyNodes": [ + [], + { + "nodename_pattern": "^Feidorian_", + "title_aux": "feidorian-ComfyNodes" + } + ], + "https://github.com/Fictiverse/ComfyUI_Fictiverse": [ + [ + "Add Noise to Image with Mask", + "Color correction", + "Displace Image with Depth", + "Displace Images with Mask", + "Zoom Image with Depth" + ], + { + "title_aux": "ComfyUI Fictiverse Nodes" + } + ], + "https://github.com/Fihade/IC-Light-ComfyUI-Node": [ + [ + "LoadICLightUnetDiffusers", + "diffusers_model_loader", + "iclight_diffusers_sampler" + ], + { + "title_aux": "IC-Light-ComfyUI-Node" + } + ], + "https://github.com/FizzleDorf/ComfyUI-AIT": [ + [ + "AIT_Unet_Loader", + "AIT_VAE_Encode_Loader" + ], + { + "title_aux": "ComfyUI-AIT" + } + ], + "https://github.com/FizzleDorf/ComfyUI_FizzNodes": [ + [ + "AbsCosWave", + "AbsSinWave", + "BatchGLIGENSchedule", + "BatchPromptSchedule", + "BatchPromptScheduleEncodeSDXL", + "BatchPromptScheduleLatentInput", + "BatchPromptScheduleNodeFlowEnd", + "BatchPromptScheduleSDXLLatentInput", + "BatchStringSchedule", + "BatchValueSchedule", + "BatchValueScheduleLatentInput", + "CalculateFrameOffset", + "ConcatStringSingle", + "CosWave", + "FizzFrame", + "FizzFrameConcatenate", + "ImagesFromBatchSchedule", + "Init FizzFrame", + "InvCosWave", + "InvSinWave", + "Lerp", + "PromptSchedule", + "PromptScheduleEncodeSDXL", + "PromptScheduleNodeFlow", + "PromptScheduleNodeFlowEnd", + "SawtoothWave", + "SinWave", + "SquareWave", + "StringConcatenate", + "StringSchedule", + "TriangleWave", + "ValueSchedule", + "convertKeyframeKeysToBatchKeys" + ], + { + "title_aux": "FizzNodes" + } + ], + "https://github.com/FlyingFireCo/tiled_ksampler": [ + [ + "Asymmetric Tiled KSampler", + "Circular VAEDecode", + "Tiled KSampler" + ], + { + "title_aux": "tiled_ksampler" + } + ], + "https://github.com/ForeignGods/ComfyUI-Mana-Nodes": [ + [ + "Canvas Properties", + "Combine Video", + "Font Properties", + "Generate Audio", + "Preset Color Animations", + "Save/Preview Text", + "Scheduled Values", + "Speech Recognition", + "Split Video", + "Text to Image Generator" + ], + { + "title_aux": "ComfyUI-Mana-Nodes" + } + ], + "https://github.com/Franck-Demongin/NX_PromptStyler": [ + [ + "NX_PromptStyler" + ], + { + "title_aux": "NX_PromptStyler" + } + ], + "https://github.com/FuouM/ComfyUI-FirstOrderMM": [ + [ + "FOMM_Partswap", + "FOMM_Runner", + "FOMM_Seg10Chooser", + "FOMM_Seg15Chooser", + "FOMM_Seg5Chooser" + ], + { + "author": "Fuou Marinas", + "description": "Run First Order Motion Model for Image Animation in ComfyUI.", + "nickname": "FOMM", + "title": "ComfyUI-FirstOrderMM", + "title_aux": "ComfyUI-FirstOrderMM" + } + ], + "https://github.com/G-370/ComfyUI-SD3-Powerlab": [ + [ + "G370SD3PowerLab_AttentionToImage", + "G370SD3PowerLab_ImageIntoAttention", + "G370SD3PowerLab_ImageIntoLayer", + "G370SD3PowerLab_LayerToImage", + "G370SD3PowerLab_RenderAttention" + ], + { + "title_aux": "ComfyUI-SD3-Powerlab" + } + ], + "https://github.com/GMapeSplat/ComfyUI_ezXY": [ + [ + "ConcatenateString", + "ItemFromDropdown", + "IterationDriver", + "JoinImages", + "LineToConsole", + "NumberFromList", + "NumbersToList", + "PlotImages", + "StringFromList", + "StringToLabel", + "StringsToList", + "ezMath", + "ezXY_AssemblePlot", + "ezXY_Driver" + ], + { + "title_aux": "ezXY scripts and nodes" + } + ], + "https://github.com/GTSuya-Studio/ComfyUI-Gtsuya-Nodes": [ + [ + "Danbooru (ID)", + "Danbooru (Random)", + "Random File From Path", + "Replace Strings", + "Simple Wildcards", + "Simple Wildcards (Dir.)", + "Wildcards Nodes" + ], + { + "title_aux": "ComfyUI-GTSuya-Nodes" + } + ], + "https://github.com/GavChap/ComfyUI-SD3LatentSelectRes": [ + [ + "SD3LatentSelectRes" + ], + { + "title_aux": "ComfyUI-SD3LatentSelectRes" + } + ], + "https://github.com/GentlemanHu/ComfyUI-SunoAI": [ + [ + "GentlemanHu_SunoAI", + "GentlemanHu_SunoAI_NotSafe" + ], + { + "title_aux": "ComfyUI Suno API" + } + ], + "https://github.com/Goktug/comfyui-saveimage-plus": [ + [ + "SaveImagePlus" + ], + { + "title_aux": "Save Image Plus for ComfyUI" + } + ], + "https://github.com/Gourieff/comfyui-reactor-node": [ + [ + "ImageRGBA2RGB", + "ReActorBuildFaceModel", + "ReActorFaceBoost", + "ReActorFaceSwap", + "ReActorFaceSwapOpt", + "ReActorImageDublicator", + "ReActorLoadFaceModel", + "ReActorMakeFaceModelBatch", + "ReActorMaskHelper", + "ReActorOptions", + "ReActorRestoreFace", + "ReActorSaveFaceModel" + ], + { + "title_aux": "ReActor Node for ComfyUI" + } + ], + "https://github.com/GraftingRayman/ComfyUI_GraftingRayman": [ + [ + "GR Background Remover REMBG", + "GR Checkered Board", + "GR Counter", + "GR Flip Tile Random Inverted", + "GR Flip Tile Random Red Ring", + "GR Image Details Displayer", + "GR Image Details Saver", + "GR Image Paste", + "GR Image Paste With Mask", + "GR Image Resize", + "GR Image Resize Methods", + "GR Image Size", + "GR Image/Depth Mask", + "GR Mask Create", + "GR Mask Create Random", + "GR Mask Resize", + "GR Multi Mask Create", + "GR Onomatopoeia", + "GR Prompt HUB", + "GR Prompt Selector", + "GR Prompt Selector Multi", + "GR Scroller", + "GR Stack Image", + "GR Text Overlay", + "GR Tile and Border Image", + "GR Tile and Border Image Random Flip" + ], + { + "title_aux": "GraftingRayman" + } + ], + "https://github.com/Grant-CP/ComfyUI-LivePortraitKJ-MPS": [ + [ + "DownloadAndLoadLivePortraitModels", + "LivePortraitProcess" + ], + { + "title_aux": "ComfyUI-LivePortraitKJ-MPS" + } + ], + "https://github.com/GreenLandisaLie/AuraSR-ComfyUI": [ + [ + "AuraSR.AuraSRUpscaler" + ], + { + "title_aux": "AuraSR-ComfyUI" + } + ], + "https://github.com/Guillaume-Fgt/ComfyUI_StableCascadeLatentRatio": [ + [ + "StableCascadeLatentRatio" + ], + { + "title_aux": "ComfyUI_StableCascadeLatentRatio" + } + ], + "https://github.com/HAL41/ComfyUI-aichemy-nodes": [ + [ + "aichemyYOLOv8Segmentation" + ], + { + "title_aux": "ComfyUI aichemy nodes" + } + ], + "https://github.com/HECer/ComfyUI-FilePathCreator": [ + [ + "FilePathCreator" + ], + { + "title_aux": "ComfyUI-FilePathCreator" + } + ], + "https://github.com/Hangover3832/ComfyUI-Hangover-Moondream": [ + [ + "Moondream Interrogator" + ], + { + "author": "AlexL", + "description": "An implementation of the moondream visual LLM", + "nickname": "Hangover-Moondream", + "title": "ComfyUI-Hangover-Moondream", + "title_aux": "ComfyUI-Hangover-Moondream" + } + ], + "https://github.com/Hangover3832/ComfyUI-Hangover-Nodes": [ + [ + "Image Scale Bounding Box", + "MS kosmos-2 Interrogator", + "Make Inpaint Model", + "Save Image w/o Metadata" + ], + { + "author": "AlexL", + "description": "Scales an input image into a given box size, whereby the aspect ratio keeps retained.", + "nickname": "Hangover-Image_Scale_Bouning_Box", + "title": "ComfyUI-Hangover-Image_Scale_Bouning_Box", + "title_aux": "ComfyUI-Hangover-Nodes" + } + ], + "https://github.com/Hangover3832/ComfyUI-Hangover-Recognize_Anything": [ + [ + "Recognize Anything Model (RAM)" + ], + { + "author": "AlexL", + "description": "An implementation of the Recognize Anything Model (RAM++) for ComfyUI. The counterpart of Segment Anything Model (SAM).", + "nickname": "Hangover-Recognize_Anything", + "title": "ComfyUI-Hangover-Recognize_Anything", + "title_aux": "Recognize Anything Model (RAM) for ComfyUI" + } + ], + "https://github.com/Haoming02/comfyui-diffusion-cg": [ + [ + "Normalization", + "NormalizationXL", + "Recenter", + "Recenter XL" + ], + { + "title_aux": "ComfyUI Diffusion Color Grading" + } + ], + "https://github.com/Haoming02/comfyui-floodgate": [ + [ + "FloodGate" + ], + { + "title_aux": "ComfyUI Floodgate" + } + ], + "https://github.com/HaydenReeve/ComfyUI-Better-Strings": [ + [ + "BetterString" + ], + { + "title_aux": "ComfyUI Better Strings" + } + ], + "https://github.com/HebelHuber/comfyui-enhanced-save-node": [ + [ + "EnhancedSaveNode" + ], + { + "title_aux": "comfyui-enhanced-save-node" + } + ], + "https://github.com/Hiero207/ComfyUI-Hiero-Nodes": [ + [ + "Load Prompt Travel file", + "Post to Discord w/ Webhook", + "Save Prompt Travel file" + ], + { + "author": "Hiero", + "description": "Just some nodes that I wanted/needed, so I made them.", + "nickname": "HNodes", + "title": "Hiero-Nodes", + "title_aux": "Hiero-Nodes" + } + ], + "https://github.com/IDGallagher/ComfyUI-IG-Nodes": [ + [ + "IG Analyze SSIM", + "IG Cross Fade Images", + "IG Explorer", + "IG Float", + "IG Float List", + "IG Folder", + "IG Int", + "IG Interpolate", + "IG Load Image", + "IG Load Images", + "IG Multiply", + "IG Path Join", + "IG String", + "IG String List", + "IG ZFill" + ], + { + "author": "IDGallagher", + "description": "Custom nodes to aid in the exploration of Latent Space", + "nickname": "IG Interpolation Nodes", + "title": "IG Interpolation Nodes", + "title_aux": "IG Interpolation Nodes" + } + ], + "https://github.com/ITurchenko/ComfyUI-SizeFromArray": [ + [ + "SizeFromArray" + ], + { + "title_aux": "ComfyUI-SizeFromArray" + } + ], + "https://github.com/ImmortalPie/ComfyUI-PonySwitch/raw/main/PonySwitch.py": [ + [ + "PonySwitch" + ], + { + "title_aux": "PonySwitch Node" + } + ], + "https://github.com/Intersection98/ComfyUI_MX_post_processing-nodes": [ + [ + "MX_AlphaBlend", + "MX_Blend", + "MX_Blur", + "MX_Canny", + "MX_ChromaticAberration", + "MX_ColorCorrect", + "MX_ColorMatch", + "MX_ColorTint", + "MX_Glow", + "MX_HSVThresholdMask", + "MX_KuwaharaBlur(Cartoon)", + "MX_LUT", + "MX_LensBokeh", + "MX_LensOpticAxis", + "MX_LensZoomBurst", + "MX_Mosaic", + "MX_Noise", + "MX_Posterize", + "MX_SineWave", + "MX_Solarize", + "MX_Vignette" + ], + { + "title_aux": "ComfyUI-MX-post-processing-nodes" + } + ], + "https://github.com/Inzaniak/comfyui-ranbooru": [ + [ + "LockSeed", + "PromptBackground", + "PromptLimit", + "PromptMix", + "PromptRandomWeight", + "PromptRemove", + "Ranbooru", + "RanbooruURL", + "RandomPicturePath", + "TimestampFileName" + ], + { + "title_aux": "Ranbooru for ComfyUI" + } + ], + "https://github.com/IsItDanOrAi/ComfyUI-Stereopsis": [ + [ + "Dan_FrameDelay", + "Dan_Stereopsis" + ], + { + "title_aux": "ComfyUI-Stereopsis" + } + ], + "https://github.com/JPS-GER/ComfyUI_JPS-Nodes": [ + [ + "CLIPTextEncode SDXL Plus (JPS)", + "Conditioning Switch (JPS)", + "ControlNet Switch (JPS)", + "Crop Image Pipe (JPS)", + "Crop Image Settings (JPS)", + "Crop Image Square (JPS)", + "Crop Image TargetSize (JPS)", + "CtrlNet CannyEdge Pipe (JPS)", + "CtrlNet CannyEdge Settings (JPS)", + "CtrlNet MiDaS Pipe (JPS)", + "CtrlNet MiDaS Settings (JPS)", + "CtrlNet OpenPose Pipe (JPS)", + "CtrlNet OpenPose Settings (JPS)", + "CtrlNet ZoeDepth Pipe (JPS)", + "CtrlNet ZoeDepth Settings (JPS)", + "Disable Enable Switch (JPS)", + "Enable Disable Switch (JPS)", + "Generation TXT IMG Settings (JPS)", + "Get Date Time String (JPS)", + "Get Image Size (JPS)", + "IP Adapter Settings (JPS)", + "IP Adapter Settings Pipe (JPS)", + "IP Adapter Tiled Settings (JPS)", + "IP Adapter Tiled Settings Pipe (JPS)", + "IPA Switch (JPS)", + "Image Prepare Pipe (JPS)", + "Image Prepare Settings (JPS)", + "Image Switch (JPS)", + "ImageToImage Pipe (JPS)", + "ImageToImage Settings (JPS)", + "Images Masks MultiPipe (JPS)", + "InstantID Mask Prepare Pipe (JPS)", + "InstantID Mask Prepare Settings (JPS)", + "InstantID Pipe (JPS)", + "InstantID Pose Prepare Pipe (JPS)", + "InstantID Pose Prepare Settings (JPS)", + "InstantID Settings (JPS)", + "InstantID Source Prepare Pipe (JPS)", + "InstantID Source Prepare Settings (JPS)", + "Integer Switch (JPS)", + "Largest Int (JPS)", + "Latent Switch (JPS)", + "Lora Loader (JPS)", + "Mask Switch (JPS)", + "Model Switch (JPS)", + "Multiply Float Float (JPS)", + "Multiply Int Float (JPS)", + "Multiply Int Int (JPS)", + "Prepare Image (JPS)", + "Prepare Image Plus (JPS)", + "Prepare Image Tiled IPA (JPS)", + "Resolution Multiply (JPS)", + "Revision Settings (JPS)", + "Revision Settings Pipe (JPS)", + "SDXL Basic Settings (JPS)", + "SDXL Basic Settings Pipe (JPS)", + "SDXL Fundamentals MultiPipe (JPS)", + "SDXL Prompt Handling (JPS)", + "SDXL Prompt Handling Plus (JPS)", + "SDXL Prompt Styler (JPS)", + "SDXL Recommended Resolution Calc (JPS)", + "SDXL Resolutions (JPS)", + "SDXL Settings (JPS)", + "SDXL Settings Pipe (JPS)", + "Sampler Scheduler Settings (JPS)", + "Save Images Plus (JPS)", + "Substract Int Int (JPS)", + "Text Concatenate (JPS)", + "Text Prompt (JPS)", + "Text Prompt Combo (JPS)", + "Time Seed (JPS)", + "VAE Switch (JPS)" + ], + { + "author": "JPS", + "description": "Various nodes to handle SDXL Resolutions, SDXL Basic Settings, IP Adapter Settings, Revision Settings, SDXL Prompt Styler, Crop Image to Square, Crop Image to Target Size, Get Date-Time String, Resolution Multiply, Largest Integer, 5-to-1 Switches for Integer, Images, Latents, Conditioning, Model, VAE, ControlNet", + "nickname": "JPS Custom Nodes", + "title": "JPS Custom Nodes for ComfyUI", + "title_aux": "JPS Custom Nodes for ComfyUI" + } + ], + "https://github.com/Jannchie/ComfyUI-J": [ + [ + "DiffusersCompelPromptEmbedding", + "DiffusersControlnetLoader", + "DiffusersControlnetUnit", + "DiffusersControlnetUnitStack", + "DiffusersDecoder", + "DiffusersGenerator", + "DiffusersPipeline", + "DiffusersPrepareLatents", + "DiffusersTextureInversionLoader", + "DiffusersXLPipeline", + "GetAverageColorFromImage", + "GetFilledColorImage" + ], + { + "title_aux": "ComfyUI-J" + } + ], + "https://github.com/JaredTherriault/ComfyUI-JNodes": [ + [ + "JNodes_AddOrSetMetaDataKey", + "JNodes_AnyToString", + "JNodes_AppendReversedFrames", + "JNodes_BooleanSelectorWithString", + "JNodes_BreakMediaInfo", + "JNodes_CheckpointSelectorWithString", + "JNodes_CreateStereoscopicImageFromDepth", + "JNodes_GetOutputDirectory", + "JNodes_GetParameterFromList", + "JNodes_GetParameterGlobal", + "JNodes_GetTempDirectory", + "JNodes_ImageFormatSelector", + "JNodes_ImageSizeSelector", + "JNodes_LoadVideo", + "JNodes_LoadVisualMediaFromPath", + "JNodes_LoraExtractor", + "JNodes_MediaInfoToString", + "JNodes_OutVideoInfo", + "JNodes_ParseDynamicPrompts", + "JNodes_ParseParametersToGlobalList", + "JNodes_ParseWildcards", + "JNodes_PromptBuilderSingleSubject", + "JNodes_RemoveCommentedText", + "JNodes_RemoveMetaDataKey", + "JNodes_RemoveParseableDataForInference", + "JNodes_SamplerSelectorWithString", + "JNodes_SaveImageWithOutput", + "JNodes_SaveVideo", + "JNodes_SchedulerSelectorWithString", + "JNodes_SearchAndReplace", + "JNodes_SearchAndReplaceFromFile", + "JNodes_SearchAndReplaceFromList", + "JNodes_SelectRandomFileFromDirectory", + "JNodes_SetNegativePromptInMetaData", + "JNodes_SetPositivePromptInMetaData", + "JNodes_SplitAndJoin", + "JNodes_StringLiteral", + "JNodes_SyncedStringLiteral", + "JNodes_TokenCounter", + "JNodes_TrimAndStrip", + "JNodes_UploadVideo", + "JNodes_UploadVisualMedia", + "JNodes_VaeSelectorWithString" + ], + { + "title_aux": "ComfyUI-JNodes" + } + ], + "https://github.com/JayLyu/ComfyUI_BaiKong_Node": [ + [ + "BK_ColorLimit", + "BK_ColorSelector", + "BK_GradientImage", + "BK_Img2Color" + ], + { + "title_aux": "ComfyUI_BaiKong_Node" + } + ], + "https://github.com/JcandZero/ComfyUI_GLM4Node": [ + [ + "GLM3_turbo_CHAT", + "GLM4_CHAT", + "GLM4_Vsion_IMGURL" + ], + { + "title_aux": "ComfyUI_GLM4Node" + } + ], + "https://github.com/Jcd1230/rembg-comfyui-node": [ + [ + "Image Remove Background (rembg)" + ], + { + "title_aux": "Rembg Background Removal Node for ComfyUI" + } + ], + "https://github.com/JerryOrbachJr/ComfyUI-RandomSize": [ + [ + "JOJR_RandomSize" + ], + { + "author": "JerryOrbachJr", + "description": "A ComfyUI custom node that randomly selects a height and width pair from a list in a config file", + "nickname": "Random Size", + "title": "Random Size", + "title_aux": "Random Size" + } + ], + "https://github.com/JettHu/ComfyUI-TCD": [ + [ + "TCDModelSamplingDiscrete" + ], + { + "title_aux": "ComfyUI-TCD" + } + ], + "https://github.com/JettHu/ComfyUI_TGate": [ + [ + "TGateApply", + "TGateApplyAdvanced", + "TGateApplySimple" + ], + { + "title_aux": "ComfyUI_TGate" + } + ], + "https://github.com/Jordach/comfy-plasma": [ + [ + "JDC_AutoContrast", + "JDC_BlendImages", + "JDC_BrownNoise", + "JDC_Contrast", + "JDC_EqualizeGrey", + "JDC_GaussianBlur", + "JDC_GreyNoise", + "JDC_Greyscale", + "JDC_ImageLoader", + "JDC_ImageLoaderMeta", + "JDC_PinkNoise", + "JDC_Plasma", + "JDC_PlasmaSampler", + "JDC_PowerImage", + "JDC_RandNoise", + "JDC_ResizeFactor" + ], + { + "title_aux": "comfy-plasma" + } + ], + "https://github.com/Kangkang625/ComfyUI-paint-by-example": [ + [ + "PaintbyExamplePipeLoader", + "PaintbyExampleSampler" + ], + { + "title_aux": "ComfyUI-Paint-by-Example" + } + ], + "https://github.com/KewkLW/ComfyUI-kewky_tools": [ + [ + "CLIPInterrogator", + "FormattedPromptNode", + "ImageBatcher", + "LoadImagePlus", + "LoadVideoPlus", + "TensorDebugPlus", + "TextAppendNode", + "TextSearchNode", + "VRAM_Debug_Plus" + ], + { + "title_aux": "ComfyUI-kewky_tools" + } + ], + "https://github.com/KoreTeknology/ComfyUI-Universal-Styler": [ + [ + "Load Nai Styles Complex CSV", + "ShowText|pysssss", + "Universal_Styler_Node", + "concat" + ], + { + "title_aux": "ComfyUI Universal Styler" + } + ], + "https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet": [ + [ + "ACN_AdvancedControlNetApply", + "ACN_ControlNetLoaderWithLoraAdvanced", + "ACN_DefaultUniversalWeights", + "ACN_ReferenceControlNet", + "ACN_ReferenceControlNetFinetune", + "ACN_ReferencePreprocessor", + "ACN_SparseCtrlIndexMethodNode", + "ACN_SparseCtrlLoaderAdvanced", + "ACN_SparseCtrlMergedLoaderAdvanced", + "ACN_SparseCtrlRGBPreprocessor", + "ACN_SparseCtrlSpreadMethodNode", + "ACN_SparseCtrlWeightExtras", + "ACN_TimestepKeyframeFromStrengthList", + "ACN_TimestepKeyframeInterpolation", + "ControlNetLoaderAdvanced", + "CustomControlNetWeights", + "CustomT2IAdapterWeights", + "DiffControlNetLoaderAdvanced", + "LatentKeyframe", + "LatentKeyframeBatchedGroup", + "LatentKeyframeGroup", + "LatentKeyframeTiming", + "LoadImagesFromDirectory", + "ScaledSoftControlNetWeights", + "ScaledSoftMaskedUniversalWeights", + "SoftControlNetWeights", + "SoftT2IAdapterWeights", + "TimestepKeyframe" + ], + { + "title_aux": "ComfyUI-Advanced-ControlNet" + } + ], + "https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved": [ + [ + "ADE_AdjustPEFullStretch", + "ADE_AdjustPEManual", + "ADE_AdjustPESweetspotStretch", + "ADE_AdjustWeightAllAdd", + "ADE_AdjustWeightAllMult", + "ADE_AdjustWeightIndivAdd", + "ADE_AdjustWeightIndivAttnAdd", + "ADE_AdjustWeightIndivAttnMult", + "ADE_AdjustWeightIndivMult", + "ADE_AnimateDiffCombine", + "ADE_AnimateDiffKeyframe", + "ADE_AnimateDiffLoRALoader", + "ADE_AnimateDiffLoaderGen1", + "ADE_AnimateDiffLoaderV1Advanced", + "ADE_AnimateDiffLoaderWithContext", + "ADE_AnimateDiffModelSettings", + "ADE_AnimateDiffModelSettingsAdvancedAttnStrengths", + "ADE_AnimateDiffModelSettingsSimple", + "ADE_AnimateDiffModelSettings_Release", + "ADE_AnimateDiffSamplingSettings", + "ADE_AnimateDiffSettings", + "ADE_AnimateDiffUniformContextOptions", + "ADE_AnimateDiffUnload", + "ADE_ApplyAnimateDiffModel", + "ADE_ApplyAnimateDiffModelSimple", + "ADE_ApplyAnimateDiffModelWithCameraCtrl", + "ADE_ApplyAnimateDiffModelWithPIA", + "ADE_ApplyAnimateLCMI2VModel", + "ADE_AttachLoraHookToCLIP", + "ADE_AttachLoraHookToConditioning", + "ADE_BatchedContextOptions", + "ADE_CameraCtrlAnimateDiffKeyframe", + "ADE_CameraManualPoseAppend", + "ADE_CameraPoseAdvanced", + "ADE_CameraPoseBasic", + "ADE_CameraPoseCombo", + "ADE_CombineLoraHooks", + "ADE_CombineLoraHooksEight", + "ADE_CombineLoraHooksFour", + "ADE_ConditioningSetMask", + "ADE_ConditioningSetMaskAndCombine", + "ADE_ConditioningSetUnmaskedAndCombine", + "ADE_CustomCFG", + "ADE_CustomCFGKeyframe", + "ADE_EmptyLatentImageLarge", + "ADE_InjectI2VIntoAnimateDiffModel", + "ADE_InjectPIAIntoAnimateDiffModel", + "ADE_InputPIA_Multival", + "ADE_InputPIA_PaperPresets", + "ADE_IterationOptsDefault", + "ADE_IterationOptsFreeInit", + "ADE_LoadAnimateDiffModel", + "ADE_LoadAnimateDiffModelWithCameraCtrl", + "ADE_LoadAnimateLCMI2VModel", + "ADE_LoadCameraPoses", + "ADE_LoopedUniformContextOptions", + "ADE_LoopedUniformViewOptions", + "ADE_LoraHookKeyframe", + "ADE_LoraHookKeyframeFromStrengthList", + "ADE_LoraHookKeyframeInterpolation", + "ADE_MultivalConvertToMask", + "ADE_MultivalDynamic", + "ADE_MultivalDynamicFloatInput", + "ADE_MultivalScaledMask", + "ADE_NoiseLayerAdd", + "ADE_NoiseLayerAddWeighted", + "ADE_NoiseLayerReplace", + "ADE_NoisedImageInjectOptions", + "ADE_NoisedImageInjection", + "ADE_PIA_AnimateDiffKeyframe", + "ADE_PairedConditioningSetMask", + "ADE_PairedConditioningSetMaskAndCombine", + "ADE_PairedConditioningSetUnmaskedAndCombine", + "ADE_RawSigmaSchedule", + "ADE_RegisterLoraHook", + "ADE_RegisterLoraHookModelOnly", + "ADE_RegisterModelAsLoraHook", + "ADE_RegisterModelAsLoraHookModelOnly", + "ADE_ReplaceCameraParameters", + "ADE_ReplaceOriginalPoseAspectRatio", + "ADE_SetLoraHookKeyframe", + "ADE_SigmaSchedule", + "ADE_SigmaScheduleSplitAndCombine", + "ADE_SigmaScheduleWeightedAverage", + "ADE_SigmaScheduleWeightedAverageInterp", + "ADE_StandardStaticContextOptions", + "ADE_StandardStaticViewOptions", + "ADE_StandardUniformContextOptions", + "ADE_StandardUniformViewOptions", + "ADE_TimestepsConditioning", + "ADE_UpscaleAndVAEEncode", + "ADE_UseEvolvedSampling", + "ADE_ViewsOnlyContextOptions", + "AnimateDiffLoaderV1", + "CheckpointLoaderSimpleWithNoiseSelect" + ], + { + "title_aux": "AnimateDiff Evolved" + } + ], + "https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite": [ + [ + "VHS_AudioToVHSAudio", + "VHS_BatchManager", + "VHS_DuplicateImages", + "VHS_DuplicateLatents", + "VHS_DuplicateMasks", + "VHS_GetImageCount", + "VHS_GetLatentCount", + "VHS_GetMaskCount", + "VHS_LoadAudio", + "VHS_LoadAudioUpload", + "VHS_LoadImages", + "VHS_LoadImagesPath", + "VHS_LoadVideo", + "VHS_LoadVideoPath", + "VHS_MergeImages", + "VHS_MergeLatents", + "VHS_MergeMasks", + "VHS_PruneOutputs", + "VHS_SelectEveryNthImage", + "VHS_SelectEveryNthLatent", + "VHS_SelectEveryNthMask", + "VHS_SplitImages", + "VHS_SplitLatents", + "VHS_SplitMasks", + "VHS_VAEDecodeBatched", + "VHS_VAEEncodeBatched", + "VHS_VHSAudioToAudio", + "VHS_VideoCombine", + "VHS_VideoInfo", + "VHS_VideoInfoLoaded", + "VHS_VideoInfoSource" + ], + { + "title_aux": "ComfyUI-VideoHelperSuite" + } + ], + "https://github.com/KytraScript/ComfyUI_KytraWebhookHTTP": [ + [ + "SendToDiscordWebhook" + ], + { + "title_aux": "ComfyUI_KytraWebhookHTTP" + } + ], + "https://github.com/LEv145/images-grid-comfy-plugin": [ + [ + "GridAnnotation", + "ImageCombine", + "ImagesGridByColumns", + "ImagesGridByRows", + "LatentCombine" + ], + { + "title_aux": "ImagesGrid" + } + ], + "https://github.com/LarryJane491/Image-Captioning-in-ComfyUI": [ + [ + "LoRA Caption Load", + "LoRA Caption Save" + ], + { + "title_aux": "Image-Captioning-in-ComfyUI" + } + ], + "https://github.com/LarryJane491/Lora-Training-in-Comfy": [ + [ + "Lora Training in Comfy (Advanced)", + "Lora Training in ComfyUI", + "Tensorboard Access" + ], + { + "title_aux": "Lora-Training-in-Comfy" + } + ], + "https://github.com/Layer-norm/comfyui-lama-remover": [ + [ + "LamaRemover", + "LamaRemoverIMG" + ], + { + "title_aux": "Comfyui lama remover" + } + ], + "https://github.com/Lerc/canvas_tab": [ + [ + "Canvas_Tab", + "Send_To_Editor" + ], + { + "author": "Lerc", + "description": "This extension provides a full page image editor with mask support. There are two nodes, one to receive images from the editor and one to send images to the editor.", + "nickname": "Canvas Tab", + "title": "Canvas Tab", + "title_aux": "Canvas Tab" + } + ], + "https://github.com/Limitex/ComfyUI-Calculation": [ + [ + "CenterCalculation", + "CreateQRCode" + ], + { + "title_aux": "ComfyUI-Calculation" + } + ], + "https://github.com/Limitex/ComfyUI-Diffusers": [ + [ + "CreateIntListNode", + "DiffusersClipTextEncode", + "DiffusersModelMakeup", + "DiffusersPipelineLoader", + "DiffusersSampler", + "DiffusersSchedulerLoader", + "DiffusersVaeLoader", + "LcmLoraLoader", + "StreamDiffusionCreateStream", + "StreamDiffusionFastSampler", + "StreamDiffusionSampler", + "StreamDiffusionWarmup" + ], + { + "title_aux": "ComfyUI-Diffusers" + } + ], + "https://github.com/Loewen-Hob/rembg-comfyui-node-better": [ + [ + "Image Remove Background (rembg)" + ], + { + "title_aux": "Rembg Background Removal Node for ComfyUI (Better)" + } + ], + "https://github.com/LonicaMewinsky/ComfyUI-MakeFrame": [ + [ + "BreakFrames", + "BreakGrid", + "GetKeyFrames", + "MakeGrid", + "RandomImageFromDir" + ], + { + "title_aux": "ComfyBreakAnim" + } + ], + "https://github.com/LonicaMewinsky/ComfyUI-RawSaver": [ + [ + "SaveTifImage" + ], + { + "title_aux": "ComfyUI-RawSaver" + } + ], + "https://github.com/Ludobico/ComfyUI-ScenarioPrompt": [ + [ + "ScenarioPrompt" + ], + { + "title_aux": "ComfyUI-ScenarioPrompt" + } + ], + "https://github.com/LyazS/comfyui-anime-seg": [ + [ + "Anime Character Seg" + ], + { + "title_aux": "Anime Character Segmentation node for comfyui" + } + ], + "https://github.com/M1kep/ComfyLiterals": [ + [ + "Checkpoint", + "Float", + "Int", + "KepStringLiteral", + "Lora", + "Operation", + "String" + ], + { + "title_aux": "ComfyLiterals" + } + ], + "https://github.com/M1kep/ComfyUI-KepOpenAI": [ + [ + "KepOpenAI_ImageWithPrompt" + ], + { + "title_aux": "ComfyUI-KepOpenAI" + } + ], + "https://github.com/M1kep/ComfyUI-OtherVAEs": [ + [ + "OtherVAE_Taesd" + ], + { + "title_aux": "ComfyUI-OtherVAEs" + } + ], + "https://github.com/M1kep/Comfy_KepKitchenSink": [ + [ + "KepRotateImage" + ], + { + "title_aux": "Comfy_KepKitchenSink" + } + ], + "https://github.com/M1kep/Comfy_KepListStuff": [ + [ + "Empty Images", + "Image Overlay", + "ImageListLoader", + "Join Float Lists", + "Join Image Lists", + "KepStringList", + "KepStringListFromNewline", + "Kep_JoinListAny", + "Kep_RepeatList", + "Kep_ReverseList", + "Kep_VariableImageBuilder", + "List Length", + "Range(Num Steps) - Float", + "Range(Num Steps) - Int", + "Range(Step) - Float", + "Range(Step) - Int", + "Stack Images", + "XYAny", + "XYImage" + ], + { + "title_aux": "Comfy_KepListStuff" + } + ], + "https://github.com/M1kep/Comfy_KepMatteAnything": [ + [ + "MatteAnything_DinoBoxes", + "MatteAnything_GenerateVITMatte", + "MatteAnything_InitSamPredictor", + "MatteAnything_LoadDINO", + "MatteAnything_LoadVITMatteModel", + "MatteAnything_SAMLoader", + "MatteAnything_SAMMaskFromBoxes", + "MatteAnything_ToTrimap" + ], + { + "title_aux": "Comfy_KepMatteAnything" + } + ], + "https://github.com/M1kep/KepPromptLang": [ + [ + "Build Gif", + "Special CLIP Loader" + ], + { + "title_aux": "KepPromptLang" + } + ], + "https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes": [ + [ + "\u26d4 Generate Negative Prompt", + "\u2728 Groq LLM API", + "\ud83d\udcbe Save Text File With Path", + "\ud83d\uddbc\ufe0f Download Image from URL" + ], + { + "title_aux": "ComfyUI-mnemic-nodes" + } + ], + "https://github.com/Makeezi/ComfyUI-promptLAB": [ + [ + "PromptLAB" + ], + { + "title_aux": "ComfyUI-promptLAB" + } + ], + "https://github.com/Mamaaaamooooo/batchImg-rembg-ComfyUI-nodes": [ + [ + "Image Remove Background (rembg)" + ], + { + "title_aux": "Batch Rembg for ComfyUI" + } + ], + "https://github.com/ManglerFTW/ComfyI2I": [ + [ + "Color Transfer", + "Combine and Paste", + "Inpaint Segments", + "Mask Ops" + ], + { + "author": "ManglerFTW", + "title": "ComfyI2I", + "title_aux": "ComfyI2I" + } + ], + "https://github.com/MaraScott/ComfyUI_MaraScott_Nodes": [ + [ + "MaraScottAnyBusNode", + "MaraScottAnyBus_v2", + "MaraScottDisplayInfoNode", + "MaraScottDisplayInfo_v1", + "MaraScottPasteInpaintingByMask_v1", + "MaraScottPromptFromImage_v1", + "MaraScottSetInpaintingByMask_v1", + "MaraScottUpscalerRefinerNode_v2", + "MaraScottUpscalerRefinerNode_v3", + "MaraScott_Kijai_TokenCounter_v1", + "McBoaty_Refiner_v4", + "McBoaty_TilePrompter_v4", + "McBoaty_Upscaler_v4" + ], + { + "title_aux": "\ud83d\udc30 MaraScott Nodes" + } + ], + "https://github.com/MarcusNyne/m9-prompts-comfyui": [ + [ + "ScramblePrompts_m9", + "TweakWeights_m9" + ], + { + "title_aux": "m9-prompts-comfyui" + } + ], + "https://github.com/MariusKM/ComfyUI-BadmanNodes": [ + [ + "BadmanCLIPTextEncodeSDXLRegion", + "BadmanIO", + "BadmanIntUtil", + "BadmanStringSelect", + "Badman_Blend", + "Badman_Concat_String", + "Badman_HexGenerator", + "Badman_Print", + "Badman_String" + ], + { + "title_aux": "ComfyUI-BadmanNodes" + } + ], + "https://github.com/MarkoCa1/ComfyUI-Text": [ + [ + "CombinationText", + "PlaceholderText", + "ReplaceText", + "ShowText" + ], + { + "title_aux": "ComfyUI-Text" + } + ], + "https://github.com/MarkoCa1/ComfyUI_Segment_Mask": [ + [ + "AutomaticMask(segment anything)" + ], + { + "title_aux": "ComfyUI_Segment_Mask" + } + ], + "https://github.com/Mason-McGough/ComfyUI-Mosaica": [ + [ + "ApplyLUTToLabelImage", + "KMeans", + "LoadLUTFromMatplotlib", + "MeanShift", + "RandomLUT", + "Watershed" + ], + { + "title_aux": "Mosaica" + } + ], + "https://github.com/MilitantHitchhiker/MilitantHitchhiker-SwitchbladePack": [ + [ + "IntegratedRandomPromptGenerator", + "TextAppender" + ], + { + "author": "Militant Hitchhiker", + "description": "Militant Hitchhiker's multi-function nodes.", + "nickname": "Switchblade", + "title": "Switchblade Pack", + "title_aux": "Militant Hitchhiker's Switchblade Pack" + } + ], + "https://github.com/Miosp/ComfyUI-FBCNN": [ + [ + "JPEG artifacts removal FBCNN" + ], + { + "title_aux": "ComfyUI-FBCNN" + } + ], + "https://github.com/MitoshiroPJ/comfyui_slothful_attention": [ + [ + "NearSightedAttention", + "NearSightedAttentionSimple", + "NearSightedTile", + "SlothfulAttention" + ], + { + "title_aux": "ComfyUI Slothful Attention" + } + ], + "https://github.com/MokkaBoss1/ComfyUI_Mokkaboss1": [ + [ + "AnimeCosplayDir", + "AspectRatioCondition", + "ChooseImage", + "Colors", + "CombinedCrop", + "ConnectFloat", + "ConnectImage", + "ConnectInteger", + "ConnectLatent", + "ConnectString", + "DirSelector", + "DoubleClipTextEncode", + "EmbeddingLoader", + "FilmCharDir", + "FuseImages", + "FuseImages2", + "HashText", + "HueSatLum", + "HueShift", + "ImageDimensions", + "ImageDimensionsBatch", + "ImageOverlayResized", + "ImageResizeLong", + "ImageZigzag", + "IndoorBackgrounds", + "IndoorDir", + "IntEvaluate", + "IntFloatDict", + "IntStringDict", + "JsonSearch", + "KillWorkflow", + "LandscapeBackgrounds", + "LandscapeDir", + "MakeupStylesDir", + "Mbsampler", + "OptimalCrop", + "Overlay", + "PhotomontageA", + "PhotomontageB", + "PhotomontageC", + "PostSamplerCrop", + "PresetLoad", + "PresetRemove", + "PresetSave", + "PromptSwitcher", + "RandomString", + "SDXLEmptyLatent", + "SavePrompt", + "SaveWithMetaData", + "SaveWithMetaData2", + "SearchReplace", + "SimplePrompts", + "SpecificStylesDir", + "SplitImages", + "StringJoin", + "TimeStamp", + "TintnShift", + "TricolorComposition", + "WorkflowSettings", + "WrapText", + "X_In_a_Dress", + "X_In_a_Suit", + "X_In_a_Suit)", + "ZoomCrop", + "imageborder" + ], + { + "title_aux": "Node Pack mostly for manipulating strings and integers" + } + ], + "https://github.com/MrForExample/ComfyUI-3D-Pack": [ + [], + { + "nodename_pattern": "^\\[Comfy3D\\]", + "title_aux": "ComfyUI-3D-Pack" + } + ], + "https://github.com/MrForExample/ComfyUI-AnimateAnyone-Evolved": [ + [], + { + "nodename_pattern": "^\\[AnimateAnyone\\]", + "title_aux": "ComfyUI-AnimateAnyone-Evolved" + } + ], + "https://github.com/MrSamSeen/ComfyUI_SSStereoscope": [ + [ + "SBS_by_SamSeen" + ], + { + "title_aux": "ComfyUI_SSStereoscope" + } + ], + "https://github.com/Munkyfoot/ComfyUI-TextOverlay": [ + [ + "Text Overlay" + ], + { + "title_aux": "ComfyUI-TextOverlay" + } + ], + "https://github.com/NeuralSamurAI/Comfyui-Superprompt-Unofficial": [ + [ + "SuperPrompterNode" + ], + { + "title_aux": "SuperPrompter Node for ComfyUI" + } + ], + "https://github.com/NicholasMcCarthy/ComfyUI_TravelSuite": [ + [ + "LatentTravel" + ], + { + "title_aux": "ComfyUI_TravelSuite" + } + ], + "https://github.com/NimaNzrii/comfyui-photoshop": [ + [ + "\ud83d\udd39 Photoshop RemoteConnection", + "\ud83d\udd39Photoshop ComfyUI Plugin", + "\ud83d\udd39SendTo Photoshop Plugin" + ], + { + "title_aux": "comfyui-photoshop" + } + ], + "https://github.com/NimaNzrii/comfyui-popup_preview": [ + [ + "PreviewPopup" + ], + { + "title_aux": "comfyui-popup_preview" + } + ], + "https://github.com/Niutonian/ComfyUi-NoodleWebcam": [ + [ + "WebcamNode" + ], + { + "title_aux": "ComfyUi-NoodleWebcam" + } + ], + "https://github.com/Nlar/ComfyUI_CartoonSegmentation": [ + [ + "AnimeSegmentation", + "KenBurnsConfigLoader", + "KenBurns_Processor", + "LoadImageFilename" + ], + { + "author": "Nels Larsen", + "description": "This extension offers a front end to the Cartoon Segmentation Project (https://github.com/CartoonSegmentation/CartoonSegmentation)", + "nickname": "CfyCS", + "title": "ComfyUI_CartoonSegmentation", + "title_aux": "ComfyUI_CartoonSegmentation" + } + ], + "https://github.com/NotHarroweD/Harronode": [ + [ + "Harronode" + ], + { + "author": "HarroweD and quadmoon (https://github.com/traugdor)", + "description": "This extension to ComfyUI will build a prompt for the Harrlogos LoRA for SDXL.", + "nickname": "Harronode", + "nodename_pattern": "Harronode", + "title": "Harrlogos Prompt Builder Node", + "title_aux": "Harrlogos Prompt Builder Node" + } + ], + "https://github.com/Nourepide/ComfyUI-Allor": [ + [ + "AlphaChanelAdd", + "AlphaChanelAddByMask", + "AlphaChanelAsMask", + "AlphaChanelRemove", + "AlphaChanelRestore", + "ClipClamp", + "ClipVisionClamp", + "ClipVisionOutputClamp", + "ConditioningClamp", + "ControlNetClamp", + "GligenClamp", + "ImageBatchCopy", + "ImageBatchFork", + "ImageBatchGet", + "ImageBatchJoin", + "ImageBatchPermute", + "ImageBatchRemove", + "ImageClamp", + "ImageCompositeAbsolute", + "ImageCompositeAbsoluteByContainer", + "ImageCompositeRelative", + "ImageCompositeRelativeByContainer", + "ImageContainer", + "ImageContainerInheritanceAdd", + "ImageContainerInheritanceMax", + "ImageContainerInheritanceScale", + "ImageContainerInheritanceSum", + "ImageDrawArc", + "ImageDrawArcByContainer", + "ImageDrawChord", + "ImageDrawChordByContainer", + "ImageDrawEllipse", + "ImageDrawEllipseByContainer", + "ImageDrawLine", + "ImageDrawLineByContainer", + "ImageDrawPieslice", + "ImageDrawPiesliceByContainer", + "ImageDrawPolygon", + "ImageDrawRectangle", + "ImageDrawRectangleByContainer", + "ImageDrawRectangleRounded", + "ImageDrawRectangleRoundedByContainer", + "ImageEffectsAdjustment", + "ImageEffectsGrayscale", + "ImageEffectsLensBokeh", + "ImageEffectsLensChromaticAberration", + "ImageEffectsLensOpticAxis", + "ImageEffectsLensVignette", + "ImageEffectsLensZoomBurst", + "ImageEffectsNegative", + "ImageEffectsSepia", + "ImageFilterBilateralBlur", + "ImageFilterBlur", + "ImageFilterBoxBlur", + "ImageFilterContour", + "ImageFilterDetail", + "ImageFilterEdgeEnhance", + "ImageFilterEdgeEnhanceMore", + "ImageFilterEmboss", + "ImageFilterFindEdges", + "ImageFilterGaussianBlur", + "ImageFilterGaussianBlurAdvanced", + "ImageFilterMax", + "ImageFilterMedianBlur", + "ImageFilterMin", + "ImageFilterMode", + "ImageFilterRank", + "ImageFilterSharpen", + "ImageFilterSmooth", + "ImageFilterSmoothMore", + "ImageFilterStackBlur", + "ImageNoiseBeta", + "ImageNoiseBinomial", + "ImageNoiseBytes", + "ImageNoiseGaussian", + "ImageSegmentation", + "ImageSegmentationCustom", + "ImageSegmentationCustomAdvanced", + "ImageText", + "ImageTextMultiline", + "ImageTextMultilineOutlined", + "ImageTextOutlined", + "ImageTransformCropAbsolute", + "ImageTransformCropCorners", + "ImageTransformCropRelative", + "ImageTransformPaddingAbsolute", + "ImageTransformPaddingRelative", + "ImageTransformResizeAbsolute", + "ImageTransformResizeClip", + "ImageTransformResizeRelative", + "ImageTransformRotate", + "ImageTransformTranspose", + "LatentClamp", + "MaskClamp", + "ModelClamp", + "StyleModelClamp", + "UpscaleModelClamp", + "VaeClamp" + ], + { + "title_aux": "Allor Plugin" + } + ], + "https://github.com/Nuked88/ComfyUI-N-Nodes": [ + [ + "CLIPTextEncodeAdvancedNSuite [n-suite]", + "DynamicPrompt [n-suite]", + "Float Variable [n-suite]", + "FrameInterpolator [n-suite]", + "GPT Loader Simple [n-suite]", + "GPT Sampler [n-suite]", + "ImagePadForOutpaintAdvanced [n-suite]", + "Integer Variable [n-suite]", + "Llava Clip Loader [n-suite]", + "LoadFramesFromFolder [n-suite]", + "LoadImageFromFolder [n-suite]", + "LoadVideo [n-suite]", + "SaveVideo [n-suite]", + "SetMetadataForSaveVideo [n-suite]", + "String Variable [n-suite]" + ], + { + "title_aux": "ComfyUI-N-Nodes" + } + ], + "https://github.com/Off-Live/ComfyUI-off-suite": [ + [ + "Apply CLAHE", + "Cached Image Load From URL", + "CalcMaskBound", + "Crop Center wigh SEGS", + "Crop Center with SEGS", + "Dilate Mask for Each Face", + "GW Number Formatting", + "Grid Image from batch (OFF)", + "Image Crop Fit", + "Image Resize Fit", + "OFF SEGS to Image", + "Paste Face Segment to Image", + "Query Gender and Age", + "RandomSeedfromList", + "SEGS to Face Crop Data", + "Safe Mask to Image", + "VAE Encode For Inpaint V2", + "Watermarking" + ], + { + "title_aux": "ComfyUI-off-suite" + } + ], + "https://github.com/Onierous/QRNG_Node_ComfyUI/raw/main/qrng_node.py": [ + [ + "QRNG_Node_CSV" + ], + { + "title_aux": "QRNG_Node_ComfyUI" + } + ], + "https://github.com/PCMonsterx/ComfyUI-CSV-Loader": [ + [ + "Load Artists CSV", + "Load Artmovements CSV", + "Load Characters CSV", + "Load Colors CSV", + "Load Composition CSV", + "Load Lighting CSV", + "Load Negative CSV", + "Load Positive CSV", + "Load Settings CSV", + "Load Styles CSV" + ], + { + "title_aux": "ComfyUI-CSV-Loader" + } + ], + "https://github.com/ParisNeo/lollms_nodes_suite": [ + [ + "Artbot", + "Lollms_Text_Gen", + "Lollms_Text_Saver", + "RandomizeVideo" + ], + { + "title_aux": "lollms_nodes_suite" + } + ], + "https://github.com/ParmanBabra/ComfyUI-Malefish-Custom-Scripts": [ + [ + "CSVPromptsLoader", + "CombinePrompt", + "MultiLoraLoader", + "RandomPrompt" + ], + { + "title_aux": "ComfyUI-Malefish-Custom-Scripts" + } + ], + "https://github.com/Pfaeff/pfaeff-comfyui": [ + [ + "AstropulsePixelDetector", + "BackgroundRemover", + "ImagePadForBetterOutpaint", + "Inpainting", + "InpaintingPipelineLoader" + ], + { + "title_aux": "pfaeff-comfyui" + } + ], + "https://github.com/PnthrLeo/comfyUI-image-search": [ + [ + "CloseImagesSearcher" + ], + { + "title_aux": "comfyUI-image-search" + } + ], + "https://github.com/Pos13/comfyui-cyclist": [ + [ + "CyclistCompare", + "CyclistMathFloat", + "CyclistMathInt", + "CyclistTimer", + "CyclistTimerStop", + "CyclistTypeCast", + "Interrupt", + "LoopManager", + "MemorizeConditioning", + "MemorizeFloat", + "MemorizeInt", + "MemorizeString", + "OverrideImage", + "OverrideLatent", + "OverrideModel", + "RecallConditioning", + "RecallFloat", + "RecallInt", + "RecallString", + "ReloadImage", + "ReloadLatent", + "ReloadModel" + ], + { + "author": "Pos13", + "description": "This extension provides tools to iterate generation results between runs. In general, it's for cycles.", + "nickname": "comfyui-cyclist", + "title": "Cyclist", + "title_aux": "Cyclist" + } + ], + "https://github.com/QaisMalkawi/ComfyUI-QaisHelper": [ + [ + "Bool Binary Operation", + "Bool Unary Operation", + "Item Debugger", + "Item Switch", + "Nearest SDXL Resolution", + "SDXL Resolution", + "Size Swapper" + ], + { + "title_aux": "ComfyUI-Qais-Helper" + } + ], + "https://github.com/RedRayz/ComfyUI-Danbooru-To-WD": [ + [ + "DanbooruToWD" + ], + { + "title_aux": "ComfyUI-Danbooru-To-WD" + } + ], + "https://github.com/RenderRift/ComfyUI-RenderRiftNodes": [ + [ + "AnalyseMetadata", + "DateIntegerNode", + "DisplayMetaOptions", + "LoadImageWithMeta", + "MetadataOverlayNode", + "VideoPathMetaExtraction" + ], + { + "title_aux": "ComfyUI-RenderRiftNodes" + } + ], + "https://github.com/RomanKuschanow/ComfyUI-Advanced-Latent-Control": [ + [ + "LatentAddTransform", + "LatentInterpolateTransform", + "LatentMirror", + "LatentNormalize", + "LatentShift", + "MirrorTransform", + "MultiplyTransform", + "OffsetCombine", + "OneTimeLatentAddTransform", + "OneTimeLatentInterpolateTransform", + "OneTimeMirrorTransform", + "OneTimeMultiplyTransform", + "OneTimeShiftTransform", + "ShiftTransform", + "TransformHijack", + "TransformOffset", + "TransformSampler", + "TransformSamplerAdvanced", + "TransformsCombine" + ], + { + "title_aux": "Advanced Latent Control" + } + ], + "https://github.com/Ron-Digital/ComfyUI-SceneGenerator": [ + [ + "Scene Generator" + ], + { + "title_aux": "ComfyUI-SceneGenerator" + } + ], + "https://github.com/Ryuukeisyou/comfyui_face_parsing": [ + [ + "BBoxListItemSelect(FaceParsing)", + "BBoxResize(FaceParsing)", + "ColorAdjust(FaceParsing)", + "FaceBBoxDetect(FaceParsing)", + "FaceBBoxDetectorLoader(FaceParsing)", + "FaceParse(FaceParsing)", + "FaceParsingModelLoader(FaceParsing)", + "FaceParsingProcessorLoader(FaceParsing)", + "FaceParsingResultsParser(FaceParsing)", + "GuidedFilter(FaceParsing)", + "ImageCropWithBBox(FaceParsing)", + "ImageInsertWithBBox(FaceParsing)", + "ImageListSelect(FaceParsing)", + "ImagePadWithBBox(FaceParsing)", + "ImageResizeCalculator(FaceParsing)", + "ImageResizeWithBBox(FaceParsing)", + "ImageSize(FaceParsing)", + "LatentCropWithBBox(FaceParsing)", + "LatentInsertWithBBox(FaceParsing)", + "LatentSize(FaceParsing)", + "MaskComposite(FaceParsing)", + "MaskInsertWithBBox(FaceParsing)", + "MaskListComposite(FaceParsing)", + "MaskListSelect(FaceParsing)", + "MaskToBBox(FaceParsing)", + "SkinDetectTraditional(FaceParsing)" + ], + { + "title_aux": "comfyui_face_parsing" + } + ], + "https://github.com/Ryuukeisyou/comfyui_io_helpers": [ + [ + "ImageLoadAsMaskByPath(IOHelpers)", + "ImageLoadByPath(IOHelpers)", + "ImageLoadFromBase64(IOHelpers)", + "ImageSaveAsBase64(IOHelpers)", + "ImageSaveToPath(IOHelpers)", + "TypeConversion(IOHelpers)" + ], + { + "title_aux": "comfyui_io_helpers" + } + ], + "https://github.com/SEkINVR/ComfyUI-SaveAs": [ + [ + "ComfyUISaveAs" + ], + { + "title_aux": "ComfyUI SaveAS" + } + ], + "https://github.com/SLAPaper/ComfyUI-Image-Selector": [ + [ + "ImageDuplicator", + "ImageSelector", + "LatentDuplicator", + "LatentSelector" + ], + { + "title_aux": "ComfyUI-Image-Selector" + } + ], + "https://github.com/SOELexicon/ComfyUI-LexMSDBNodes": [ + [ + "MSSqlSelectNode", + "MSSqlTableNode" + ], + { + "title_aux": "LexMSDBNodes" + } + ], + "https://github.com/SOELexicon/ComfyUI-LexTools": [ + [ + "AesthetlcScoreSorter", + "AgeClassifierNode", + "ArtOrHumanClassifierNode", + "CalculateAestheticScore", + "DocumentClassificationNode", + "FoodCategoryClassifierNode", + "ImageAspectPadNode", + "ImageCaptioning", + "ImageFilterByFloatScoreNode", + "ImageFilterByIntScoreNode", + "ImageQualityScoreNode", + "ImageRankingNode", + "ImageScaleToMin", + "LoadAesteticModel", + "MD5ImageHashNode", + "SamplerPropertiesNode", + "ScoreConverterNode", + "SeedIncrementerNode", + "SegformerNode", + "SegformerNodeMasks", + "SegformerNodeMergeSegments", + "StepCfgIncrementNode" + ], + { + "title_aux": "ComfyUI-LexTools" + } + ], + "https://github.com/SadaleNet/CLIPTextEncodeA1111-ComfyUI/raw/master/custom_nodes/clip_text_encoder_a1111.py": [ + [ + "CLIPTextEncodeA1111", + "RerouteTextForCLIPTextEncodeA1111" + ], + { + "preemptions": [ + "SAMLoader" + ], + "title_aux": "ComfyUI A1111-like Prompt Custom Node Solution" + } + ], + "https://github.com/SamKhoze/ComfyUI-DeepFuze": [ + [ + "DeepFuze Save", + "DeepFuzeAdavance", + "DeepFuzeFaceSwap", + "DeepfuzePreview", + "LLM_node", + "PlayBackAudio", + "TTS_generation" + ], + { + "title_aux": "DeepFuze" + } + ], + "https://github.com/SayanoAI/Comfy-RVC": [ + [ + "AudioBatchValueNode", + "AudioTranscriptionNode", + "DownloadAudio", + "ImageRepeatInterleavedNode", + "LatentRepeatInterleavedNode", + "LoadAudio", + "LoadHubertModel", + "LoadPitchExtractionParams", + "LoadRVCModelNode", + "LoadWhisperModelNode", + "MergeAudioNode", + "MergeImageBatches", + "MergeLatentBatches", + "PreviewAudio", + "RVCNode", + "UVR5Node" + ], + { + "title_aux": "Comfy-RVC" + } + ], + "https://github.com/Scholar01/ComfyUI-Keyframe": [ + [ + "KeyframeApply", + "KeyframeInterpolationPart", + "KeyframePart" + ], + { + "title_aux": "SComfyUI-Keyframe" + } + ], + "https://github.com/Scorpinaus/ComfyUI-DiffusersLoader": [ + [ + "CombinedDiffusersLoader", + "DiffusersClipLoader", + "DiffusersUNETLoader", + "DiffusersVAELoader" + ], + { + "title_aux": "Loaders for Diffusers-format checkpoints" + } + ], + "https://github.com/ScreamingHawk/comfyui-ollama-prompt-encode": [ + [ + "OllamaCLIPTextEncode", + "OllamaPromptGenerator" + ], + { + "author": "Michael Standen", + "description": "Use AI to generate prompts and perform CLIP text encoding", + "nickname": "Ollama Prompt Encode", + "title": "Ollama Prompt Encode", + "title_aux": "Ollama Prompt Encode" + } + ], + "https://github.com/SeaArtLab/ComfyUI-Long-CLIP": [ + [ + "SeaArtLongClip", + "SeaArtLongXLClipMerge" + ], + { + "title_aux": "ComfyUI-Long-CLIP" + } + ], + "https://github.com/SeargeDP/SeargeSDXL": [ + [ + "SeargeAdvancedParameters", + "SeargeCheckpointLoader", + "SeargeConditionMixing", + "SeargeConditioningMuxer2", + "SeargeConditioningMuxer5", + "SeargeConditioningParameters", + "SeargeControlnetAdapterV2", + "SeargeControlnetModels", + "SeargeCustomAfterUpscaling", + "SeargeCustomAfterVaeDecode", + "SeargeCustomPromptMode", + "SeargeDebugPrinter", + "SeargeEnablerInputs", + "SeargeFloatConstant", + "SeargeFloatMath", + "SeargeFloatPair", + "SeargeFreeU", + "SeargeGenerated1", + "SeargeGenerationParameters", + "SeargeHighResolution", + "SeargeImage2ImageAndInpainting", + "SeargeImageAdapterV2", + "SeargeImageSave", + "SeargeImageSaving", + "SeargeInput1", + "SeargeInput2", + "SeargeInput3", + "SeargeInput4", + "SeargeInput5", + "SeargeInput6", + "SeargeInput7", + "SeargeIntegerConstant", + "SeargeIntegerMath", + "SeargeIntegerPair", + "SeargeIntegerScaler", + "SeargeLatentMuxer3", + "SeargeLoraLoader", + "SeargeLoras", + "SeargeMagicBox", + "SeargeModelSelector", + "SeargeOperatingMode", + "SeargeOutput1", + "SeargeOutput2", + "SeargeOutput3", + "SeargeOutput4", + "SeargeOutput5", + "SeargeOutput6", + "SeargeOutput7", + "SeargeParameterProcessor", + "SeargePipelineStart", + "SeargePipelineTerminator", + "SeargePreviewImage", + "SeargePromptAdapterV2", + "SeargePromptCombiner", + "SeargePromptStyles", + "SeargePromptText", + "SeargeSDXLBasePromptEncoder", + "SeargeSDXLImage2ImageSampler", + "SeargeSDXLImage2ImageSampler2", + "SeargeSDXLPromptEncoder", + "SeargeSDXLRefinerPromptEncoder", + "SeargeSDXLSampler", + "SeargeSDXLSampler2", + "SeargeSDXLSamplerV3", + "SeargeSamplerAdvanced", + "SeargeSamplerInputs", + "SeargeSaveFolderInputs", + "SeargeSeparator", + "SeargeStylePreprocessor", + "SeargeTextInputV2", + "SeargeUpscaleModelLoader", + "SeargeUpscaleModels", + "SeargeVAELoader" + ], + { + "title_aux": "SeargeSDXL" + } + ], + "https://github.com/Seedsa/Fooocus_Nodes": [ + [ + "BasicScheduler", + "CLIPLoader", + "CLIPMergeSimple", + "CLIPSave", + "CLIPSetLastLayer", + "CLIPTextEncode", + "CLIPTextEncodeSDXL", + "CLIPTextEncodeSDXLRefiner", + "CLIPVisionEncode", + "CLIPVisionLoader", + "Canny", + "CheckpointLoader", + "CheckpointLoaderSimple", + "CheckpointSave", + "ConditioningAverage", + "ConditioningCombine", + "ConditioningConcat", + "ConditioningSetArea", + "ConditioningSetAreaPercentage", + "ConditioningSetMask", + "ConditioningSetTimestepRange", + "ConditioningZeroOut", + "ControlNetApply", + "ControlNetApplyAdvanced", + "ControlNetLoader", + "CropMask", + "DiffControlNetLoader", + "DiffusersLoader", + "DualCLIPLoader", + "EmptyImage", + "EmptyLatentImage", + "ExponentialScheduler", + "FeatherMask", + "FlipSigmas", + "Fooocus ApplyImagePrompt", + "Fooocus Controlnet", + "Fooocus ImagePrompt", + "Fooocus Inpaint", + "Fooocus KSampler", + "Fooocus Loader", + "Fooocus LoraStack", + "Fooocus PipeOut", + "Fooocus PreKSampler", + "Fooocus Styles", + "Fooocus Upscale", + "Fooocus detailerFix", + "Fooocus negative", + "Fooocus positive", + "Fooocus preDetailerFix", + "Fooocus samLoaderPipe", + "Fooocus ultralyticsDetectorPipe", + "FreeU", + "FreeU_V2", + "GLIGENLoader", + "GLIGENTextBoxApply", + "GrowMask", + "HyperTile", + "HypernetworkLoader", + "ImageBatch", + "ImageBlend", + "ImageBlur", + "ImageColorToMask", + "ImageCompositeMasked", + "ImageCrop", + "ImageInvert", + "ImageOnlyCheckpointLoader", + "ImageOnlyCheckpointSave", + "ImagePadForOutpaint", + "ImageQuantize", + "ImageScale", + "ImageScaleBy", + "ImageScaleToTotalPixels", + "ImageSharpen", + "ImageToMask", + "ImageUpscaleWithModel", + "InpaintModelConditioning", + "InvertMask", + "JoinImageWithAlpha", + "KSampler", + "KSamplerAdvanced", + "KSamplerSelect", + "KarrasScheduler", + "LatentAdd", + "LatentBatch", + "LatentBatchSeedBehavior", + "LatentBlend", + "LatentComposite", + "LatentCompositeMasked", + "LatentCrop", + "LatentFlip", + "LatentFromBatch", + "LatentInterpolate", + "LatentMultiply", + "LatentRotate", + "LatentSubtract", + "LatentUpscale", + "LatentUpscaleBy", + "LoadImage", + "LoadImageMask", + "LoadLatent", + "LoraLoader", + "LoraLoaderModelOnly", + "MaskComposite", + "MaskToImage", + "ModelMergeAdd", + "ModelMergeBlocks", + "ModelMergeSimple", + "ModelMergeSubtract", + "ModelSamplingContinuousEDM", + "ModelSamplingDiscrete", + "PatchModelAddDownscale", + "PerpNeg", + "PhotoMakerEncode", + "PhotoMakerLoader", + "PolyexponentialScheduler", + "PorterDuffImageComposite", + "PreviewImage", + "RebatchImages", + "RebatchLatents", + "RepeatImageBatch", + "RepeatLatentBatch", + "RescaleCFG", + "SDTurboScheduler", + "SD_4XUpscale_Conditioning", + "SVD_img2vid_Conditioning", + "SamplerCustom", + "SamplerDPMPP_2M_SDE", + "SamplerDPMPP_SDE", + "SaveAnimatedPNG", + "SaveAnimatedWEBP", + "SaveImage", + "SaveLatent", + "SelfAttentionGuidance", + "SetLatentNoiseMask", + "SolidMask", + "SplitImageWithAlpha", + "SplitSigmas", + "StableZero123_Conditioning", + "StableZero123_Conditioning_Batched", + "StyleModelApply", + "StyleModelLoader", + "TomePatchModel", + "UNETLoader", + "UpscaleModelLoader", + "VAEDecode", + "VAEDecodeTiled", + "VAEEncode", + "VAEEncodeForInpaint", + "VAEEncodeTiled", + "VAELoader", + "VAESave", + "VPScheduler", + "VideoLinearCFGGuidance", + "unCLIPCheckpointLoader", + "unCLIPConditioning" + ], + { + "title_aux": "ComfyUI Fooocus Nodes" + } + ], + "https://github.com/Ser-Hilary/SDXL_sizing/raw/main/conditioning_sizing_for_SDXL.py": [ + [ + "get_aspect_from_image", + "get_aspect_from_ints", + "sizing_node", + "sizing_node_basic", + "sizing_node_unparsed" + ], + { + "title_aux": "SDXL_sizing" + } + ], + "https://github.com/Shadetail/ComfyUI_Eagleshadow": [ + [ + "Batch 12 Images", + "Detect Transparency", + "Fix Checkpoint Name", + "ImageLinearGammaCompositeMasked", + "KSampler Same Noise", + "MaskGlow", + "OffsetImage", + "Round Float to String", + "SaveImageToFolder", + "Select ControlNet", + "Select Model 20", + "Simple Load Image Batch" + ], + { + "title_aux": "Eagleshadow Custom Nodes" + } + ], + "https://github.com/SherryXieYuchen/ComfyUI-Image-Inpainting": [ + [ + "CropImageByRect", + "INPAINT_ColorCorrection", + "INPAINT_CropImage", + "INPAINT_InpaintingWithModel", + "INPAINT_LoadModel", + "INPAINT_PasteBackCropImage", + "INPAINT_VAEDecode", + "INPAINT_VAEEncode", + "ImagePostprocess", + "ImagePreprocess" + ], + { + "title_aux": "ComfyUI-Image-Inpainting" + } + ], + "https://github.com/Shibiko-AI/ShibikoAI-ComfyUI-Tools": [ + [ + "Cascade", + "Luts", + "Waifu2x" + ], + { + "title_aux": "Shibiko AI ComfyUI Tools" + } + ], + "https://github.com/ShmuelRonen/ComfyUI-SVDResizer": [ + [ + "SVDRsizer" + ], + { + "title_aux": "ComfyUI-SVDResizer" + } + ], + "https://github.com/ShmuelRonen/ComfyUI_Gemini_Flash": [ + [ + "Gemini_Flash" + ], + { + "title_aux": "ComfyUI_Gemini_Flash" + } + ], + "https://github.com/ShmuelRonen/ComfyUI_wav2lip": [ + [ + "Wav2Lip" + ], + { + "title_aux": "Wav2Lip Node for ComfyUI" + } + ], + "https://github.com/Shraknard/ComfyUI-Remover": [ + [ + "Remover" + ], + { + "title_aux": "ComfyUI-Remover" + } + ], + "https://github.com/Siberpone/lazy-pony-prompter": [ + [ + "LPP_Deleter", + "LPP_Derpibooru", + "LPP_E621", + "LPP_Loader_Derpibooru", + "LPP_Loader_E621", + "LPP_Saver" + ], + { + "title_aux": "Lazy Pony Prompter" + } + ], + "https://github.com/Smirnov75/ComfyUI-mxToolkit": [ + [ + "mxSeed", + "mxSlider", + "mxSlider2D", + "mxStop" + ], + { + "title_aux": "ComfyUI-mxToolkit" + } + ], + "https://github.com/Smuzzies/comfyui_chatbox_overlay/raw/main/chatbox_overlay.py": [ + [ + "Chatbox Overlay" + ], + { + "title_aux": "Chatbox Overlay node for ComfyUI" + } + ], + "https://github.com/Smuzzies/comfyui_meme_maker": [ + [ + "MemeMaker" + ], + { + "title_aux": "comfyui_meme_maker" + } + ], + "https://github.com/SoftMeng/ComfyUI_ImageToText": [ + [ + "ComfyUI_ImageToText" + ], + { + "title_aux": "ComfyUI_ImageToText" + } + ], + "https://github.com/SoftMeng/ComfyUI_Mexx_Poster": [ + [ + "ComfyUI_Mexx_Poster" + ], + { + "title_aux": "ComfyUI_Mexx_Poster" + } + ], + "https://github.com/SoftMeng/ComfyUI_Mexx_Styler": [ + [ + "MexxSDXLPromptStyler", + "MexxSDXLPromptStylerAdvanced" + ], + { + "title_aux": "ComfyUI_Mexx_Styler" + } + ], + "https://github.com/Sorcerio/MBM-Music-Visualizer": [ + [ + "id", + "mbmAudioFeatureCalculator", + "mbmAudioLoader", + "mbmImageConcat", + "mbmPromptSequenceBuilder", + "mbmPromptSequenceBuilderAdv", + "mbmPromptSequenceInterpolator", + "mbmPromptSequenceLoader", + "mbmPromptSequenceRenderer" + ], + { + "title_aux": "MBM's Music Visualizer" + } + ], + "https://github.com/SozeInc/ComfyUI-Mobile": [ + [ + "Mobile_Settings_Launcher_Data", + "Send Notification (Mobile)", + "Settings Launcher (Mobile)", + "Ultimate Concat (Mobile)" + ], + { + "title_aux": "ComfyUI-Mobile" + } + ], + "https://github.com/SpaceKendo/ComfyUI-svd_txt2vid": [ + [ + "SVD_txt2vid_ConditioningwithLatent" + ], + { + "title_aux": "Text to video for Stable Video Diffusion in ComfyUI" + } + ], + "https://github.com/Stability-AI/ComfyUI-SAI_API": [ + [ + "Stability Conservative Upscale", + "Stability Control Skech", + "Stability Control Structure", + "Stability Creative Upscale", + "Stability Erase", + "Stability Image Core", + "Stability Image Ultra", + "Stability Inpainting", + "Stability Outpainting", + "Stability Remove Background", + "Stability SD3", + "Stability Search and Replace" + ], + { + "title_aux": "Stability API nodes for ComfyUI" + } + ], + "https://github.com/Stability-AI/stability-ComfyUI-nodes": [ + [ + "ColorBlend", + "ControlLoraSave", + "GetImageSize" + ], + { + "title_aux": "stability-ComfyUI-nodes" + } + ], + "https://github.com/StartHua/ComfyUI_OOTDiffusion_CXH": [ + [ + "Ood_CXH" + ], + { + "title_aux": "ComfyUI_OOTDiffusion_CXH" + } + ], + "https://github.com/StartHua/ComfyUI_PCDMs": [ + [ + "PCDMS_CXH" + ], + { + "title_aux": "ComfyUI_PCDMs" + } + ], + "https://github.com/StartHua/ComfyUI_Seg_VITON": [ + [ + "segformer_agnostic", + "segformer_clothes", + "segformer_remove_bg", + "stabel_vition" + ], + { + "title_aux": "ComfyUI_Seg_VITON" + } + ], + "https://github.com/StartHua/Comfyui_joytag": [ + [ + "CXH_JoyTag" + ], + { + "title_aux": "Comfyui_joytag" + } + ], + "https://github.com/StartHua/Comfyui_segformer_b2_clothes": [ + [ + "segformer_b2_clothes" + ], + { + "title_aux": "comfyui_segformer_b2_clothes" + } + ], + "https://github.com/SuperBeastsAI/ComfyUI-SuperBeasts": [ + [ + "Deflicker (SuperBeasts.AI)", + "HDR Effects (SuperBeasts.AI)", + "Image Batch Manager (SuperBeasts.AI)", + "Make Resized Mask Batch (SuperBeasts.AI)", + "Mask Batch Manager (SuperBeasts.AI)", + "Pixel Deflicker (SuperBeasts.AI)", + "String List Manager (SuperBeasts.AI)" + ], + { + "title_aux": "ComfyUI-SuperBeasts" + } + ], + "https://github.com/SuperMasterBlasterLaser/ComfyUI_YOLO_Classifiers": [ + [ + "YOLO Classifier Model Loader", + "YOLO Classify" + ], + { + "title_aux": "ComfyUI_YOLO_Classifiers" + } + ], + "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes": [ + [ + "CR 8 Channel In", + "CR 8 Channel Out", + "CR Apply ControlNet", + "CR Apply LoRA Stack", + "CR Apply Model Merge", + "CR Apply Multi Upscale", + "CR Apply Multi-ControlNet", + "CR Arabic Text RTL", + "CR Aspect Ratio", + "CR Aspect Ratio Banners", + "CR Aspect Ratio SDXL", + "CR Aspect Ratio Social Media", + "CR Batch Images From List", + "CR Batch Process Switch", + "CR Binary Pattern", + "CR Binary To Bit List", + "CR Bit Schedule", + "CR Central Schedule", + "CR Checker Pattern", + "CR Clamp Value", + "CR Clip Input Switch", + "CR Color Bars", + "CR Color Gradient", + "CR Color Panel", + "CR Color Tint", + "CR Combine Prompt", + "CR Combine Schedules", + "CR Comic Panel Templates", + "CR Composite Text", + "CR Conditioning Input Switch", + "CR Conditioning Mixer", + "CR ControlNet Input Switch", + "CR Current Frame", + "CR Cycle Images", + "CR Cycle Images Simple", + "CR Cycle LoRAs", + "CR Cycle Models", + "CR Cycle Text", + "CR Cycle Text Simple", + "CR Data Bus In", + "CR Data Bus Out", + "CR Debatch Frames", + "CR Diamond Panel", + "CR Draw Perspective Text", + "CR Draw Pie", + "CR Draw Shape", + "CR Draw Text", + "CR Encode Scheduled Prompts", + "CR Feathered Border", + "CR Float Range List", + "CR Float To Integer", + "CR Float To String", + "CR Font File List", + "CR Get Parameter From Prompt", + "CR Gradient Float", + "CR Gradient Integer", + "CR Half Drop Panel", + "CR Halftone Filter", + "CR Halftone Grid", + "CR Hires Fix Process Switch", + "CR Image Border", + "CR Image Grid Panel", + "CR Image Input Switch", + "CR Image Input Switch (4 way)", + "CR Image List", + "CR Image List Simple", + "CR Image Output", + "CR Image Panel", + "CR Image Pipe Edit", + "CR Image Pipe In", + "CR Image Pipe Out", + "CR Image Size", + "CR Img2Img Process Switch", + "CR Increment Float", + "CR Increment Integer", + "CR Index", + "CR Index Increment", + "CR Index Multiply", + "CR Index Reset", + "CR Input Text List", + "CR Integer Multiple", + "CR Integer Range List", + "CR Integer To String", + "CR Interpolate Latents", + "CR Intertwine Lists", + "CR Keyframe List", + "CR Latent Batch Size", + "CR Latent Input Switch", + "CR LoRA List", + "CR LoRA Stack", + "CR Load Animation Frames", + "CR Load Flow Frames", + "CR Load GIF As List", + "CR Load Image List", + "CR Load Image List Plus", + "CR Load LoRA", + "CR Load Prompt Style", + "CR Load Schedule From File", + "CR Load Scheduled ControlNets", + "CR Load Scheduled LoRAs", + "CR Load Scheduled Models", + "CR Load Text List", + "CR Mask Text", + "CR Math Operation", + "CR Model Input Switch", + "CR Model List", + "CR Model Merge Stack", + "CR Module Input", + "CR Module Output", + "CR Module Pipe Loader", + "CR Multi Upscale Stack", + "CR Multi-ControlNet Stack", + "CR Multiline Text", + "CR Output Flow Frames", + "CR Output Schedule To File", + "CR Overlay Text", + "CR Overlay Transparent Image", + "CR Page Layout", + "CR Pipe Switch", + "CR Polygons", + "CR Prompt List", + "CR Prompt List Keyframes", + "CR Prompt Scheduler", + "CR Prompt Text", + "CR Radial Gradient", + "CR Random Hex Color", + "CR Random LoRA Stack", + "CR Random Multiline Colors", + "CR Random Multiline Values", + "CR Random Panel Codes", + "CR Random RGB", + "CR Random RGB Gradient", + "CR Random Shape Pattern", + "CR Random Weight LoRA", + "CR Repeater", + "CR SD1.5 Aspect Ratio", + "CR SDXL Aspect Ratio", + "CR SDXL Base Prompt Encoder", + "CR SDXL Prompt Mix Presets", + "CR SDXL Prompt Mixer", + "CR SDXL Style Text", + "CR Save Text To File", + "CR Schedule Input Switch", + "CR Schedule To ScheduleList", + "CR Seamless Checker", + "CR Seed", + "CR Seed to Int", + "CR Select Font", + "CR Select ISO Size", + "CR Select Model", + "CR Select Resize Method", + "CR Set Switch From String", + "CR Set Value On Binary", + "CR Set Value On Boolean", + "CR Set Value on String", + "CR Simple Banner", + "CR Simple Binary Pattern", + "CR Simple Binary Pattern Simple", + "CR Simple Image Compare", + "CR Simple List", + "CR Simple Meme Template", + "CR Simple Prompt List", + "CR Simple Prompt List Keyframes", + "CR Simple Prompt Scheduler", + "CR Simple Schedule", + "CR Simple Text Panel", + "CR Simple Text Scheduler", + "CR Simple Text Watermark", + "CR Simple Titles", + "CR Simple Value Scheduler", + "CR Split String", + "CR Starburst Colors", + "CR Starburst Lines", + "CR String To Boolean", + "CR String To Combo", + "CR String To Number", + "CR Style Bars", + "CR Switch Model and CLIP", + "CR Text", + "CR Text Blacklist", + "CR Text Concatenate", + "CR Text Cycler", + "CR Text Input Switch", + "CR Text Input Switch (4 way)", + "CR Text Length", + "CR Text List", + "CR Text List Simple", + "CR Text List To String", + "CR Text Operation", + "CR Text Replace", + "CR Text Scheduler", + "CR Thumbnail Preview", + "CR Trigger", + "CR Upscale Image", + "CR VAE Decode", + "CR VAE Input Switch", + "CR Value", + "CR Value Cycler", + "CR Value Scheduler", + "CR Vignette Filter", + "CR XY From Folder", + "CR XY Index", + "CR XY Interpolate", + "CR XY List", + "CR XY Product", + "CR XY Save Grid Image", + "CR XYZ Index", + "CR_Aspect Ratio For Print" + ], + { + "author": "Suzie1", + "description": "175 custom nodes for artists, designers and animators.", + "nickname": "Comfyroll Studio", + "title": "Comfyroll Studio", + "title_aux": "Comfyroll Studio" + } + ], + "https://github.com/Sxela/ComfyWarp": [ + [ + "ExtractOpticalFlow", + "LoadFrame", + "LoadFrameFromDataset", + "LoadFrameFromFolder", + "LoadFramePairFromDataset", + "LoadFrameSequence", + "MakeFrameDataset", + "MixConsistencyMaps", + "OffsetNumber", + "ResizeToFit", + "SaveFrame", + "WarpFrame" + ], + { + "title_aux": "ComfyWarp" + } + ], + "https://github.com/TGu-97/ComfyUI-TGu-utils": [ + [ + "MPNReroute", + "MPNSwitch", + "PNSwitch" + ], + { + "title_aux": "TGu Utilities" + } + ], + "https://github.com/THtianhao/ComfyUI-FaceChain": [ + [ + "FC CropAndPaste", + "FC CropBottom", + "FC CropToOrigin", + "FC FaceDetectCrop", + "FC FaceFusion", + "FC FaceSegAndReplace", + "FC FaceSegment", + "FC MaskOP", + "FC RemoveCannyFace", + "FC ReplaceByMask", + "FC StyleLoraLoad" + ], + { + "title_aux": "ComfyUI-FaceChain" + } + ], + "https://github.com/THtianhao/ComfyUI-Portrait-Maker": [ + [ + "PM_BoxCropImage", + "PM_ColorTransfer", + "PM_ExpandMaskBox", + "PM_FaceFusion", + "PM_FaceShapMatch", + "PM_FaceSkin", + "PM_GetImageInfo", + "PM_ImageResizeTarget", + "PM_ImageScaleShort", + "PM_MakeUpTransfer", + "PM_MaskDilateErode", + "PM_MaskMerge2Image", + "PM_PortraitEnhancement", + "PM_RatioMerge2Image", + "PM_ReplaceBoxImg", + "PM_RetinaFace", + "PM_Similarity", + "PM_SkinRetouching", + "PM_SuperColorTransfer", + "PM_SuperMakeUpTransfer" + ], + { + "title_aux": "ComfyUI-Portrait-Maker" + } + ], + "https://github.com/TJ16th/comfyUI_TJ_NormalLighting": [ + [ + "EulerLightingNode" + ], + { + "title_aux": "comfyUI_TJ_NormalLighting" + } + ], + "https://github.com/TMElyralab/Comfyui-MusePose": [ + [ + "filenamestring", + "musepose", + "museposealign" + ], + { + "title_aux": "Comfyui-MusePose" + } + ], + "https://github.com/TRI3D-LC/ComfyUI-MiroBoard": [ + [ + "add-image-miro-board" + ], + { + "title_aux": "ComfyUI-MiroBoard" + } + ], + "https://github.com/TRI3D-LC/tri3d-comfyui-nodes": [ + [ + "get_histogram_limits", + "main_light_layer", + "main_scaled_paste", + "simple_rescale_histogram", + "tri3d-HistogramEqualization", + "tri3d-LAB_2_RGB", + "tri3d-RGB_2_LAB", + "tri3d-adjust-neck", + "tri3d-atr-parse", + "tri3d-atr-parse-batch", + "tri3d-bgremove-mega", + "tri3d-clear-memory", + "tri3d-clipdrop-bgremove-api", + "tri3d-clipdrop-bgreplace-api", + "tri3d-composite-image-splitter", + "tri3d-dwpose", + "tri3d-extract-hand", + "tri3d-extract-masks-batch", + "tri3d-extract-parts-batch", + "tri3d-extract-parts-batch2", + "tri3d-extract-parts-mask-batch", + "tri3d-extract-pascal-parts-batch", + "tri3d-face-recognise", + "tri3d-facer_face_segment", + "tri3d-flexible_color_extract", + "tri3d-float-to-image", + "tri3d-fuzzification", + "tri3d-get_histogram_limits", + "tri3d-get_mean_and_standard_deviation", + "tri3d-get_threshold_for_bg_swap", + "tri3d-image-mask-2-box", + "tri3d-image-mask-box-2-image", + "tri3d-interaction-canny", + "tri3d-levindabhi-cloth-seg", + "tri3d-load-pose-json", + "tri3d-load_AEMatter_Model", + "tri3d-load_MVANet_Model", + "tri3d-luminosity-match", + "tri3d-main_transparent_background", + "tri3d-photoroom-bgremove-api", + "tri3d-pose-adaption", + "tri3d-pose-to-image", + "tri3d-position-hands", + "tri3d-position-parts-batch", + "tri3d-position-pascal-parts-batch", + "tri3d-recolor-mask", + "tri3d-recolor-mask-LAB_space", + "tri3d-recolor-mask-LAB_space_manual", + "tri3d-recolor-mask-RGB_space", + "tri3d-renormalize_array", + "tri3d-run_AEMatter_inference", + "tri3d-run_MVANet_inference", + "tri3d-scaled-paste", + "tri3d-simple_bg_swap", + "tri3d-simple_rescale_histogram", + "tri3d-skin-feathered-padded-mask", + "tri3d-swap-pixels" + ], + { + "title_aux": "tri3d-comfyui-nodes" + } + ], + "https://github.com/TW-CUI/TW-CUI-Util": [ + [ + "TWCUI_Util_CommonSDXLResolutions", + "TWCUI_Util_FloatLiteral", + "TWCUI_Util_GenerationParameters", + "TWCUI_Util_GenerationPrompts", + "TWCUI_Util_IntLiteral", + "TWCUI_Util_ModelVAELORALoader", + "TWCUI_Util_ModelVAELoader", + "TWCUI_Util_MultilineStringLiteral", + "TWCUI_Util_SaveImage", + "TWCUI_Util_SaveImageAdvanced", + "TWCUI_Util_StringLiteral" + ], + { + "title_aux": "TW-CUI-Util" + } + ], + "https://github.com/TaiTair/comfyui-simswap": [ + [ + "Simswap", + "SimswapBuildFaceModel", + "SimswapFaceSwapOpt", + "SimswapImageDublicator", + "SimswapLoadFaceModel", + "SimswapMaskHelper", + "SimswapOptions", + "SimswapRestoreFace", + "SimswapSaveFaceModel" + ], + { + "title_aux": "Simswap Node for ComfyUI" + } + ], + "https://github.com/Taremin/comfyui-prompt-extranetworks": [ + [ + "PromptExtraNetworks" + ], + { + "title_aux": "ComfyUI Prompt ExtraNetworks" + } + ], + "https://github.com/Taremin/comfyui-string-tools": [ + [ + "StringToolsBalancedChoice", + "StringToolsConcat", + "StringToolsRandomChoice", + "StringToolsString", + "StringToolsText" + ], + { + "title_aux": "ComfyUI String Tools" + } + ], + "https://github.com/Taremin/webui-monaco-prompt": [ + [ + "WebuiMonacoPromptFind", + "WebuiMonacoPromptReplace" + ], + { + "title_aux": "WebUI Monaco Prompt" + } + ], + "https://github.com/TeaCrab/ComfyUI-TeaNodes": [ + [ + "TC_ColorFill", + "TC_CropTo", + "TC_EqualizeCLAHE", + "TC_ImageResize", + "TC_ImageScale", + "TC_KorniaGamma", + "TC_RandomColorFill", + "TC_SizeApproximation" + ], + { + "title_aux": "ComfyUI-TeaNodes" + } + ], + "https://github.com/TemryL/ComfyS3": [ + [ + "DownloadFileS3", + "LoadImageS3", + "SaveImageS3", + "SaveVideoFilesS3", + "UploadFileS3" + ], + { + "title_aux": "ComfyS3" + } + ], + "https://github.com/TemryL/ComfyUI-IDM-VTON": [ + [ + "IDM-VTON", + "PipelineLoader" + ], + { + "title_aux": "ComfyUI-IDM-VTON [WIP]" + } + ], + "https://github.com/TencentQQGYLab/ComfyUI-ELLA": [ + [ + "CombineClipEllaEmbeds", + "ConcatConditionEllaEmbeds", + "ConditionToEllaEmbeds", + "ELLALoader", + "EllaApply", + "EllaCombineEmbeds", + "EllaEncode", + "EllaTextEncode", + "SetEllaTimesteps", + "T5TextEncode #ELLA", + "T5TextEncoderLoader #ELLA" + ], + { + "title_aux": "ComfyUI-ELLA" + } + ], + "https://github.com/TheBarret/ZSuite": [ + [ + "ZSuite: Prompter", + "ZSuite: RF Noise", + "ZSuite: SeedMod" + ], + { + "title_aux": "ZSuite" + } + ], + "https://github.com/TheBill2001/comfyui-upscale-by-model": [ + [ + "UpscaleImageByUsingModel" + ], + { + "author": "Tr\u1ea7n Nam Tu\u1ea5n", + "description": "This custom node allow upscaling an image by a factor using a model.", + "nickname": "Upscale Image By (Using Model)", + "title": "Upscale Image By (Using Model)", + "title_aux": "comfyui-upscale-by-model" + } + ], + "https://github.com/TheMistoAI/ComfyUI-Anyline": [ + [ + "AnyLinePreprocessor" + ], + { + "title_aux": "Anyline" + } + ], + "https://github.com/ThereforeGames/ComfyUI-Unprompted": [ + [ + "Unprompted" + ], + { + "title_aux": "ComfyUI-Unprompted" + } + ], + "https://github.com/TinyTerra/ComfyUI_tinyterraNodes": [ + [ + "ttN KSampler_v2", + "ttN advPlot combo", + "ttN advPlot range", + "ttN advPlot string", + "ttN advanced xyPlot", + "ttN compareInput", + "ttN concat", + "ttN conditioning", + "ttN debugInput", + "ttN float", + "ttN hiresfixScale", + "ttN imageOutput", + "ttN imageREMBG", + "ttN int", + "ttN multiModelMerge", + "ttN pipe2BASIC", + "ttN pipe2DETAILER", + "ttN pipeEDIT", + "ttN pipeEncodeConcat", + "ttN pipeIN", + "ttN pipeKSampler", + "ttN pipeKSamplerAdvanced", + "ttN pipeKSamplerAdvanced_v2", + "ttN pipeKSamplerSDXL", + "ttN pipeKSamplerSDXL_v2", + "ttN pipeKSampler_v2", + "ttN pipeLoader", + "ttN pipeLoaderSDXL", + "ttN pipeLoaderSDXL_v2", + "ttN pipeLoader_v2", + "ttN pipeLoraStack", + "ttN pipeOUT", + "ttN seed", + "ttN text", + "ttN text3BOX_3WAYconcat", + "ttN text7BOX_concat", + "ttN textCycleLine", + "ttN textDebug", + "ttN tinyLoader", + "ttN xyPlot" + ], + { + "author": "tinyterra", + "description": "This extension offers extensive xyPlot, various pipe nodes, fullscreen image viewer based on node history, dynamic widgets, interface customization, and more.", + "nickname": "\ud83c\udf0f", + "nodename_pattern": "^ttN ", + "title": "tinyterraNodes", + "title_aux": "ComfyUI_tinyterraNodes" + } + ], + "https://github.com/TripleHeadedMonkey/ComfyUI_MileHighStyler": [ + [ + "menus" + ], + { + "title_aux": "ComfyUI_MileHighStyler" + } + ], + "https://github.com/Tropfchen/ComfyUI-Embedding_Picker": [ + [ + "EmbeddingPicker" + ], + { + "title_aux": "Embedding Picker" + } + ], + "https://github.com/Tropfchen/ComfyUI-yaResolutionSelector": [ + [ + "YARS", + "YARSAdv" + ], + { + "title_aux": "YARS: Yet Another Resolution Selector" + } + ], + "https://github.com/Trung0246/ComfyUI-0246": [ + [ + "0246.Beautify", + "0246.BoxRange", + "0246.CastReroute", + "0246.Cloud", + "0246.Convert", + "0246.Count", + "0246.Highway", + "0246.HighwayBatch", + "0246.Hold", + "0246.Hub", + "0246.Junction", + "0246.JunctionBatch", + "0246.Loop", + "0246.Merge", + "0246.Meta", + "0246.Pick", + "0246.RandomInt", + "0246.Script", + "0246.ScriptNode", + "0246.ScriptPile", + "0246.ScriptRule", + "0246.Stringify", + "0246.Switch", + "0246.Tag" + ], + { + "author": "Trung0246", + "description": "Random nodes for ComfyUI I made to solve my struggle with ComfyUI (ex: pipe, process). Have varying quality.", + "nickname": "ComfyUI-0246", + "title": "ComfyUI-0246", + "title_aux": "ComfyUI-0246" + } + ], + "https://github.com/Ttl/ComfyUi_NNLatentUpscale": [ + [ + "NNLatentUpscale" + ], + { + "preemptions": [ + "NNLatentUpscale" + ], + "title_aux": "ComfyUI Neural Network Latent Upscale" + } + ], + "https://github.com/TylerZoro/SD3-Scaling": [ + [ + "SD3ImageScaleToTotalPixels" + ], + { + "title_aux": "SD3-Scaling" + } + ], + "https://github.com/Umikaze-job/select_folder_path_easy": [ + [ + "SelectFolderPathEasy" + ], + { + "title_aux": "select_folder_path_easy" + } + ], + "https://github.com/VAST-AI-Research/ComfyUI-Tripo": [ + [ + "TripoAPIImageToMeshNode", + "TripoAPITextToMeshNode", + "TripoGLBViewer" + ], + { + "title_aux": "Tripo for ComfyUI" + } + ], + "https://github.com/WASasquatch/ASTERR": [ + [ + "ASTERR", + "SaveASTERR" + ], + { + "title_aux": "ASTERR" + } + ], + "https://github.com/WASasquatch/ComfyUI_Preset_Merger": [ + [ + "Preset_Model_Merge" + ], + { + "title_aux": "ComfyUI Preset Merger" + } + ], + "https://github.com/WASasquatch/FreeU_Advanced": [ + [ + "FreeU (Advanced)", + "FreeU_V2 (Advanced)" + ], + { + "title_aux": "FreeU_Advanced" + } + ], + "https://github.com/WASasquatch/PPF_Noise_ComfyUI": [ + [ + "Blend Latents (PPF Noise)", + "Cross-Hatch Power Fractal (PPF Noise)", + "Images as Latents (PPF Noise)", + "Perlin Power Fractal Latent (PPF Noise)" + ], + { + "title_aux": "PPF_Noise_ComfyUI" + } + ], + "https://github.com/WASasquatch/PowerNoiseSuite": [ + [ + "Blend Latents (PPF Noise)", + "Cross-Hatch Power Fractal (PPF Noise)", + "Cross-Hatch Power Fractal Settings (PPF Noise)", + "Images as Latents (PPF Noise)", + "Latent Adjustment (PPF Noise)", + "Latents to CPU (PPF Noise)", + "Linear Cross-Hatch Power Fractal (PPF Noise)", + "Perlin Power Fractal Latent (PPF Noise)", + "Perlin Power Fractal Settings (PPF Noise)", + "Power KSampler Advanced (PPF Noise)", + "Power-Law Noise (PPF Noise)" + ], + { + "title_aux": "Power Noise Suite for ComfyUI" + } + ], + "https://github.com/WASasquatch/WAS_Extras": [ + [ + "BLVAEEncode", + "CLIPTextEncodeList", + "CLIPTextEncodeSequence2", + "ConditioningBlend", + "DebugInput", + "KSamplerSeq", + "KSamplerSeq2", + "VAEEncodeForInpaint (WAS)", + "VividSharpen" + ], + { + "title_aux": "WAS_Extras" + } + ], + "https://github.com/WASasquatch/was-node-suite-comfyui": [ + [ + "BLIP Analyze Image", + "BLIP Model Loader", + "Blend Latents", + "Boolean To Text", + "Bounded Image Blend", + "Bounded Image Blend with Mask", + "Bounded Image Crop", + "Bounded Image Crop with Mask", + "Bus Node", + "CLIP Input Switch", + "CLIP Vision Input Switch", + "CLIPSeg Batch Masking", + "CLIPSeg Masking", + "CLIPSeg Model Loader", + "CLIPTextEncode (BlenderNeko Advanced + NSP)", + "CLIPTextEncode (NSP)", + "Cache Node", + "Checkpoint Loader", + "Checkpoint Loader (Simple)", + "Conditioning Input Switch", + "Constant Number", + "Control Net Model Input Switch", + "Convert Masks to Images", + "Create Grid Image", + "Create Grid Image from Batch", + "Create Morph Image", + "Create Morph Image from Path", + "Create Video from Path", + "Debug Number to Console", + "Dictionary to Console", + "Diffusers Hub Model Down-Loader", + "Diffusers Model Loader", + "Export API", + "HSL to Hex", + "Hex to HSL", + "Image Analyze", + "Image Aspect Ratio", + "Image Batch", + "Image Blank", + "Image Blend", + "Image Blend by Mask", + "Image Blending Mode", + "Image Bloom Filter", + "Image Bounds", + "Image Bounds to Console", + "Image Canny Filter", + "Image Chromatic Aberration", + "Image Color Palette", + "Image Crop Face", + "Image Crop Location", + "Image Crop Square Location", + "Image Displacement Warp", + "Image Dragan Photography Filter", + "Image Edge Detection Filter", + "Image Film Grain", + "Image Filter Adjustments", + "Image Flip", + "Image Generate Gradient", + "Image Gradient Map", + "Image High Pass Filter", + "Image History Loader", + "Image Input Switch", + "Image Levels Adjustment", + "Image Load", + "Image Lucy Sharpen", + "Image Median Filter", + "Image Mix RGB Channels", + "Image Monitor Effects Filter", + "Image Nova Filter", + "Image Padding", + "Image Paste Crop", + "Image Paste Crop by Location", + "Image Paste Face", + "Image Perlin Noise", + "Image Perlin Power Fractal", + "Image Pixelate", + "Image Power Noise", + "Image Rembg (Remove Background)", + "Image Remove Background (Alpha)", + "Image Remove Color", + "Image Resize", + "Image Rotate", + "Image Rotate Hue", + "Image SSAO (Ambient Occlusion)", + "Image SSDO (Direct Occlusion)", + "Image Save", + "Image Seamless Texture", + "Image Select Channel", + "Image Select Color", + "Image Send HTTP", + "Image Shadows and Highlights", + "Image Size to Number", + "Image Stitch", + "Image Style Filter", + "Image Threshold", + "Image Tiled", + "Image Transpose", + "Image Voronoi Noise Filter", + "Image fDOF Filter", + "Image to Latent Mask", + "Image to Noise", + "Image to Seed", + "Images to Linear", + "Images to RGB", + "Inset Image Bounds", + "Integer place counter", + "KSampler (WAS)", + "KSampler Cycle", + "Latent Batch", + "Latent Input Switch", + "Latent Noise Injection", + "Latent Size to Number", + "Latent Upscale by Factor (WAS)", + "Load Cache", + "Load Image Batch", + "Load Lora", + "Load Text File", + "Logic Boolean", + "Logic Boolean Primitive", + "Logic Comparison AND", + "Logic Comparison OR", + "Logic Comparison XOR", + "Logic NOT", + "Lora Input Switch", + "Lora Loader", + "Mask Arbitrary Region", + "Mask Batch", + "Mask Batch to Mask", + "Mask Ceiling Region", + "Mask Crop Dominant Region", + "Mask Crop Minority Region", + "Mask Crop Region", + "Mask Dilate Region", + "Mask Dominant Region", + "Mask Erode Region", + "Mask Fill Holes", + "Mask Floor Region", + "Mask Gaussian Region", + "Mask Invert", + "Mask Minority Region", + "Mask Paste Region", + "Mask Smooth Region", + "Mask Threshold Region", + "Masks Add", + "Masks Combine Batch", + "Masks Combine Regions", + "Masks Subtract", + "MiDaS Depth Approximation", + "MiDaS Mask Image", + "MiDaS Model Loader", + "Model Input Switch", + "Number Counter", + "Number Input Condition", + "Number Input Switch", + "Number Multiple Of", + "Number Operation", + "Number PI", + "Number to Float", + "Number to Int", + "Number to Seed", + "Number to String", + "Number to Text", + "Prompt Multiple Styles Selector", + "Prompt Styles Selector", + "Random Number", + "SAM Image Mask", + "SAM Model Loader", + "SAM Parameters", + "SAM Parameters Combine", + "Samples Passthrough (Stat System)", + "Save Text File", + "Seed", + "String to Text", + "Tensor Batch to Image", + "Text Add Token by Input", + "Text Add Tokens", + "Text Compare", + "Text Concatenate", + "Text Contains", + "Text Dictionary Convert", + "Text Dictionary Get", + "Text Dictionary Keys", + "Text Dictionary New", + "Text Dictionary To Text", + "Text Dictionary Update", + "Text File History Loader", + "Text Find", + "Text Find and Replace", + "Text Find and Replace Input", + "Text Find and Replace by Dictionary", + "Text Input Switch", + "Text List", + "Text List Concatenate", + "Text List to Text", + "Text Load Line From File", + "Text Multiline", + "Text Multiline (Code Compatible)", + "Text Parse A1111 Embeddings", + "Text Parse Noodle Soup Prompts", + "Text Parse Tokens", + "Text Random Line", + "Text Random Prompt", + "Text Shuffle", + "Text Sort", + "Text String", + "Text String Truncate", + "Text to Conditioning", + "Text to Console", + "Text to Number", + "Text to String", + "True Random.org Number Generator", + "Upscale Model Loader", + "Upscale Model Switch", + "VAE Input Switch", + "Video Dump Frames", + "Write to GIF", + "Write to Video", + "unCLIP Checkpoint Loader" + ], + { + "title_aux": "WAS Node Suite" + } + ], + "https://github.com/WebDev9000/WebDev9000-Nodes": [ + [ + "IgnoreBraces", + "SettingsSwitch" + ], + { + "title_aux": "WebDev9000-Nodes" + } + ], + "https://github.com/Wicloz/ComfyUI-Simply-Nodes": [ + [ + "WF_ConditionalLoraLoader", + "WF_MultilineText", + "WF_RandomStyle", + "WF_ResolutionSDXL", + "WF_TextFlow" + ], + { + "title_aux": "ComfyUI Simply Nodes" + } + ], + "https://github.com/XmYx/deforum-comfy-nodes": [ + [ + "DeforumAddNoiseNode", + "DeforumAnimParamsNode", + "DeforumAreaPromptNode", + "DeforumBaseParamsNode", + "DeforumCacheLatentNode", + "DeforumCadenceNode", + "DeforumCadenceParamsNode", + "DeforumColorMatchNode", + "DeforumColorParamsNode", + "DeforumConditioningBlendNode", + "DeforumDepthParamsNode", + "DeforumDiffusionParamsNode", + "DeforumFILMInterpolationNode", + "DeforumFrameWarpNode", + "DeforumGetCachedLatentNode", + "DeforumHybridMotionNode", + "DeforumHybridParamsNode", + "DeforumHybridScheduleNode", + "DeforumIteratorNode", + "DeforumKSampler", + "DeforumLoadVideo", + "DeforumNoiseParamsNode", + "DeforumPromptNode", + "DeforumSeedNode", + "DeforumSetVAEDownscaleRatioNode", + "DeforumSimpleInterpolationNode", + "DeforumSingleSampleNode", + "DeforumTranslationParamsNode", + "DeforumVideoSaveNode" + ], + { + "title_aux": "Deforum Nodes" + } + ], + "https://github.com/Xyem/Xycuno-Oobabooga": [ + [ + "Oobabooga" + ], + { + "title_aux": "Xycuno Oobabooga" + } + ], + "https://github.com/YMC-GitHub/ymc-node-suite-comfyui": [ + [ + "canvas-util-cal-size", + "conditioning-util-input-switch", + "cutoff-region-util", + "hks-util-cal-denoise-step", + "img-util-get-image-size", + "img-util-switch-input-image", + "io-image-save", + "io-text-save", + "io-util-file-list-get", + "io-util-file-list-get-text", + "number-util-random-num", + "pipe-util-to-basic-pipe", + "region-util-get-by-center-and-size", + "region-util-get-by-lt", + "region-util-get-crop-location-from-center-size-text", + "region-util-get-pad-out-location-by-size", + "text-preset-colors", + "text-util-join-text", + "text-util-loop-text", + "text-util-path-list", + "text-util-prompt-add-prompt", + "text-util-prompt-adv-dup", + "text-util-prompt-adv-search", + "text-util-prompt-del", + "text-util-prompt-dup", + "text-util-prompt-join", + "text-util-prompt-search", + "text-util-prompt-shuffle", + "text-util-prompt-std", + "text-util-prompt-unweight", + "text-util-random-text", + "text-util-search-text", + "text-util-show-text", + "text-util-switch-text", + "xyz-util-txt-to-int" + ], + { + "title_aux": "ymc-node-suite-comfyui" + } + ], + "https://github.com/YOUR-WORST-TACO/ComfyUI-TacoNodes": [ + [ + "Example", + "TacoAnimatedLoader", + "TacoGifMaker", + "TacoImg2ImgAnimatedLoader", + "TacoImg2ImgAnimatedProcessor", + "TacoLatent" + ], + { + "title_aux": "ComfyUI-TacoNodes" + } + ], + "https://github.com/Yanick112/ComfyUI-ToSVG": [ + [ + "ConvertRasterToVector", + "SaveSVG" + ], + { + "title_aux": "ComfyUI-ToSVG" + } + ], + "https://github.com/YinBailiang/MergeBlockWeighted_fo_ComfyUI": [ + [ + "MergeBlockWeighted" + ], + { + "title_aux": "MergeBlockWeighted_fo_ComfyUI" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR": [ + [ + "APISR_Lterative_Zho", + "APISR_ModelLoader_Zho", + "APISR_Zho" + ], + { + "title_aux": "APISR IN COMFYUI" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Animated-optical-illusions": [ + [ + "AOI_Processing_Zho" + ], + { + "title_aux": "ComfyUI-Animated-optical-illusions" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-ArtGallery": [ + [ + "ArtGallery_Zho", + "ArtistsImage_Zho", + "CamerasImage_Zho", + "FilmsImage_Zho", + "MovementsImage_Zho", + "StylesImage_Zho" + ], + { + "title_aux": "ComfyUI-ArtGallery" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BRIA_AI-RMBG": [ + [ + "BRIA_RMBG_ModelLoader_Zho", + "BRIA_RMBG_Zho" + ], + { + "title_aux": "ComfyUI-BRIA_AI-RMBG" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BiRefNet-ZHO": [ + [ + "BiRefNet_ModelLoader_Zho", + "BiRefNet_Zho" + ], + { + "title_aux": "ComfyUI-BiRefNet-ZHO" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-DepthFM": [ + [ + "DepthFM_Literative_Zho", + "DepthFM_ModelLoader_Zho", + "DepthFM_Zho" + ], + { + "title_aux": "DepthFM IN COMFYUI" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Gemini": [ + [ + "ConcatText_Zho", + "DisplayText_Zho", + "Gemini_15P_API_S_Advance_Zho", + "Gemini_15P_API_S_Chat_Advance_Zho", + "Gemini_API_Chat_Zho", + "Gemini_API_S_Chat_Zho", + "Gemini_API_S_Vsion_ImgURL_Zho", + "Gemini_API_S_Zho", + "Gemini_API_Vsion_ImgURL_Zho", + "Gemini_API_Zho", + "Gemini_FileUpload_API_S_Zho", + "Gemini_File_API_S_Zho" + ], + { + "title_aux": "ComfyUI-Gemini" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-InstantID": [ + [ + "IDBaseModelLoader_fromhub", + "IDBaseModelLoader_local", + "IDControlNetLoader", + "IDGenerationNode", + "ID_Prompt_Styler", + "InsightFaceLoader_Zho", + "Ipadapter_instantidLoader" + ], + { + "title_aux": "ComfyUI-InstantID" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Phi-3-mini": [ + [ + "Phi3mini_4k_Chat_Zho", + "Phi3mini_4k_ModelLoader_Zho", + "Phi3mini_4k_Zho" + ], + { + "title_aux": "Phi-3-mini in ComfyUI" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PhotoMaker-ZHO": [ + [ + "BaseModel_Loader_fromhub", + "BaseModel_Loader_local", + "LoRALoader", + "NEW_PhotoMaker_Generation", + "PhotoMakerAdapter_Loader_fromhub", + "PhotoMakerAdapter_Loader_local", + "PhotoMaker_Generation", + "Prompt_Styler", + "Ref_Image_Preprocessing" + ], + { + "title_aux": "ComfyUI PhotoMaker (ZHO)" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PixArt-alpha-Diffusers": [ + [ + "PA_BaseModelLoader_fromhub_Zho", + "PA_Generation_Zho", + "PA_Styler_Zho" + ], + { + "title_aux": "ComfyUI-PixArt-alpha-Diffusers" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Q-Align": [ + [ + "QAlign_Zho" + ], + { + "title_aux": "ComfyUI-Q-Align" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-2": [ + [ + "Qwen2_Chat_Zho", + "Qwen2_ModelLoader_Zho", + "Qwen2_Zho" + ], + { + "title_aux": "ComfyUI-Qwen-2" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-VL-API": [ + [ + "QWenVL_API_S_Multi_Zho", + "QWenVL_API_S_Zho" + ], + { + "title_aux": "ComfyUI-Qwen-VL-API" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SVD-ZHO": [ + [ + "SVD_Aspect_Ratio_Zho", + "SVD_Steps_MotionStrength_Seed_Zho", + "SVD_Styler_Zho" + ], + { + "title_aux": "ComfyUI-SVD-ZHO (WIP)" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SegMoE": [ + [ + "SMoE_Generation_Zho", + "SMoE_ModelLoader_Zho" + ], + { + "title_aux": "ComfyUI SegMoE" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Text_Image-Composite": [ + [ + "AlphaChanelAddByMask", + "ImageCompositeBy_BG_Zho", + "ImageCompositeBy_Zho", + "ImageComposite_BG_Zho", + "ImageComposite_Zho", + "RGB_Image_Zho", + "Text_Image_Frame_Zho", + "Text_Image_Multiline_Zho", + "Text_Image_Zho" + ], + { + "title_aux": "ComfyUI-Text_Image-Composite [WIP]" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM": [ + [ + "ESAM_ModelLoader_Zho", + "Yoloworld_ESAM_DetectorProvider_Zho", + "Yoloworld_ESAM_Zho", + "Yoloworld_ModelLoader_Zho" + ], + { + "title_aux": "ComfyUI YoloWorld-EfficientSAM" + } + ], + "https://github.com/ZHO-ZHO-ZHO/comfyui-portrait-master-zh-cn": [ + [ + "PortraitMaster_\u4e2d\u6587\u7248" + ], + { + "title_aux": "comfyui-portrait-master-zh-cn" + } + ], + "https://github.com/ZZXYWQ/ComfyUI-ZZXYWQ": [ + [ + "VideoFormatConverter" + ], + { + "title_aux": "ZZX Nodes" + } + ], + "https://github.com/ZaneA/ComfyUI-ImageReward": [ + [ + "ImageRewardLoader", + "ImageRewardScore" + ], + { + "title_aux": "ImageReward" + } + ], + "https://github.com/ZeDarkAdam/ComfyUI-Embeddings-Tools": [ + [ + "EmbeddingsNameLoader", + "EmbendingList" + ], + { + "title_aux": "ComfyUI-Embeddings-Tools" + } + ], + "https://github.com/a1lazydog/ComfyUI-AudioScheduler": [ + [ + "AmplitudeToGraph", + "AmplitudeToNumber", + "AudioToAmplitudeGraph", + "AudioToFFTs", + "BatchAmplitudeSchedule", + "ClipAmplitude", + "FloatArrayToGraph", + "GateNormalizedAmplitude", + "LoadAudio", + "LoadVHSAudio", + "NormalizeAmplitude", + "NormalizedAmplitudeDrivenString", + "NormalizedAmplitudeToGraph", + "NormalizedAmplitudeToNumber", + "TransientAmplitudeBasic" + ], + { + "title_aux": "ComfyUI-AudioScheduler" + } + ], + "https://github.com/aburahamu/ComfyUI-IsNiceParts": [ + [ + "NiceHand" + ], + { + "title_aux": "ComfyUI-IsNiceParts" + } + ], + "https://github.com/aburahamu/ComfyUI-RequestsPoster": [ + [ + "GetImageFromSD3byI2I", + "GetImageFromSD3byT2I", + "PostImage2Discord", + "PostImage2X", + "PostText" + ], + { + "title_aux": "ComfyUI-RequestPoster" + } + ], + "https://github.com/abyz22/image_control": [ + [ + "abyz22_AddPrompt", + "abyz22_Convertpipe", + "abyz22_Editpipe", + "abyz22_FirstNonNull", + "abyz22_FromBasicPipe_v2", + "abyz22_Frompipe", + "abyz22_ImpactWildcardEncode", + "abyz22_ImpactWildcardEncode_GetPrompt", + "abyz22_Ksampler", + "abyz22_Padding Image", + "abyz22_RandomMask", + "abyz22_RemoveControlnet", + "abyz22_ResizeOpenpose", + "abyz22_SaveImage", + "abyz22_SetQueue", + "abyz22_ToBasicPipe", + "abyz22_Topipe", + "abyz22_blend_onecolor", + "abyz22_blendimages", + "abyz22_bypass", + "abyz22_censoring", + "abyz22_drawmask", + "abyz22_lamaInpaint", + "abyz22_lamaPreprocessor", + "abyz22_makecircles", + "abyz22_setimageinfo", + "abyz22_smallhead" + ], + { + "title_aux": "image_control" + } + ], + "https://github.com/adbrasi/ComfyUI-TrashNodes-DownloadHuggingface": [ + [ + "DownloadLinkChecker", + "ShowFileNames" + ], + { + "title_aux": "ComfyUI-TrashNodes-DownloadHuggingface" + } + ], + "https://github.com/adieyal/comfyui-dynamicprompts": [ + [ + "DPCombinatorialGenerator", + "DPFeelingLucky", + "DPJinja", + "DPMagicPrompt", + "DPOutput", + "DPRandomGenerator" + ], + { + "title_aux": "DynamicPrompts Custom Nodes" + } + ], + "https://github.com/adigayung/ComfyUI-Translator": [ + [ + "CLIP Text Encode (Auto Translate)" + ], + { + "title_aux": "ComfyUI-Translator" + } + ], + "https://github.com/adriflex/ComfyUI_Blender_Texdiff": [ + [ + "ViewportColor", + "ViewportDepth" + ], + { + "title_aux": "ComfyUI_Blender_Texdiff" + } + ], + "https://github.com/aegis72/aegisflow_utility_nodes": [ + [ + "Add Text To Image", + "Aegisflow CLIP Pass", + "Aegisflow Conditioning Pass", + "Aegisflow Image Pass", + "Aegisflow Latent Pass", + "Aegisflow Mask Pass", + "Aegisflow Model Pass", + "Aegisflow Pos/Neg Pass", + "Aegisflow SDXL Tuple Pass", + "Aegisflow VAE Pass", + "Aegisflow controlnet preprocessor bus", + "Apply Instagram Filter", + "Binary INT Switch", + "Brightness_Contrast_Ally", + "Flatten Colors", + "Gaussian Blur_Ally", + "GlitchThis Effect", + "Hue Rotation", + "Image Flip_ally", + "Placeholder Tuple", + "Swap Color Mode", + "aegisflow Multi_Pass", + "aegisflow Multi_Pass XL", + "af_pipe_in_15", + "af_pipe_in_xl", + "af_pipe_out_15", + "af_pipe_out_xl" + ], + { + "title_aux": "AegisFlow Utility Nodes" + } + ], + "https://github.com/aegis72/comfyui-styles-all": [ + [ + "menus" + ], + { + "title_aux": "ComfyUI-styles-all" + } + ], + "https://github.com/ai-liam/comfyui-liam": [ + [ + "AiStoreAzureGPTLiam", + "GetBetterDepthImage", + "LiamLibDisplayText", + "LiamLibFillImage", + "LiamLibImageToGray", + "LiamLibLoadImage", + "LiamLibMergeText", + "LiamLibSaveImg", + "LiamLibSaveText", + "OllamaApiTNodeLiam", + "PreviewReliefImage", + "SpeechRecognitionLiam", + "SpeechSynthesisLiam" + ], + { + "title_aux": "LiamUtil" + } + ], + "https://github.com/ai-liam/comfyui_liam_util": [ + [ + "LiamLoadImage" + ], + { + "title_aux": "LiamUtil (single node)" + } + ], + "https://github.com/aianimation55/ComfyUI-FatLabels": [ + [ + "FatLabels" + ], + { + "title_aux": "Comfy UI FatLabels" + } + ], + "https://github.com/al-swaiti/ComfyUI-CascadeResolutions": [ + [ + "CascadeResolutions" + ], + { + "title_aux": "ComfyUI-CascadeResolutions" + } + ], + "https://github.com/alessandrozonta/ComfyUI-CenterNode": [ + [ + "BBoxCrop" + ], + { + "title_aux": "Bounding Box Crop Node for ComfyUI" + } + ], + "https://github.com/alessandrozonta/ComfyUI-Layers": [ + [ + "LayersSaver - Save Layer", + "LayersSaver - Save Layer From Images" + ], + { + "title_aux": "Save Layers Node for ComfyUI" + } + ], + "https://github.com/alessandrozonta/ComfyUI-OpenPose": [ + [ + "OpenPose - Get poses" + ], + { + "author": "joe", + "title_aux": "OpenPose Node" + } + ], + "https://github.com/alexopus/ComfyUI-Image-Saver": [ + [ + "Cfg Literal (Image Saver)", + "Checkpoint Loader with Name (Image Saver)", + "Float Literal (Image Saver)", + "Image Saver", + "Int Literal (Image Saver)", + "Sampler Selector (Image Saver)", + "Scheduler Selector (Comfy) (Image Saver)", + "Scheduler Selector (Image Saver)", + "SchedulerComfyToString (Image Saver)", + "SchedulerToString (Image Saver)", + "Seed Generator (Image Saver)", + "String Literal (Image Saver)", + "Width/Height Literal (Image Saver)" + ], + { + "title_aux": "ComfyUI Image Saver" + } + ], + "https://github.com/alisson-anjos/ComfyUI-Ollama-Describer": [ + [ + "InputText", + "OllamaImageDescriber", + "OllamaTextDescriber", + "ShowText", + "TextTransformer" + ], + { + "title_aux": "ComfyUI-Ollama-Describer" + } + ], + "https://github.com/alpertunga-bile/prompt-generator-comfyui": [ + [ + "Prompt Generator" + ], + { + "title_aux": "prompt-generator" + } + ], + "https://github.com/alsritter/asymmetric-tiling-comfyui": [ + [ + "Asymmetric_Tiling_KSampler" + ], + { + "title_aux": "asymmetric-tiling-comfyui" + } + ], + "https://github.com/alt-key-project/comfyui-dream-project": [ + [ + "Analyze Palette [Dream]", + "Beat Curve [Dream]", + "Big Float Switch [Dream]", + "Big Image Switch [Dream]", + "Big Int Switch [Dream]", + "Big Latent Switch [Dream]", + "Big Palette Switch [Dream]", + "Big Text Switch [Dream]", + "Boolean To Float [Dream]", + "Boolean To Int [Dream]", + "Build Prompt [Dream]", + "CSV Curve [Dream]", + "CSV Generator [Dream]", + "Calculation [Dream]", + "Common Frame Dimensions [Dream]", + "Compare Palettes [Dream]", + "FFMPEG Video Encoder [Dream]", + "File Count [Dream]", + "Finalize Prompt [Dream]", + "Float Input [Dream]", + "Float to Log Entry [Dream]", + "Frame Count Calculator [Dream]", + "Frame Counter (Directory) [Dream]", + "Frame Counter (Simple) [Dream]", + "Frame Counter Info [Dream]", + "Frame Counter Offset [Dream]", + "Frame Counter Time Offset [Dream]", + "Image Brightness Adjustment [Dream]", + "Image Color Shift [Dream]", + "Image Contrast Adjustment [Dream]", + "Image Motion [Dream]", + "Image Sequence Blend [Dream]", + "Image Sequence Loader [Dream]", + "Image Sequence Saver [Dream]", + "Image Sequence Tweening [Dream]", + "Int Input [Dream]", + "Int to Log Entry [Dream]", + "Laboratory [Dream]", + "Linear Curve [Dream]", + "Log Entry Joiner [Dream]", + "Log File [Dream]", + "Noise from Area Palettes [Dream]", + "Noise from Palette [Dream]", + "Palette Color Align [Dream]", + "Palette Color Shift [Dream]", + "Sample Image Area as Palette [Dream]", + "Sample Image as Palette [Dream]", + "Saw Curve [Dream]", + "Sine Curve [Dream]", + "Smooth Event Curve [Dream]", + "String Input [Dream]", + "String Tokenizer [Dream]", + "String to Log Entry [Dream]", + "Text Input [Dream]", + "Triangle Curve [Dream]", + "Triangle Event Curve [Dream]", + "WAV Curve [Dream]" + ], + { + "title_aux": "Dream Project Animation Nodes" + } + ], + "https://github.com/alt-key-project/comfyui-dream-video-batches": [ + [ + "Blended Transition [DVB]", + "Calculation [DVB]", + "Create Frame Set [DVB]", + "Divide [DVB]", + "Fade From Black [DVB]", + "Fade To Black [DVB]", + "Float Input [DVB]", + "For Each Done [DVB]", + "For Each Filename [DVB]", + "Frame Set Append [DVB]", + "Frame Set Frame Dimensions Scaled [DVB]", + "Frame Set Index Offset [DVB]", + "Frame Set Merger [DVB]", + "Frame Set Reindex [DVB]", + "Frame Set Repeat [DVB]", + "Frame Set Reverse [DVB]", + "Frame Set Split Beginning [DVB]", + "Frame Set Split End [DVB]", + "Frame Set Splitter [DVB]", + "Generate Inbetween Frames [DVB]", + "Int Input [DVB]", + "Linear Camera Pan [DVB]", + "Linear Camera Roll [DVB]", + "Linear Camera Zoom [DVB]", + "Load Image From Path [DVB]", + "Multiply [DVB]", + "Sine Camera Pan [DVB]", + "Sine Camera Roll [DVB]", + "Sine Camera Zoom [DVB]", + "String Input [DVB]", + "Text Input [DVB]", + "Trace Memory Allocation [DVB]", + "Unwrap Frame Set [DVB]" + ], + { + "title_aux": "Dream Video Batches" + } + ], + "https://github.com/an90ray/ComfyUI_RErouter_CustomNodes": [ + [ + "CLIPTextEncode (RE)", + "CLIPTextEncodeSDXL (RE)", + "CLIPTextEncodeSDXLRefiner (RE)", + "Int (RE)", + "RErouter <=", + "RErouter =>", + "String (RE)" + ], + { + "title_aux": "ComfyUI_RErouter_CustomNodes" + } + ], + "https://github.com/andersxa/comfyui-PromptAttention": [ + [ + "CLIPAttentionMaskEncode" + ], + { + "title_aux": "CLIP Directional Prompt Attention" + } + ], + "https://github.com/angeloshredder/StableCascadeResizer": [ + [ + "CascadeResize" + ], + { + "title_aux": "StableCascadeResizer" + } + ], + "https://github.com/ansonkao/comfyui-geometry": [ + [ + "TransformTemplateOntoFaceMask" + ], + { + "author": "Anson Kao", + "description": "A small collection of custom nodes for use with ComfyUI, by Discopixel", + "nickname": "ComfyUI Discopixel", + "title": "ComfyUI Discopixel", + "title_aux": "comfyui-geometry" + } + ], + "https://github.com/antrobot1234/antrobots-comfyUI-nodepack": [ + [ + "composite", + "crop", + "paste", + "preview_mask", + "scale" + ], + { + "title_aux": "antrobots ComfyUI Nodepack" + } + ], + "https://github.com/asagi4/ComfyUI-Adaptive-Guidance": [ + [ + "AdaptiveGuidance" + ], + { + "title_aux": "Adaptive Guidance for ComfyUI" + } + ], + "https://github.com/asagi4/ComfyUI-CADS": [ + [ + "CADS" + ], + { + "title_aux": "ComfyUI-CADS" + } + ], + "https://github.com/asagi4/comfyui-prompt-control": [ + [ + "EditableCLIPEncode", + "FilterSchedule", + "LoRAScheduler", + "PCApplySettings", + "PCPromptFromSchedule", + "PCScheduleAddMasks", + "PCScheduleSettings", + "PCSplitSampling", + "PCWrapGuider", + "PromptControlSimple", + "PromptToSchedule", + "ScheduleToCond", + "ScheduleToModel" + ], + { + "title_aux": "ComfyUI prompt control" + } + ], + "https://github.com/asagi4/comfyui-utility-nodes": [ + [ + "MUForceCacheClear", + "MUJinjaRender", + "MUReplaceModelWeights", + "MUSimpleWildcard" + ], + { + "title_aux": "asagi4/comfyui-utility-nodes" + } + ], + "https://github.com/aszc-dev/ComfyUI-CoreMLSuite": [ + [ + "Core ML Converter", + "Core ML LCM Converter", + "Core ML LoRA Loader", + "CoreMLModelAdapter", + "CoreMLSampler", + "CoreMLSamplerAdvanced", + "CoreMLUNetLoader" + ], + { + "title_aux": "Core ML Suite for ComfyUI" + } + ], + "https://github.com/audioscavenger/ComfyUI-Thumbnails": [ + [ + "LoadImageThumbnails" + ], + { + "author": "AudioscavengeR", + "description": "Load Image thumbnails and show input subfolders.", + "nickname": "ComfyUI Thumbnails", + "title": "ComfyUI Thumbnails", + "title_aux": "ComfyUI Thumbnails" + } + ], + "https://github.com/audioscavenger/save-image-extended-comfyui": [ + [ + "SaveImageExtended" + ], + { + "title_aux": "Save Image Extended for ComfyUI" + } + ], + "https://github.com/avatechai/avatar-graph-comfyui": [ + [ + "ApplyMeshTransformAsShapeKey", + "B_ENUM", + "B_VECTOR3", + "B_VECTOR4", + "Combine Points", + "CreateShapeFlow", + "ExportBlendshapes", + "ExportGLTF", + "Extract Boundary Points", + "Image Alpha Mask Merge", + "ImageBridge", + "LoadImageFromRequest", + "LoadImageWithAlpha", + "LoadValueFromRequest", + "SAM MultiLayer", + "Save Image With Workflow" + ], + { + "author": "Avatech Limited", + "description": "Include nodes for sam + bpy operation, that allows workflow creations for generative 2d character rig.", + "nickname": "Avatar Graph", + "title": "Avatar Graph", + "title_aux": "Avatar Graph" + } + ], + "https://github.com/aws-samples/comfyui-llm-node-for-amazon-bedrock": [ + [ + "Bedrock - Claude", + "Bedrock - Claude Multimodal", + "Bedrock - SDXL", + "Bedrock - Titan Inpainting", + "Bedrock - Titan Outpainting", + "Bedrock - Titan Text to Image", + "Bedrock - Titan Variation", + "Image From S3", + "Image From URL", + "Image To S3", + "Prompt Regex Remove", + "Prompt Template" + ], + { + "title_aux": "Amazon Bedrock nodes for ComfyUI" + } + ], + "https://github.com/azure-dragon-ai/ComfyUI-ClipScore-Nodes": [ + [ + "HaojihuiClipScoreFakeImageProcessor", + "HaojihuiClipScoreImageProcessor", + "HaojihuiClipScoreImageScore", + "HaojihuiClipScoreLoader", + "HaojihuiClipScoreRealImageProcessor", + "HaojihuiClipScoreTextProcessor" + ], + { + "title_aux": "ComfyUI-ClipScore-Nodes" + } + ], + "https://github.com/badayvedat/ComfyUI-fal-Connector": [ + [ + "RemoteCheckpointLoader_fal", + "RemoteLoraLoader_fal" + ], + { + "title_aux": "ComfyUI-fal-Connector" + } + ], + "https://github.com/badjeff/comfyui_lora_tag_loader": [ + [ + "LoraTagLoader" + ], + { + "title_aux": "LoRA Tag Loader for ComfyUI" + } + ], + "https://github.com/baicai99/ComfyUI-FrameSkipping": [ + [ + "FrameSelector", + "FrameSkipping", + "FrameTruncating", + "IntOperationsNode", + "MaskFrameSkipping", + "MaskGenerator", + "MaskSelector" + ], + { + "title_aux": "ComfyUI-FrameSkipping" + } + ], + "https://github.com/banodoco/steerable-motion": [ + [ + "BatchCreativeInterpolation", + "IpaConfiguration", + "RemoveAndInterpolateFrames" + ], + { + "title_aux": "Steerable Motion" + } + ], + "https://github.com/barckley75/comfyUI_DaVinciResolve/raw/main/custom_nodes/node_text_to_speech.py": [ + [ + "TextToSpeech" + ], + { + "title_aux": "comfyUI_DaVinciResolve" + } + ], + "https://github.com/bash-j/mikey_nodes": [ + [ + "AddMetaData", + "Batch Crop Image", + "Batch Crop Resize Inplace", + "Batch Load Images", + "Batch Resize Image for SDXL", + "Checkpoint Loader Simple Mikey", + "CheckpointHash", + "CinematicLook", + "Empty Latent Ratio Custom SDXL", + "Empty Latent Ratio Select SDXL", + "EvalFloats", + "FaceFixerOpenCV", + "FileNamePrefix", + "FileNamePrefixDateDirFirst", + "Float to String", + "GetSubdirectories", + "HaldCLUT", + "Image Caption", + "ImageBorder", + "ImageOverlay", + "ImagePaste", + "Int to String", + "LMStudioPrompt", + "Load Image Based on Number", + "LoraSyntaxProcessor", + "Mikey Sampler", + "Mikey Sampler Base Only", + "Mikey Sampler Base Only Advanced", + "Mikey Sampler Tiled", + "Mikey Sampler Tiled Base Only", + "MikeyLatentTileSampler", + "MikeyLatentTileSamplerCustom", + "MikeySamplerTiledAdvanced", + "MikeySamplerTiledAdvancedBaseOnly", + "MosaicExpandImage", + "OobaPrompt", + "PresetRatioSelector", + "Prompt With SDXL", + "Prompt With Style", + "Prompt With Style V2", + "Prompt With Style V3", + "Range Float", + "Range Integer", + "Ratio Advanced", + "Resize Image for SDXL", + "SD3TextConditioningWithOptionsOnePrompt", + "SRFloatPromptInput", + "SRIntPromptInput", + "SRStringPromptInput", + "Save Image If True", + "Save Image With Prompt Data", + "Save Images Mikey", + "Save Images No Display", + "SaveMetaData", + "SearchAndReplace", + "Seed String", + "Style Conditioner", + "Style Conditioner Base Only", + "Text2InputOr3rdOption", + "TextCombinations", + "TextCombinations3", + "TextConcat", + "TextPadderMikey", + "TextPreserve", + "Upscale Tile Calculator", + "Wildcard Processor", + "WildcardAndLoraSyntaxProcessor", + "WildcardOobaPrompt" + ], + { + "title_aux": "Mikey Nodes" + } + ], + "https://github.com/bedovyy/ComfyUI_NAIDGenerator": [ + [ + "GenerateNAID", + "Img2ImgOptionNAID", + "InpaintingOptionNAID", + "MaskImageToNAID", + "ModelOptionNAID", + "PromptToNAID", + "VibeTransferOptionNAID" + ], + { + "title_aux": "ComfyUI_NAIDGenerator" + } + ], + "https://github.com/bilal-arikan/ComfyUI_TextAssets": [ + [ + "LoadTextAsset" + ], + { + "title_aux": "ComfyUI_TextAssets" + } + ], + "https://github.com/bitaffinity/ComfyUI_HF_Inference": [ + [ + "Classification", + "FeatureExtraction", + "Generation", + "ObjectDetection", + "QuestionAnswering", + "Segmentation", + "TextToImage", + "Translation" + ], + { + "title_aux": "ComfyUI_HF_Inference" + } + ], + "https://github.com/bkunbargi/BrevImage/raw/main/BrevLoadImage.py": [ + [ + "BrevImage" + ], + { + "title_aux": "BrevImage" + } + ], + "https://github.com/blepping/ComfyUI-bleh": [ + [ + "BlehBlockOps", + "BlehDeepShrink", + "BlehDisableNoise", + "BlehDiscardPenultimateSigma", + "BlehForceSeedSampler", + "BlehHyperTile", + "BlehInsaneChainSampler", + "BlehLatentOps", + "BlehLatentScaleBy", + "BlehModelPatchConditional", + "BlehPlug", + "BlehRefinerAfter" + ], + { + "title_aux": "ComfyUI-bleh" + } + ], + "https://github.com/blepping/ComfyUI-sonar": [ + [ + "NoisyLatentLike", + "SamplerConfigOverride", + "SamplerSonarDPMPPSDE", + "SamplerSonarEuler", + "SamplerSonarEulerA", + "SonarCompositeNoise", + "SonarCustomNoise", + "SonarGuidanceConfig", + "SonarGuidedNoise", + "SonarModulatedNoise", + "SonarRandomNoise", + "SonarRepeatedNoise", + "SonarScheduledNoise" + ], + { + "title_aux": "ComfyUI-sonar" + } + ], + "https://github.com/blepping/comfyui_jankhidiffusion": [ + [ + "ApplyMSWMSAAttention", + "ApplyMSWMSAAttentionSimple", + "ApplyRAUNet", + "ApplyRAUNetSimple" + ], + { + "title_aux": "ComfyUI jank HiDiffusion" + } + ], + "https://github.com/blueraincoatli/comfyUI_SillyNodes": [ + [ + "BooleanJumper|SillyNode", + "QueueSequence|SillyNode", + "Screenshots|SillyNode", + "dummyInput|SillyNode", + "dummyInput|blueraincoat" + ], + { + "title_aux": "comfyUI_SillyNodes" + } + ], + "https://github.com/bluevisor/ComfyUI_PS_Blend_Node": [ + [ + "PSBlendNode" + ], + { + "title_aux": "ComfyUI_PS_Blend_Node" + } + ], + "https://github.com/bmad4ever/comfyui_ab_samplercustom": [ + [ + "AB SamplerCustom (experimental)" + ], + { + "title_aux": "comfyui_ab_sampler" + } + ], + "https://github.com/bmad4ever/comfyui_bmad_nodes": [ + [ + "AdaptiveThresholding", + "Add String To Many", + "AddAlpha", + "AdjustRect", + "AnyToAny", + "BoundingRect (contours)", + "BuildColorRangeAdvanced (hsv)", + "BuildColorRangeHSV (hsv)", + "CLAHE", + "CLIPEncodeMultiple", + "CLIPEncodeMultipleAdvanced", + "ChameleonMask", + "CheckpointLoader (dirty)", + "CheckpointLoaderSimple (dirty)", + "Color (RGB)", + "Color (hexadecimal)", + "Color Clip", + "Color Clip (advanced)", + "Color Clip ADE20k", + "ColorDictionary", + "ColorDictionary (custom)", + "Conditioning (combine multiple)", + "Conditioning (combine selective)", + "Conditioning Grid (cond)", + "Conditioning Grid (string)", + "Conditioning Grid (string) Advanced", + "Contour To Mask", + "Contours", + "ControlNetHadamard", + "ControlNetHadamard (manual)", + "ConvertImg", + "CopyMakeBorder", + "CreateRequestMetadata", + "DistanceTransform", + "Draw Contour(s)", + "EqualizeHistogram", + "ExtendColorList", + "ExtendCondList", + "ExtendFloatList", + "ExtendImageList", + "ExtendIntList", + "ExtendLatentList", + "ExtendMaskList", + "ExtendModelList", + "ExtendStringList", + "FadeMaskEdges", + "Filter Contour", + "FindComplementaryColor", + "FindThreshold", + "FlatLatentsIntoSingleGrid", + "Framed Mask Grab Cut", + "Framed Mask Grab Cut 2", + "FromListGet1Color", + "FromListGet1Cond", + "FromListGet1Float", + "FromListGet1Image", + "FromListGet1Int", + "FromListGet1Latent", + "FromListGet1Mask", + "FromListGet1Model", + "FromListGet1String", + "FromListGetColors", + "FromListGetConds", + "FromListGetFloats", + "FromListGetImages", + "FromListGetInts", + "FromListGetLatents", + "FromListGetMasks", + "FromListGetModels", + "FromListGetStrings", + "Get Contour from list", + "Get Models", + "Get Prompt", + "HypernetworkLoader (dirty)", + "ImageBatchToList", + "InRange (hsv)", + "Inpaint", + "Input/String to Int Array", + "KMeansColor", + "Load 64 Encoded Image", + "LoraLoader (dirty)", + "MaskGrid N KSamplers Advanced", + "MaskOuterBlur", + "Merge Latent Batch Gridwise", + "MonoMerge", + "MorphologicOperation", + "MorphologicSkeletoning", + "NaiveAutoKMeansColor", + "OtsuThreshold", + "RGB to HSV", + "Rect Grab Cut", + "Remap", + "RemapBarrelDistortion", + "RemapFromInsideParabolas", + "RemapFromQuadrilateral (homography)", + "RemapInsideParabolas", + "RemapInsideParabolasAdvanced", + "RemapPinch", + "RemapReverseBarrelDistortion", + "RemapStretch", + "RemapToInnerCylinder", + "RemapToOuterCylinder", + "RemapToQuadrilateral", + "RemapWarpPolar", + "Repeat Into Grid (image)", + "Repeat Into Grid (latent)", + "RequestInputs", + "SampleColorHSV", + "Save Image (api)", + "SeamlessClone", + "SeamlessClone (simple)", + "SetRequestStateToComplete", + "String", + "String to Float", + "String to Integer", + "ToColorList", + "ToCondList", + "ToFloatList", + "ToImageList", + "ToIntList", + "ToLatentList", + "ToMaskList", + "ToModelList", + "ToStringList", + "UnGridify (image)", + "VAEEncodeBatch" + ], + { + "title_aux": "Bmad Nodes" + } + ], + "https://github.com/bmad4ever/comfyui_lists_cartesian_product": [ + [ + "AnyListCartesianProduct" + ], + { + "title_aux": "Lists Cartesian Product" + } + ], + "https://github.com/bmad4ever/comfyui_quilting": [ + [ + "ImageQuilting_Bmad", + "LatentQuilting_Bmad" + ], + { + "title_aux": "comfyui_quilting" + } + ], + "https://github.com/bmad4ever/comfyui_wfc_like": [ + [ + "WFC_CustomTemperature_Bmad", + "WFC_CustomValueWeights_Bmad", + "WFC_Decode_BMad", + "WFC_EmptyState_Bmad", + "WFC_Encode_BMad", + "WFC_Filter_Bmad", + "WFC_GenParallel_Bmad", + "WFC_Generate_BMad", + "WFC_SampleNode_BMad" + ], + { + "title_aux": "comfyui_wfc_like" + } + ], + "https://github.com/bobmagicii/comfykit-custom-nodes": [ + [ + "LoraThree", + "LoraWithMeta", + "TypecasterImage", + "TypecasterLatent" + ], + { + "title_aux": "ComfyKit Custom Nodes" + } + ], + "https://github.com/bradsec/ComfyUI_ResolutionSelector": [ + [ + "ResolutionSelector" + ], + { + "title_aux": "ResolutionSelector for ComfyUI" + } + ], + "https://github.com/bradsec/ComfyUI_StringTools": [ + [ + "ModifyStringNode", + "RandomStringNode", + "ReplaceStringNode", + "ShowStringNode", + "TextStringNode" + ], + { + "title_aux": "ComfyUI_StringTools" + } + ], + "https://github.com/braintacles/braintacles-comfyui-nodes": [ + [ + "CLIPTextEncodeSDXL-Multi-IO", + "CLIPTextEncodeSDXL-Pipe", + "Empty Latent Image from Aspect-Ratio", + "Interval Sampler", + "Random Find and Replace" + ], + { + "title_aux": "braintacles-nodes" + } + ], + "https://github.com/brianfitzgerald/style_aligned_comfy": [ + [ + "StyleAlignedBatchAlign", + "StyleAlignedReferenceSampler", + "StyleAlignedSampleReferenceLatents" + ], + { + "title_aux": "StyleAligned for ComfyUI" + } + ], + "https://github.com/bronkula/comfyui-fitsize": [ + [ + "FS: Crop Image Into Even Pieces", + "FS: Fit Image And Resize", + "FS: Fit Size From Image", + "FS: Fit Size From Int", + "FS: Image Region To Mask", + "FS: Load Image And Resize To Fit", + "FS: Pick Image From Batch", + "FS: Pick Image From Batches", + "FS: Pick Image From List" + ], + { + "title_aux": "comfyui-fitsize" + } + ], + "https://github.com/bruefire/ComfyUI-SeqImageLoader": [ + [ + "VFrame Loader With Mask Editor", + "Video Loader With Mask Editor" + ], + { + "title_aux": "ComfyUI Sequential Image Loader" + } + ], + "https://github.com/budihartono/comfyui_otonx_nodes": [ + [ + "OTX Integer Multiple Inputs 4", + "OTX Integer Multiple Inputs 5", + "OTX Integer Multiple Inputs 6", + "OTX KSampler Feeder", + "OTX Versatile Multiple Inputs 4", + "OTX Versatile Multiple Inputs 5", + "OTX Versatile Multiple Inputs 6" + ], + { + "title_aux": "Otonx's Custom Nodes" + } + ], + "https://github.com/bvhari/ComfyUI_ImageProcessing": [ + [ + "BilateralFilter", + "Brightness", + "Gamma", + "Hue", + "Saturation", + "SigmoidCorrection", + "UnsharpMask" + ], + { + "title_aux": "ImageProcessing" + } + ], + "https://github.com/bvhari/ComfyUI_PerpWeight": [ + [ + "CLIPTextEncodePerpWeight" + ], + { + "title_aux": "ComfyUI_PerpWeight" + } + ], + "https://github.com/bvhari/ComfyUI_SUNoise": [ + [ + "SUNoiseLatent", + "SamplerDPM2Ancestral_SUN", + "SamplerDPMPP2SAncestral_SUN", + "SamplerDPMPP_2M_SDE_SUN", + "SamplerDPMPP_3M_SDE_SUN", + "SamplerDPMPP_SDE_SUN", + "SamplerEulerAncestralCFGpp_SUN", + "SamplerEulerAncestral_SUN", + "SamplersSUNoise", + "SamplersSUNoiseAdvanced" + ], + { + "title_aux": "ComfyUI_SUNoise" + } + ], + "https://github.com/catscandrive/comfyui-imagesubfolders/raw/main/loadImageWithSubfolders.py": [ + [ + "LoadImagewithSubfolders" + ], + { + "title_aux": "Image loader with subfolders" + } + ], + "https://github.com/cdb-boop/ComfyUI-Bringing-Old-Photos-Back-to-Life": [ + [ + "BOPBTL_BlendFaces", + "BOPBTL_DetectEnhanceBlendFaces", + "BOPBTL_DetectFaces", + "BOPBTL_EnhanceFaces", + "BOPBTL_EnhanceFacesAdvanced", + "BOPBTL_LoadFaceDetectorModel", + "BOPBTL_LoadFaceEnhancerModel", + "BOPBTL_LoadRestoreOldPhotosModel", + "BOPBTL_LoadScratchMaskModel", + "BOPBTL_RestoreOldPhotos", + "BOPBTL_ScratchMask" + ], + { + "title_aux": "ComfyUI Bringing Old Photos Back to Life" + } + ], + "https://github.com/cdb-boop/comfyui-image-round": [ + [ + "ComfyUI_Image_Round__ImageCropAdvanced", + "ComfyUI_Image_Round__ImageRound", + "ComfyUI_Image_Round__ImageRoundAdvanced" + ], + { + "title_aux": "comfyui-image-round" + } + ], + "https://github.com/celsojr2013/comfyui_jamworks_client": [ + [ + "Jamworks_Download", + "Jamworks_Login", + "Shell_Command" + ], + { + "title_aux": "comfyui_jamworks_client" + } + ], + "https://github.com/celsojr2013/comfyui_simpletools": [ + [ + "GoogleTranslator", + "Parameters", + "ResolutionSolver" + ], + { + "title_aux": "ComfyUI SimpleTools Suit" + } + ], + "https://github.com/cerspense/ComfyUI_cspnodes": [ + [ + "ImageDirIterator", + "Modelscopet2v", + "Modelscopev2v", + "RemapRange", + "SplitImageChannels", + "TextFileLineIterator", + "VidDirIterator" + ], + { + "title_aux": "cspnodes" + } + ], + "https://github.com/ceruleandeep/ComfyUI-LLaVA-Captioner": [ + [ + "LlavaCaptioner" + ], + { + "title_aux": "ComfyUI LLaVA Captioner" + } + ], + "https://github.com/chakib-belgaid/ComfyUI-autosize": [ + [ + "CustomAutoSize", + "SDXLAutoSize" + ], + { + "title_aux": "ComfyUI-autosize" + } + ], + "https://github.com/chakib-belgaid/Comfyui_Prompt_styler": [ + [ + "Prompt_Styler" + ], + { + "title_aux": "ComfyUI Style Plugin" + } + ], + "https://github.com/chandlergis/ComfyUI-IMG_Query": [ + [ + "ImageRequestNode" + ], + { + "title_aux": "ComfyUI-IMG_Query" + } + ], + "https://github.com/chandlergis/ComfyUI_EmojiOverlay": [ + [ + "Image Emoji Overlay" + ], + { + "title_aux": "ComfyUI_EmojiOverlay" + } + ], + "https://github.com/chaojie/ComfyUI-AniPortrait": [ + [ + "AniPortraitLoader", + "AniPortraitRun", + "Box2Video", + "CoverVideo", + "MaskList2Video" + ], + { + "title_aux": "ComfyUI-AniPortrait" + } + ], + "https://github.com/chaojie/ComfyUI-CameraCtrl-Wrapper": [ + [ + "CameraBasic", + "CameraCombine", + "CameraCtrlLoader", + "CameraCtrlRun", + "CameraJoin", + "CameraTrajectory" + ], + { + "title_aux": "ComfyUI-CameraCtrl-Wrapper" + } + ], + "https://github.com/chaojie/ComfyUI-Champ": [ + [ + "ChampLoader", + "ChampRun", + "ImageCombineOneColumn", + "ImageCombineOneRow" + ], + { + "title_aux": "ComfyUI-Champ" + } + ], + "https://github.com/chaojie/ComfyUI-DragAnything": [ + [ + "DragAnythingLoader", + "DragAnythingPipelineRun", + "DragAnythingPipelineRunRandom", + "DragAnythingRun", + "DragAnythingRunRandom", + "LoadText", + "SaveText", + "VHS_FILENAMES_STRING" + ], + { + "title_aux": "ComfyUI-DragAnything" + } + ], + "https://github.com/chaojie/ComfyUI-DragNUWA": [ + [ + "BrushMotion", + "CompositeMotionBrush", + "CompositeMotionBrushWithoutModel", + "DragNUWA Run", + "DragNUWA Run MotionBrush", + "Get First Image", + "Get Last Image", + "InstantCameraMotionBrush", + "InstantObjectMotionBrush", + "Load CheckPoint DragNUWA", + "Load MotionBrush From Optical Flow", + "Load MotionBrush From Optical Flow Directory", + "Load MotionBrush From Optical Flow Without Model", + "Load MotionBrush From Tracking Points", + "Load MotionBrush From Tracking Points Without Model", + "Load Pose KeyPoints", + "Loop", + "LoopEnd_IMAGE", + "LoopStart_IMAGE", + "Split Tracking Points" + ], + { + "title_aux": "ComfyUI-DragNUWA" + } + ], + "https://github.com/chaojie/ComfyUI-DynamiCrafter": [ + [ + "DynamiCrafter Simple", + "DynamiCrafterInterp Simple", + "DynamiCrafterInterpLoader", + "DynamiCrafterLoader" + ], + { + "title_aux": "ComfyUI-DynamiCrafter" + } + ], + "https://github.com/chaojie/ComfyUI-EasyAnimate": [ + [ + "EasyAnimateLoader", + "EasyAnimateRun" + ], + { + "title_aux": "ComfyUI-EasyAnimate" + } + ], + "https://github.com/chaojie/ComfyUI-Gemma": [ + [ + "GemmaLoader", + "GemmaRun" + ], + { + "title_aux": "ComfyUI-Gemma" + } + ], + "https://github.com/chaojie/ComfyUI-I2VGEN-XL": [ + [ + "I2VGEN-XL Simple", + "Modelscope Pipeline Loader" + ], + { + "title_aux": "ComfyUI-I2VGEN-XL" + } + ], + "https://github.com/chaojie/ComfyUI-Img2Img-Turbo": [ + [ + "Img2ImgTurboEdgeLoader", + "Img2ImgTurboEdgeRun", + "Img2ImgTurboSketchLoader", + "Img2ImgTurboSketchRun" + ], + { + "title_aux": "ComfyUI-Img2Img-Turbo" + } + ], + "https://github.com/chaojie/ComfyUI-LaVIT": [ + [ + "VHS_FILENAMES_STRING_LaVIT", + "VideoLaVITI2I", + "VideoLaVITI2V", + "VideoLaVITI2VLong", + "VideoLaVITLoader", + "VideoLaVITT2V", + "VideoLaVITT2VLong", + "VideoLaVITUnderstandingImage", + "VideoLaVITUnderstandingLoader", + "VideoLaVITUnderstandingVideo", + "VideoLaVITVideoDetokenizerLoader", + "VideoLaVITVideoReconstruction" + ], + { + "title_aux": "ComfyUI-LaVIT" + } + ], + "https://github.com/chaojie/ComfyUI-LightGlue": [ + [ + "LightGlue Loader", + "LightGlue Simple", + "LightGlue Simple Multi" + ], + { + "title_aux": "ComfyUI-LightGlue" + } + ], + "https://github.com/chaojie/ComfyUI-Moore-AnimateAnyone": [ + [ + "Moore-AnimateAnyone Denoising Unet", + "Moore-AnimateAnyone Image Encoder", + "Moore-AnimateAnyone Pipeline Loader", + "Moore-AnimateAnyone Pose Guider", + "Moore-AnimateAnyone Reference Unet", + "Moore-AnimateAnyone Simple", + "Moore-AnimateAnyone VAE" + ], + { + "title_aux": "ComfyUI-Moore-AnimateAnyone" + } + ], + "https://github.com/chaojie/ComfyUI-Motion-Vector-Extractor": [ + [ + "Motion Vector Extractor", + "VideoCombineThenPath" + ], + { + "title_aux": "ComfyUI-Motion-Vector-Extractor" + } + ], + "https://github.com/chaojie/ComfyUI-MotionCtrl": [ + [ + "Load Motion Camera Preset", + "Load Motion Traj Preset", + "Load Motionctrl Checkpoint", + "Motionctrl Cond", + "Motionctrl Sample", + "Motionctrl Sample Simple", + "Select Image Indices" + ], + { + "title_aux": "ComfyUI-MotionCtrl" + } + ], + "https://github.com/chaojie/ComfyUI-MotionCtrl-SVD": [ + [ + "Load Motionctrl-SVD Camera Preset", + "Load Motionctrl-SVD Checkpoint", + "Motionctrl-SVD Sample Simple" + ], + { + "title_aux": "ComfyUI-MotionCtrl-SVD" + } + ], + "https://github.com/chaojie/ComfyUI-MuseTalk": [ + [ + "MuseTalkCupAudio", + "MuseTalkRun", + "VHS_FILENAMES_STRING_MuseTalk" + ], + { + "title_aux": "ComfyUI-MuseTalk" + } + ], + "https://github.com/chaojie/ComfyUI-MuseV": [ + [ + "MuseVRun", + "MuseVRunVid2Vid", + "VHS_FILENAMES_STRING_MuseV" + ], + { + "author": "infguo", + "title_aux": "ComfyUI-MuseV" + } + ], + "https://github.com/chaojie/ComfyUI-Open-Sora": [ + [ + "OpenSoraLoader", + "OpenSoraRun", + "OpenSoraSampler" + ], + { + "title_aux": "ComfyUI-Open-Sora" + } + ], + "https://github.com/chaojie/ComfyUI-Open-Sora-Plan": [ + [ + "OpenSoraPlanDecode", + "OpenSoraPlanLoader", + "OpenSoraPlanRun", + "OpenSoraPlanSample" + ], + { + "title_aux": "ComfyUI-Open-Sora-Plan" + } + ], + "https://github.com/chaojie/ComfyUI-Panda3d": [ + [ + "Panda3dAmbientLight", + "Panda3dAttachNewNode", + "Panda3dBase", + "Panda3dDirectionalLight", + "Panda3dLoadDepthModel", + "Panda3dLoadModel", + "Panda3dLoadTexture", + "Panda3dModelMerge", + "Panda3dTest", + "Panda3dTextureMerge" + ], + { + "title_aux": "ComfyUI-Panda3d" + } + ], + "https://github.com/chaojie/ComfyUI-Pymunk": [ + [ + "PygameRun", + "PygameSurface", + "PymunkDynamicBox", + "PymunkDynamicCircle", + "PymunkRun", + "PymunkShapeMerge", + "PymunkSpace", + "PymunkStaticLine" + ], + { + "title_aux": "ComfyUI-Pymunk" + } + ], + "https://github.com/chaojie/ComfyUI-RAFT": [ + [ + "Load MotionBrush", + "RAFT Run", + "Save MotionBrush", + "VizMotionBrush" + ], + { + "title_aux": "ComfyUI-RAFT" + } + ], + "https://github.com/chaojie/ComfyUI-SimDA": [ + [ + "SimDALoader", + "SimDARun", + "SimDATrain", + "VHS_FILENAMES_STRING_SimDA" + ], + { + "title_aux": "ComfyUI-SimDA" + } + ], + "https://github.com/chaojie/ComfyUI-Trajectory": [ + [ + "Trajectory_Canvas_Tab" + ], + { + "author": "Lerc", + "description": "This extension provides a full page image editor with mask support. There are two nodes, one to receive images from the editor and one to send images to the editor.", + "nickname": "Canvas Tab", + "title": "Canvas Tab", + "title_aux": "ComfyUI-Trajectory" + } + ], + "https://github.com/chaojie/ComfyUI-Video-Editing-X-Attention": [ + [ + "StringList", + "VEXAGuidance", + "VEXALoader", + "VEXARun" + ], + { + "title_aux": "ComfyUI-Video-Editing-X-Attention" + } + ], + "https://github.com/chaojie/ComfyUI-dust3r": [ + [ + "CameraPoseVideo", + "Dust3rLoader", + "Dust3rRun" + ], + { + "title_aux": "ComfyUI-dust3r" + } + ], + "https://github.com/chaojie/ComfyUI_StreamingT2V": [ + [ + "LoadText_StreamingT2V", + "PromptTravelIndex", + "SaveText_StreamingT2V", + "StreamingT2VLoaderAnimateDiff", + "StreamingT2VLoaderAnimateDiffModel", + "StreamingT2VLoaderEnhanceModel", + "StreamingT2VLoaderModelscopeModel", + "StreamingT2VLoaderModelscopeT2V", + "StreamingT2VLoaderSVD", + "StreamingT2VLoaderSVDModel", + "StreamingT2VLoaderStreamModel", + "StreamingT2VLoaderVidXTendModel", + "StreamingT2VRunEnhanceStep", + "StreamingT2VRunI2V", + "StreamingT2VRunLongStep", + "StreamingT2VRunLongStepVidXTendPipeline", + "StreamingT2VRunLongStepVidXTendPipelineCustomRef", + "StreamingT2VRunLongStepVidXTendPipelineCustomRefOutExtendOnly", + "StreamingT2VRunLongStepVidXTendPipelinePromptTravel", + "StreamingT2VRunShortStepAnimateDiff", + "StreamingT2VRunShortStepModelscopeT2V", + "StreamingT2VRunShortStepSVD", + "StreamingT2VRunT2V", + "VHS_FILENAMES_STRING_StreamingT2V" + ], + { + "title_aux": "ComfyUI_StreamingT2V" + } + ], + "https://github.com/chaosaiart/Chaosaiart-Nodes": [ + [ + "chaosaiart_Any_Switch", + "chaosaiart_Any_Switch_Big_Number", + "chaosaiart_Any_Switch_small", + "chaosaiart_CheckpointLoader", + "chaosaiart_CheckpointPrompt", + "chaosaiart_CheckpointPrompt2", + "chaosaiart_CheckpointPrompt_Frame", + "chaosaiart_CheckpointPrompt_FrameMixer", + "chaosaiart_ControlNetApply", + "chaosaiart_ControlNetApply2", + "chaosaiart_ControlNetApply3", + "chaosaiart_Denoising_Switch", + "chaosaiart_EmptyLatentImage", + "chaosaiart_FramePromptCLIPEncode", + "chaosaiart_Frame_Switch", + "chaosaiart_KSampler1", + "chaosaiart_KSampler2", + "chaosaiart_KSampler3", + "chaosaiart_KSampler4", + "chaosaiart_KSampler5", + "chaosaiart_KSampler7", + "chaosaiart_KSampler_a1", + "chaosaiart_KSampler_a1a", + "chaosaiart_KSampler_a2", + "chaosaiart_KSampler_expert_0", + "chaosaiart_KSampler_expert_1", + "chaosaiart_Ksampler_attribut", + "chaosaiart_Load_Image_Batch", + "chaosaiart_Load_Image_Batch_2img", + "chaosaiart_MainPromptCLIPEncode", + "chaosaiart_Number", + "chaosaiart_Number2", + "chaosaiart_Number_Counter", + "chaosaiart_Number_Switch", + "chaosaiart_Prompt", + "chaosaiart_Prompt_Frame", + "chaosaiart_Prompt_mixer_byFrame", + "chaosaiart_SaveImage", + "chaosaiart_Show_Info", + "chaosaiart_Simple_Prompt", + "chaosaiart_Style_Node", + "chaosaiart_TextCLIPEncode", + "chaosaiart_TextCLIPEncode_lora", + "chaosaiart_adjust_color", + "chaosaiart_any_array2input_1Input", + "chaosaiart_any_array2input_all_big", + "chaosaiart_any_array2input_all_small", + "chaosaiart_any_input2array_big", + "chaosaiart_any_input2array_small", + "chaosaiart_controlnet_weidgth", + "chaosaiart_convert", + "chaosaiart_convert_Prompt", + "chaosaiart_forPreview", + "chaosaiart_image_loop", + "chaosaiart_img2gif", + "chaosaiart_img2video", + "chaosaiart_lora", + "chaosaiart_lora_advanced", + "chaosaiart_merge_Folders", + "chaosaiart_oneNode", + "chaosaiart_reloadAny_Load", + "chaosaiart_reloadAny_Save", + "chaosaiart_reloadIMG_Load", + "chaosaiart_reloadIMG_Save", + "chaosaiart_reloadLatent_Load", + "chaosaiart_reloadLatent_Save", + "chaosaiart_restarter", + "chaosaiart_restarter_advanced", + "chaosaiart_video2img1", + "chaosaiart_zoom_frame" + ], + { + "title_aux": "Chaosaiart-Nodes" + } + ], + "https://github.com/chesnokovivan/ComfyUI-Novakid": [ + [ + "Novakid Styler" + ], + { + "title_aux": "ComfyUI-Novakid" + } + ], + "https://github.com/chflame163/ComfyUI_FaceSimilarity": [ + [ + "Face Similarity" + ], + { + "title_aux": "ComfyUI Face Similarity" + } + ], + "https://github.com/chflame163/ComfyUI_LayerStyle": [ + [ + "LayerColor: AutoAdjust", + "LayerColor: AutoBrightness", + "LayerColor: Brightness & Contrast", + "LayerColor: Color of Shadow & Highlight", + "LayerColor: ColorAdapter", + "LayerColor: ColorBalance", + "LayerColor: ColorTemperature", + "LayerColor: Exposure", + "LayerColor: Gamma", + "LayerColor: HSV", + "LayerColor: LAB", + "LayerColor: LUT Apply", + "LayerColor: Levels", + "LayerColor: RGB", + "LayerColor: YUV", + "LayerFilter: AddGrain", + "LayerFilter: ChannelShake", + "LayerFilter: ColorMap", + "LayerFilter: Film", + "LayerFilter: FilmV2", + "LayerFilter: GaussianBlur", + "LayerFilter: HDREffects", + "LayerFilter: LightLeak", + "LayerFilter: MotionBlur", + "LayerFilter: Sharp & Soft", + "LayerFilter: SkinBeauty", + "LayerFilter: SoftLight", + "LayerFilter: WaterColor", + "LayerMask: BiRefNetUltra", + "LayerMask: BlendIf Mask", + "LayerMask: CreateGradientMask", + "LayerMask: ImageToMask", + "LayerMask: MaskBoxDetect", + "LayerMask: MaskByColor", + "LayerMask: MaskByDifferent", + "LayerMask: MaskEdgeShrink", + "LayerMask: MaskEdgeUltraDetail", + "LayerMask: MaskEdgeUltraDetail V2", + "LayerMask: MaskGradient", + "LayerMask: MaskGrain", + "LayerMask: MaskGrow", + "LayerMask: MaskInvert", + "LayerMask: MaskMotionBlur", + "LayerMask: MaskPreview", + "LayerMask: MaskStroke", + "LayerMask: MediapipeFacialSegment", + "LayerMask: PersonMaskUltra", + "LayerMask: PersonMaskUltra V2", + "LayerMask: PixelSpread", + "LayerMask: RemBgUltra", + "LayerMask: RmBgUltra V2", + "LayerMask: SegformerB2ClothesUltra", + "LayerMask: SegmentAnythingUltra", + "LayerMask: SegmentAnythingUltra V2", + "LayerMask: Shadow & Highlight Mask", + "LayerMask: YoloV8Detect", + "LayerStyle: ColorOverlay", + "LayerStyle: ColorOverlay V2", + "LayerStyle: DropShadow", + "LayerStyle: DropShadow V2", + "LayerStyle: GradientOverlay", + "LayerStyle: GradientOverlay V2", + "LayerStyle: InnerGlow", + "LayerStyle: InnerGlow V2", + "LayerStyle: InnerShadow", + "LayerStyle: InnerShadow V2", + "LayerStyle: OuterGlow", + "LayerStyle: OuterGlow V2", + "LayerStyle: Stroke", + "LayerStyle: Stroke V2", + "LayerUtility: AddBlindWaterMark", + "LayerUtility: BatchSelector", + "LayerUtility: Boolean", + "LayerUtility: BooleanOperator", + "LayerUtility: BooleanOperatorV2", + "LayerUtility: CheckMask", + "LayerUtility: ColorImage", + "LayerUtility: ColorImage V2", + "LayerUtility: ColorPicker", + "LayerUtility: CreateQRCode", + "LayerUtility: CropBoxResolve", + "LayerUtility: CropByMask", + "LayerUtility: CropByMask V2", + "LayerUtility: DecodeQRCode", + "LayerUtility: ExtendCanvas", + "LayerUtility: ExtendCanvasV2", + "LayerUtility: Float", + "LayerUtility: GetColorTone", + "LayerUtility: GetColorToneV2", + "LayerUtility: GetImageSize", + "LayerUtility: GradientImage", + "LayerUtility: GradientImage V2", + "LayerUtility: HLFrequencyDetailRestore", + "LayerUtility: HSV Value", + "LayerUtility: If", + "LayerUtility: ImageAutoCrop", + "LayerUtility: ImageAutoCrop V2", + "LayerUtility: ImageBlend", + "LayerUtility: ImageBlend V2", + "LayerUtility: ImageBlendAdvance", + "LayerUtility: ImageBlendAdvance V2", + "LayerUtility: ImageChannelMerge", + "LayerUtility: ImageChannelSplit", + "LayerUtility: ImageCombineAlpha", + "LayerUtility: ImageHub", + "LayerUtility: ImageMaskScaleAs", + "LayerUtility: ImageOpacity", + "LayerUtility: ImageRemoveAlpha", + "LayerUtility: ImageRewardFilter", + "LayerUtility: ImageScaleByAspectRatio", + "LayerUtility: ImageScaleByAspectRatio V2", + "LayerUtility: ImageScaleRestore", + "LayerUtility: ImageScaleRestore V2", + "LayerUtility: ImageShift", + "LayerUtility: Integer", + "LayerUtility: LaMa", + "LayerUtility: LayerImageTransform", + "LayerUtility: LayerMaskTransform", + "LayerUtility: LoadPSD", + "LayerUtility: NumberCalculator", + "LayerUtility: NumberCalculatorV2", + "LayerUtility: PrintInfo", + "LayerUtility: PromptEmbellish", + "LayerUtility: PromptTagger", + "LayerUtility: PurgeVRAM", + "LayerUtility: QWenImage2Prompt", + "LayerUtility: QueueStop", + "LayerUtility: RGB Value", + "LayerUtility: RestoreCropBox", + "LayerUtility: SD3NegativeConditioning", + "LayerUtility: SaveImagePlus", + "LayerUtility: Seed", + "LayerUtility: ShowBlindWaterMark", + "LayerUtility: SimpleTextImage", + "LayerUtility: String", + "LayerUtility: StringCondition", + "LayerUtility: SwitchCase", + "LayerUtility: TextBox", + "LayerUtility: TextImage", + "LayerUtility: TextJoin", + "LayerUtility: XY to Percent" + ], + { + "author": "chflame", + "description": "A set of nodes for ComfyUI that can composite layer and mask to achieve Photoshop like functionality.", + "nickname": "LayerStyle", + "title": "LayerStyle", + "title_aux": "ComfyUI Layer Style" + } + ], + "https://github.com/chflame163/ComfyUI_MSSpeech_TTS": [ + [ + "Input Trigger", + "MicrosoftSpeech_TTS", + "Play Sound", + "Play Sound (loop)" + ], + { + "title_aux": "ComfyUI_MSSpeech_TTS" + } + ], + "https://github.com/chflame163/ComfyUI_WordCloud": [ + [ + "ComfyWordCloud", + "LoadTextFile", + "RGB_Picker" + ], + { + "title_aux": "ComfyUI_WordCloud" + } + ], + "https://github.com/chibiace/ComfyUI-Chibi-Nodes": [ + [ + "ConditionText", + "ConditionTextMulti", + "ImageAddText", + "ImageSimpleResize", + "ImageSizeInfo", + "ImageTool", + "Int2String", + "LoadEmbedding", + "LoadImageExtended", + "Loader", + "Prompts", + "RandomResolutionLatent", + "SaveImages", + "SeedGenerator", + "SimpleSampler", + "TextSplit", + "Textbox", + "Wildcards" + ], + { + "title_aux": "ComfyUI-Chibi-Nodes" + } + ], + "https://github.com/choey/Comfy-Topaz": [ + [ + "TopazPhotoAI", + "TopazSharpenSettings", + "TopazUpscaleSettings" + ], + { + "title_aux": "Comfy-Topaz" + } + ], + "https://github.com/chris-the-wiz/EmbeddingsCurveEditor_ComfyUI": [ + [ + "Embeddings Curve Editor" + ], + { + "title_aux": "EmbeddingsCurveEditor_ComfyUI" + } + ], + "https://github.com/chrisfreilich/virtuoso-nodes": [ + [ + "BlackAndWhite", + "BlendIf", + "BlendModes", + "ColorBalance", + "ColorBalanceAdvanced", + "GaussianBlur", + "GaussianBlurDepth", + "HueSat", + "HueSatAdvanced", + "LensBlur", + "LensBlurDepth", + "Levels", + "MergeRGB", + "MotionBlur", + "MotionBlurDepth", + "SelectiveColor", + "SolidColor", + "SolidColorHSV", + "SolidColorRGB", + "SplitRGB" + ], + { + "author": "Chris Freilich", + "description": "This extension provides a \"Blend If (BlendIf)\" node.", + "nickname": "Virtuoso Pack - Blend If", + "title": "Virtuoso Pack - Blend If", + "title_aux": "Virtuoso Nodes for ComfyUI" + } + ], + "https://github.com/chrisgoringe/cg-image-picker": [ + [ + "Preview Chooser", + "Preview Chooser Fabric" + ], + { + "author": "chrisgoringe", + "description": "Custom nodes that preview images and pause the workflow to allow the user to select one or more to progress", + "nickname": "Image Chooser", + "title": "Image Chooser", + "title_aux": "Image chooser" + } + ], + "https://github.com/chrisgoringe/cg-noise": [ + [ + "Hijack", + "KSampler Advanced with Variations", + "KSampler with Variations", + "UnHijack" + ], + { + "title_aux": "Variation seeds" + } + ], + "https://github.com/chrisgoringe/cg-use-everywhere": [ + [ + "Seed Everywhere" + ], + { + "nodename_pattern": "(^(Prompts|Anything) Everywhere|Simple String)", + "title_aux": "Use Everywhere (UE Nodes)" + } + ], + "https://github.com/christian-byrne/audio-separation-nodes-comfyui": [ + [ + "AudioCombine", + "AudioCrop", + "AudioSeparation", + "AudioTempoMatch", + "AudioVideoCombine" + ], + { + "title_aux": "audio-separation-nodes-comfyui" + } + ], + "https://github.com/christian-byrne/img2colors-comfyui-node": [ + [ + "bmy_Img2ColorNode" + ], + { + "author": "christian-byrne", + "description": "", + "nickname": "img2color", + "title": "Img2Color Node - Detect and describe color palettes in images", + "title_aux": "img2colors-comfyui-node" + } + ], + "https://github.com/christian-byrne/size-match-compositing-nodes": [ + [ + "Composite Alpha Layer", + "Size Match Images/Masks" + ], + { + "title_aux": "Node - Size Matcher" + } + ], + "https://github.com/city96/ComfyUI_ColorMod": [ + [ + "CV2Tonemap", + "CV2TonemapDrago", + "CV2TonemapDurand", + "CV2TonemapMantiuk", + "CV2TonemapReinhard", + "ColorModCompress", + "ColorModEdges", + "ColorModMove", + "ColorModPivot", + "HDRCreate", + "HDRExposureFusion", + "LoadImageHDR", + "LoadImageHighPrec", + "PreviewImageHighPrec", + "SaveImageHDR", + "SaveImageHighPrec" + ], + { + "title_aux": "ComfyUI_ColorMod" + } + ], + "https://github.com/city96/ComfyUI_DiT": [ + [ + "DiTCheckpointLoader", + "DiTCheckpointLoaderSimple", + "DiTLabelCombine", + "DiTLabelSelect", + "DiTSampler" + ], + { + "title_aux": "ComfyUI_DiT [WIP]" + } + ], + "https://github.com/city96/ComfyUI_ExtraModels": [ + [ + "DiTCondLabelEmpty", + "DiTCondLabelSelect", + "DitCheckpointLoader", + "ExtraVAELoader", + "HYDiTCheckpointLoader", + "HYDiTSrcSizeCond", + "HYDiTTextEncode", + "HYDiTTextEncodeSimple", + "HYDiTTextEncoderLoader", + "MiaoBiCLIPLoader", + "MiaoBiDiffusersLoader", + "PixArtCheckpointLoader", + "PixArtCheckpointLoaderSimple", + "PixArtControlNetCond", + "PixArtLoraLoader", + "PixArtResolutionCond", + "PixArtResolutionSelect", + "PixArtT5FromSD3CLIP", + "PixArtT5TextEncode", + "T5TextEncode", + "T5v11Loader" + ], + { + "title_aux": "Extra Models for ComfyUI" + } + ], + "https://github.com/city96/ComfyUI_NetDist": [ + [ + "CombineImageBatch", + "FetchRemote", + "LoadCurrentWorkflowJSON", + "LoadDiskWorkflowJSON", + "LoadImageUrl", + "LoadLatentNumpy", + "LoadLatentUrl", + "RemoteChainEnd", + "RemoteChainStart", + "RemoteQueueSimple", + "RemoteQueueWorker", + "SaveDiskWorkflowJSON", + "SaveImageUrl", + "SaveLatentNumpy" + ], + { + "title_aux": "ComfyUI_NetDist" + } + ], + "https://github.com/city96/SD-Advanced-Noise": [ + [ + "LatentGaussianNoise", + "MathEncode" + ], + { + "title_aux": "SD-Advanced-Noise" + } + ], + "https://github.com/city96/SD-Latent-Interposer": [ + [ + "LatentInterposer" + ], + { + "title_aux": "Latent-Interposer" + } + ], + "https://github.com/city96/SD-Latent-Upscaler": [ + [ + "LatentUpscaler" + ], + { + "title_aux": "SD-Latent-Upscaler" + } + ], + "https://github.com/civitai/comfy-nodes": [ + [ + "CivitAI_Checkpoint_Loader", + "CivitAI_Lora_Loader" + ], + { + "title_aux": "comfy-nodes" + } + ], + "https://github.com/claussteinmassl/ComfyUI-CS-CustomNodes": [ + [ + "CS Transform" + ], + { + "title_aux": "CS Transform Node for ComfyUI" + } + ], + "https://github.com/comfyanonymous/ComfyUI": [ + [ + "AddNoise", + "AlignYourStepsScheduler", + "BasicGuider", + "BasicScheduler", + "CFGGuider", + "CLIPAttentionMultiply", + "CLIPLoader", + "CLIPMergeAdd", + "CLIPMergeSimple", + "CLIPMergeSubtract", + "CLIPSave", + "CLIPSetLastLayer", + "CLIPTextEncode", + "CLIPTextEncodeControlnet", + "CLIPTextEncodeSD3", + "CLIPTextEncodeSDXL", + "CLIPTextEncodeSDXLRefiner", + "CLIPVisionEncode", + "CLIPVisionLoader", + "Canny", + "CheckpointLoader", + "CheckpointLoaderSimple", + "CheckpointSave", + "ConditioningAverage", + "ConditioningCombine", + "ConditioningConcat", + "ConditioningSetArea", + "ConditioningSetAreaPercentage", + "ConditioningSetAreaStrength", + "ConditioningSetMask", + "ConditioningSetTimestepRange", + "ConditioningZeroOut", + "ControlNetApply", + "ControlNetApplyAdvanced", + "ControlNetApplySD3", + "ControlNetLoader", + "CropMask", + "DiffControlNetLoader", + "DifferentialDiffusion", + "DiffusersLoader", + "DisableNoise", + "DualCFGGuider", + "DualCLIPLoader", + "EmptyImage", + "EmptyLatentAudio", + "EmptyLatentImage", + "EmptySD3LatentImage", + "ExponentialScheduler", + "FeatherMask", + "FlipSigmas", + "FreeU", + "FreeU_V2", + "GITSScheduler", + "GLIGENLoader", + "GLIGENTextBoxApply", + "GrowMask", + "HyperTile", + "HypernetworkLoader", + "ImageBatch", + "ImageBlend", + "ImageBlur", + "ImageColorToMask", + "ImageCompositeMasked", + "ImageCrop", + "ImageFromBatch", + "ImageInvert", + "ImageOnlyCheckpointLoader", + "ImageOnlyCheckpointSave", + "ImagePadForOutpaint", + "ImageQuantize", + "ImageScale", + "ImageScaleBy", + "ImageScaleToTotalPixels", + "ImageSharpen", + "ImageToMask", + "ImageUpscaleWithModel", + "InpaintModelConditioning", + "InstructPixToPixConditioning", + "InvertMask", + "JoinImageWithAlpha", + "KSampler", + "KSamplerAdvanced", + "KSamplerSelect", + "KarrasScheduler", + "LatentAdd", + "LatentBatch", + "LatentBatchSeedBehavior", + "LatentBlend", + "LatentComposite", + "LatentCompositeMasked", + "LatentCrop", + "LatentFlip", + "LatentFromBatch", + "LatentInterpolate", + "LatentMultiply", + "LatentRotate", + "LatentSubtract", + "LatentUpscale", + "LatentUpscaleBy", + "LoadAudio", + "LoadImage", + "LoadImageMask", + "LoadLatent", + "LoraLoader", + "LoraLoaderModelOnly", + "MaskComposite", + "MaskToImage", + "ModelMergeAdd", + "ModelMergeBlocks", + "ModelMergeSD1", + "ModelMergeSD2", + "ModelMergeSD3_2B", + "ModelMergeSDXL", + "ModelMergeSimple", + "ModelMergeSubtract", + "ModelSamplingContinuousEDM", + "ModelSamplingContinuousV", + "ModelSamplingDiscrete", + "ModelSamplingSD3", + "ModelSamplingStableCascade", + "Morphology", + "PatchModelAddDownscale", + "PerpNeg", + "PerpNegGuider", + "PerturbedAttentionGuidance", + "PhotoMakerEncode", + "PhotoMakerLoader", + "PolyexponentialScheduler", + "PorterDuffImageComposite", + "PreviewAudio", + "PreviewImage", + "RandomNoise", + "RebatchImages", + "RebatchLatents", + "RepeatImageBatch", + "RepeatLatentBatch", + "RescaleCFG", + "SDTurboScheduler", + "SD_4XUpscale_Conditioning", + "SV3D_Conditioning", + "SVD_img2vid_Conditioning", + "SamplerCustom", + "SamplerCustomAdvanced", + "SamplerDPMAdaptative", + "SamplerDPMPP_2M_SDE", + "SamplerDPMPP_3M_SDE", + "SamplerDPMPP_SDE", + "SamplerEulerAncestral", + "SamplerEulerAncestralCFGPP", + "SamplerEulerCFGpp", + "SamplerLCMUpscale", + "SamplerLMS", + "SaveAnimatedPNG", + "SaveAnimatedWEBP", + "SaveAudio", + "SaveImage", + "SaveImageWebsocket", + "SaveLatent", + "SelfAttentionGuidance", + "SetLatentNoiseMask", + "SolidMask", + "SplitImageWithAlpha", + "SplitSigmas", + "SplitSigmasDenoise", + "StableCascade_EmptyLatentImage", + "StableCascade_StageB_Conditioning", + "StableCascade_StageC_VAEEncode", + "StableCascade_SuperResolutionControlnet", + "StableZero123_Conditioning", + "StableZero123_Conditioning_Batched", + "StyleModelApply", + "StyleModelLoader", + "ThresholdMask", + "TomePatchModel", + "TripleCLIPLoader", + "UNETLoader", + "UNetCrossAttentionMultiply", + "UNetSelfAttentionMultiply", + "UNetTemporalAttentionMultiply", + "UpscaleModelLoader", + "VAEDecode", + "VAEDecodeAudio", + "VAEDecodeTiled", + "VAEEncode", + "VAEEncodeAudio", + "VAEEncodeForInpaint", + "VAEEncodeTiled", + "VAELoader", + "VAESave", + "VPScheduler", + "VideoLinearCFGGuidance", + "VideoTriangleCFGGuidance", + "WebcamCapture", + "unCLIPCheckpointLoader", + "unCLIPConditioning" + ], + { + "title_aux": "ComfyUI" + } + ], + "https://github.com/comfyanonymous/ComfyUI_TensorRT": [ + [ + "DYNAMIC_TRT_MODEL_CONVERSION", + "STATIC_TRT_MODEL_CONVERSION", + "TensorRTLoader" + ], + { + "title_aux": "TensorRT Node for ComfyUI" + } + ], + "https://github.com/comfyanonymous/ComfyUI_experiments": [ + [ + "ModelMergeBlockNumber", + "ModelMergeSDXL", + "ModelMergeSDXLDetailedTransformers", + "ModelMergeSDXLTransformers", + "ModelSamplerTonemapNoiseTest", + "ReferenceOnlySimple", + "RescaleClassifierFreeGuidanceTest", + "TonemapNoiseWithRescaleCFG" + ], + { + "title_aux": "ComfyUI_experiments" + } + ], + "https://github.com/concarne000/ConCarneNode": [ + [ + "BingImageGrabber", + "Hermes", + "Zephyr" + ], + { + "title_aux": "ConCarneNode" + } + ], + "https://github.com/conquestace/ComfyUI-ImageUploader": [ + [ + "ImageUploader" + ], + { + "author": "ConquestAce", + "description": "Upload to temporary websites with API.", + "nickname": "Image Uploader", + "title": "Image Uploader", + "title_aux": "Image Uploader" + } + ], + "https://github.com/coreyryanhanson/ComfyQR": [ + [ + "comfy-qr-by-image-size", + "comfy-qr-by-module-size", + "comfy-qr-by-module-split", + "comfy-qr-mask_errors" + ], + { + "title_aux": "ComfyQR" + } + ], + "https://github.com/coreyryanhanson/ComfyQR-scanning-nodes": [ + [ + "comfy-qr-read", + "comfy-qr-validate" + ], + { + "title_aux": "ComfyQR-scanning-nodes" + } + ], + "https://github.com/cozymantis/cozy-utils-comfyui-nodes": [ + [ + "Cozy Sampler Options" + ], + { + "title_aux": "Cozy Utils" + } + ], + "https://github.com/cozymantis/human-parser-comfyui-node": [ + [ + "Cozy Human Parser ATR", + "Cozy Human Parser LIP", + "Cozy Human Parser Pascal" + ], + { + "title_aux": "Cozy Human Parser" + } + ], + "https://github.com/cozymantis/pose-generator-comfyui-node": [ + [ + "Cozy Pose Body Reference", + "Cozy Pose Face Reference" + ], + { + "title_aux": "Cozy Reference Pose Generator" + } + ], + "https://github.com/crystian/ComfyUI-Crystools": [ + [], + { + "author": "Crystian", + "description": "Plugins for multiples uses, mainly for debugging, you need them! IG: https://www.instagram.com/crystian.ia", + "nickname": "Crystools", + "nodename_pattern": " \\[Crystools\\]$", + "title": "Crystools", + "title_aux": "Crystools" + } + ], + "https://github.com/cubiq/ComfyUI_FaceAnalysis": [ + [ + "FaceAlign", + "FaceAnalysisModels", + "FaceBoundingBox", + "FaceEmbedDistance", + "FaceSegmentation", + "FaceWarp" + ], + { + "title_aux": "Face Analysis for ComfyUI" + } + ], + "https://github.com/cubiq/ComfyUI_IPAdapter_plus": [ + [ + "IPAAdapterFaceIDBatch", + "IPAdapter", + "IPAdapterAdvanced", + "IPAdapterBatch", + "IPAdapterCombineEmbeds", + "IPAdapterCombineParams", + "IPAdapterCombineWeights", + "IPAdapterEmbeds", + "IPAdapterEmbedsBatch", + "IPAdapterEncoder", + "IPAdapterFaceID", + "IPAdapterFromParams", + "IPAdapterInsightFaceLoader", + "IPAdapterLoadEmbeds", + "IPAdapterMS", + "IPAdapterModelLoader", + "IPAdapterNoise", + "IPAdapterPreciseStyleTransfer", + "IPAdapterPreciseStyleTransferBatch", + "IPAdapterPromptScheduleFromWeightsStrategy", + "IPAdapterRegionalConditioning", + "IPAdapterSaveEmbeds", + "IPAdapterStyleComposition", + "IPAdapterStyleCompositionBatch", + "IPAdapterTiled", + "IPAdapterTiledBatch", + "IPAdapterUnifiedLoader", + "IPAdapterUnifiedLoaderCommunity", + "IPAdapterUnifiedLoaderFaceID", + "IPAdapterWeights", + "IPAdapterWeightsFromStrategy", + "PrepImageForClipVision" + ], + { + "title_aux": "ComfyUI_IPAdapter_plus" + } + ], + "https://github.com/cubiq/ComfyUI_InstantID": [ + [ + "ApplyInstantID", + "ApplyInstantIDAdvanced", + "ApplyInstantIDControlNet", + "FaceKeypointsPreprocessor", + "InstantIDAttentionPatch", + "InstantIDFaceAnalysis", + "InstantIDModelLoader" + ], + { + "title_aux": "ComfyUI InstantID (Native Support)" + } + ], + "https://github.com/cubiq/ComfyUI_SimpleMath": [ + [ + "SimpleMath", + "SimpleMathDebug" + ], + { + "title_aux": "Simple Math" + } + ], + "https://github.com/cubiq/ComfyUI_essentials": [ + [ + "ApplyCLIPSeg+", + "BatchCount+", + "CLIPTextEncodeSDXL+", + "ConditioningCombineMultiple+", + "ConsoleDebug+", + "DebugTensorShape+", + "DrawText+", + "ExtractKeyframes+", + "GetImageSize+", + "ImageApplyLUT+", + "ImageBatchMultiple+", + "ImageCASharpening+", + "ImageColorMatch+", + "ImageCompositeFromMaskBatch+", + "ImageCrop+", + "ImageDesaturate+", + "ImageEnhanceDifference+", + "ImageExpandBatch+", + "ImageFlip+", + "ImageFromBatch+", + "ImageHistogramMatch+", + "ImageListToBatch+", + "ImagePosterize+", + "ImagePreviewFromLatent+", + "ImageRandomTransform+", + "ImageRemoveAlpha+", + "ImageRemoveBackground+", + "ImageResize+", + "ImageSeamCarving+", + "ImageTile+", + "ImageToDevice+", + "ImageUntile+", + "KSamplerVariationsStochastic+", + "KSamplerVariationsWithNoise+", + "LoadCLIPSegModels+", + "MaskBatch+", + "MaskBlur+", + "MaskBoundingBox+", + "MaskExpandBatch+", + "MaskFix+", + "MaskFlip+", + "MaskFromBatch+", + "MaskFromColor+", + "MaskFromList+", + "MaskFromRGBCMYBW+", + "MaskFromSegmentation+", + "MaskPreview+", + "MaskSmooth+", + "ModelCompile+", + "NoiseFromImage+", + "PixelOEPixelize+", + "RemBGSession+", + "RemoveLatentMask+", + "SD3NegativeConditioning+", + "SDXLEmptyLatentSizePicker+", + "SimpleMath+", + "TransitionMask+" + ], + { + "title_aux": "ComfyUI Essentials" + } + ], + "https://github.com/cubiq/PuLID_ComfyUI": [ + [ + "ApplyPulid", + "ApplyPulidAdvanced", + "PulidEvaClipLoader", + "PulidInsightFaceLoader", + "PulidModelLoader" + ], + { + "title_aux": "PuLID_ComfyUI" + } + ], + "https://github.com/cuongloveit/comfy_http_request": [ + [ + "Send Http Request", + "Send Http request" + ], + { + "title_aux": "comfy_http_request" + } + ], + "https://github.com/curiousjp/ComfyUI-MaskBatchPermutations": [ + [ + "CombinatorialDetailer", + "FlattenAgainstOriginal", + "PermuteMaskBatch" + ], + { + "title_aux": "ComfyUI-MaskBatchPermutations" + } + ], + "https://github.com/czcz1024/Comfyui-FaceCompare": [ + [ + "FaceCompare" + ], + { + "author": "czcz1024", + "description": "Face Compare", + "nickname": "Face Compare", + "title": "Face Compare", + "title_aux": "Face Compare" + } + ], + "https://github.com/da2el-ai/ComfyUI-d2-size-selector": [ + [ + "D2_SizeSelector" + ], + { + "author": "da2el", + "description": "Easy select image size", + "title": "D2 Size Selector", + "title_aux": "D2 Size Selector" + } + ], + "https://github.com/da2el-ai/ComfyUI-d2-steps": [ + [ + "D2 Refiner Steps", + "D2 Refiner Steps A1111", + "D2 Refiner Steps Tester" + ], + { + "author": "da2el", + "description": "Calculate the steps for the refiner", + "title": "D2 Steps", + "title_aux": "D2 Steps" + } + ], + "https://github.com/dagthomas/comfyui_dagthomas": [ + [ + "PGSD3LatentGenerator", + "PromptGenerator" + ], + { + "title_aux": "SDXL Auto Prompter" + } + ], + "https://github.com/daniabib/ComfyUI_ProPainter_Nodes": [ + [ + "ProPainterInpaint", + "ProPainterOutpaint" + ], + { + "title_aux": "ComfyUI ProPainter Nodes" + } + ], + "https://github.com/daniel-lewis-ab/ComfyUI-Llama": [ + [ + "Call LLM Advanced", + "Call LLM Basic", + "LLM_Create_Completion Advanced", + "LLM_Detokenize", + "LLM_Embed", + "LLM_Eval", + "LLM_Load_State", + "LLM_Reset", + "LLM_Sample", + "LLM_Save_State", + "LLM_Token_BOS", + "LLM_Token_EOS", + "LLM_Tokenize", + "Load LLM Model Advanced", + "Load LLM Model Basic" + ], + { + "title_aux": "ComfyUI-Llama" + } + ], + "https://github.com/daniel-lewis-ab/ComfyUI-TTS": [ + [ + "Load_Piper_Model", + "Piper_Speak_Text" + ], + { + "title_aux": "ComfyUI-TTS" + } + ], + "https://github.com/darkpixel/darkprompts": [ + [ + "DarkCheckpointRandomizer", + "DarkCheckpointSwitcher", + "DarkCombine", + "DarkFaceIndexGenerator", + "DarkFaceIndexShuffle", + "DarkFolders", + "DarkLoRALoader", + "DarkPrompt" + ], + { + "title_aux": "DarkPrompts" + } + ], + "https://github.com/dave-palt/comfyui_DSP_imagehelpers": [ + [ + "dsp-imagehelpers-concat" + ], + { + "title_aux": "comfyui_DSP_imagehelpers" + } + ], + "https://github.com/dawangraoming/ComfyUI_ksampler_gpu/raw/main/ksampler_gpu.py": [ + [ + "KSamplerAdvancedGPU", + "KSamplerGPU" + ], + { + "title_aux": "KSampler GPU" + } + ], + "https://github.com/daxcay/ComfyUI-DataSet": [ + [ + "DataSet_ConceptManager", + "DataSet_CopyFiles", + "DataSet_FindAndReplace", + "DataSet_LoadImage", + "DataSet_OpenAIChat", + "DataSet_OpenAIChatImage", + "DataSet_OpenAIChatImageBatch", + "DataSet_PathSelector", + "DataSet_SaveImage", + "DataSet_TextFilesLoad", + "DataSet_TextFilesLoadFromList", + "DataSet_TextFilesSave", + "DataSet_TriggerWords", + "DataSet_Visualizer" + ], + { + "author": "Daxton Caylor", + "description": "Data Research, Preparation, and Manipulation Nodes for Model Trainers, Artists, Designers, and Animators.", + "nickname": "ComfyUI-DataSet", + "title": "ComfyUI-DataSet", + "title_aux": "ComfyUI-DataSet" + } + ], + "https://github.com/daxcay/ComfyUI-JDCN": [ + [ + "JDCN_AnyCheckpointLoader", + "JDCN_AnyFileList", + "JDCN_AnyFileListHelper", + "JDCN_AnyFileListRandom", + "JDCN_AnyFileSelector", + "JDCN_BatchCounter", + "JDCN_BatchCounterAdvance", + "JDCN_BatchImageLoadFromDir", + "JDCN_BatchImageLoadFromList", + "JDCN_BatchLatentLoadFromDir", + "JDCN_BatchLatentLoadFromList", + "JDCN_BatchSaveLatent", + "JDCN_BoolInt", + "JDCN_EnableDisable", + "JDCN_FileMover", + "JDCN_ImageSaver", + "JDCN_ListToString", + "JDCN_ReBatch", + "JDCN_SeamlessExperience", + "JDCN_ShowAny", + "JDCN_SplitString", + "JDCN_StringManipulator", + "JDCN_StringToList", + "JDCN_SwapInputs", + "JDCN_TXTFileSaver", + "JDCN_VHSFileMover" + ], + { + "author": "Daxton Caylor & Jerry Davos", + "description": "Custom Utility Nodes for Artists, Designers and Animators.", + "nickname": "ComfyUI-JDCN", + "title": "ComfyUI-JDCN", + "title_aux": "ComfyUI-JDCN" + } + ], + "https://github.com/daxthin/DZ-FaceDetailer": [ + [ + "DZ_Face_Detailer" + ], + { + "title_aux": "DZ-FaceDetailer" + } + ], + "https://github.com/dchatel/comfyui_facetools": [ + [ + "BiSeNetMask", + "CropFaces", + "DetectFaces", + "GenderFaceFilter", + "JonathandinuMask", + "MergeWarps", + "OrderedFaceFilter", + "WarpFacesBack" + ], + { + "title_aux": "comfyui_facetools" + } + ], + "https://github.com/denfrost/Den_ComfyUI_Workflow": [ + [ + "Den_BatchIndex_AS", + "Den_CropImage_AS", + "Den_Eval_AS", + "Den_FaceRestoreCFWithModel", + "Den_GPTLoaderSimple_llama", + "Den_GPTSampler_llama", + "Den_ImageMixMasked_As", + "Den_ImageToLatentSpace", + "Den_ImageToMask_AS", + "Den_Int2Any_AS", + "Den_LatentAdd_AS", + "Den_LatentMixMasked_As", + "Den_LatentMix_AS", + "Den_LatentToImages_AS", + "Den_LoadLatent_AS", + "Den_MapRange_AS", + "Den_MaskToImage_AS", + "Den_Math_AS", + "Den_NoiseImage_AS", + "Den_Number2Float_AS", + "Den_Number2Int_AS", + "Den_Number_AS", + "Den_SVD_img2vid", + "Den_SaveLatent_AS", + "Den_TextToImage_AS", + "Den_TextWildcardList_AS", + "Increment_AS" + ], + { + "title_aux": "Den_ComfyUI_Workflows" + } + ], + "https://github.com/deroberon/StableZero123-comfyui": [ + [ + "SDZero ImageSplit", + "Stablezero123", + "Stablezero123WithDepth" + ], + { + "title_aux": "StableZero123-comfyui" + } + ], + "https://github.com/deroberon/demofusion-comfyui": [ + [ + "Batch Unsampler", + "Demofusion", + "Demofusion From Single File", + "Iterative Mixing KSampler" + ], + { + "title_aux": "demofusion-comfyui" + } + ], + "https://github.com/dfl/comfyui-clip-with-break": [ + [ + "AdvancedCLIPTextEncodeWithBreak", + "CLIPTextEncodeWithBreak" + ], + { + "author": "dfl", + "description": "CLIP text encoder that does BREAK prompting like A1111", + "nickname": "CLIP with BREAK", + "title": "CLIP with BREAK syntax", + "title_aux": "CLIP with BREAK syntax" + } + ], + "https://github.com/dfl/comfyui-tcd-scheduler": [ + [ + "SamplerTCD", + "SamplerTCD EulerA", + "TCDScheduler" + ], + { + "title_aux": "ComfyUI-TCD-scheduler" + } + ], + "https://github.com/diStyApps/ComfyUI_FrameMaker": [ + [ + "FrameMaker", + "FrameMakerBatch" + ], + { + "title_aux": "ComfyUI Frame Maker" + } + ], + "https://github.com/dicksondickson/ComfyUI-Dickson-Nodes": [ + [ + "DicksonColorMatch", + "TTPlanet_Tile_Preprocessor_GF", + "TTPlanet_Tile_Preprocessor_Simple", + "TTPlanet_Tile_Preprocessor_cufoff" + ], + { + "description": "This is a set of custom nodes that I've either written myself or adapted from other authors for my own convenience. Currently includes color matching node forked from StableSR and TTPlanet's controlnet preprocessor. https://github.com/dicksondickson", + "nickname": "Dickson Nodes", + "title": "Dickson Nodes", + "title_aux": "ComfyUI-Dickson-Nodes" + } + ], + "https://github.com/digitaljohn/comfyui-propost": [ + [ + "ProPostApplyLUT", + "ProPostDepthMapBlur", + "ProPostFilmGrain", + "ProPostRadialBlur", + "ProPostVignette" + ], + { + "title_aux": "ComfyUI-ProPost" + } + ], + "https://github.com/dimtoneff/ComfyUI-PixelArt-Detector": [ + [ + "PixelArtAddDitherPattern", + "PixelArtDetectorConverter", + "PixelArtDetectorSave", + "PixelArtDetectorToImage", + "PixelArtLoadPalettes" + ], + { + "title_aux": "ComfyUI PixelArt Detector" + } + ], + "https://github.com/diontimmer/ComfyUI-Vextra-Nodes": [ + [ + "Add Text To Image", + "Apply Instagram Filter", + "Create Solid Color", + "Flatten Colors", + "Generate Noise Image", + "GlitchThis Effect", + "Hue Rotation", + "Load Picture Index", + "Pixel Sort", + "Play Sound At Execution", + "Prettify Prompt Using distilgpt2", + "Swap Color Mode" + ], + { + "title_aux": "ComfyUI-Vextra-Nodes" + } + ], + "https://github.com/discopixel-studio/comfyui-discopixel": [ + [ + "TransformTemplateOntoFaceMask" + ], + { + "author": "Anson Kao", + "description": "A small collection of custom nodes for use with ComfyUI, by Discopixel", + "nickname": "ComfyUI Discopixel", + "title": "ComfyUI Discopixel", + "title_aux": "ComfyUI Discopixel Nodes" + } + ], + "https://github.com/discus0434/comfyui-caching-embeddings": [ + [ + "CachingCLIPTextEncode" + ], + { + "title_aux": "ComfyUI Caching Embeddings" + } + ], + "https://github.com/djbielejeski/a-person-mask-generator": [ + [ + "APersonFaceLandmarkMaskGenerator", + "APersonMaskGenerator" + ], + { + "title_aux": "a-person-mask-generator" + } + ], + "https://github.com/dmMaze/sketch2manga": [ + [ + "BlendScreentone", + "EmptyLatentImageAdvanced" + ], + { + "title_aux": "Sketch2Manga" + } + ], + "https://github.com/dmarx/ComfyUI-AudioReactive": [ + [ + "OpAbs", + "OpBandpass", + "OpClamp", + "OpHarmonic", + "OpModulo", + "OpNormalize", + "OpNovelty", + "OpPercussive", + "OpPow", + "OpPow2", + "OpPredominant_pulse", + "OpQuantize", + "OpRms", + "OpSmoosh", + "OpSmooth", + "OpSqrt", + "OpStretch", + "OpSustain", + "OpThreshold" + ], + { + "title_aux": "ComfyUI-AudioReactive" + } + ], + "https://github.com/dmarx/ComfyUI-Keyframed": [ + [ + "Example", + "KfAddCurveToPGroup", + "KfAddCurveToPGroupx10", + "KfApplyCurveToCond", + "KfConditioningAdd", + "KfConditioningAddx10", + "KfCurveConstant", + "KfCurveDraw", + "KfCurveFromString", + "KfCurveFromYAML", + "KfCurveInverse", + "KfCurveToAcnLatentKeyframe", + "KfCurvesAdd", + "KfCurvesAddx10", + "KfCurvesDivide", + "KfCurvesMultiply", + "KfCurvesMultiplyx10", + "KfCurvesSubtract", + "KfDebug_Clip", + "KfDebug_Cond", + "KfDebug_Curve", + "KfDebug_Float", + "KfDebug_Image", + "KfDebug_Int", + "KfDebug_Latent", + "KfDebug_Model", + "KfDebug_Passthrough", + "KfDebug_Segs", + "KfDebug_String", + "KfDebug_Vae", + "KfDrawSchedule", + "KfEvaluateCurveAtT", + "KfGetCurveFromPGroup", + "KfGetScheduleConditionAtTime", + "KfGetScheduleConditionSlice", + "KfKeyframedCondition", + "KfKeyframedConditionWithText", + "KfPGroupCurveAdd", + "KfPGroupCurveMultiply", + "KfPGroupDraw", + "KfPGroupProd", + "KfPGroupSum", + "KfSetCurveLabel", + "KfSetKeyframe", + "KfSinusoidalAdjustAmplitude", + "KfSinusoidalAdjustFrequency", + "KfSinusoidalAdjustPhase", + "KfSinusoidalAdjustWavelength", + "KfSinusoidalEntangledZeroOneFromFrequencyx2", + "KfSinusoidalEntangledZeroOneFromFrequencyx3", + "KfSinusoidalEntangledZeroOneFromFrequencyx4", + "KfSinusoidalEntangledZeroOneFromFrequencyx5", + "KfSinusoidalEntangledZeroOneFromFrequencyx6", + "KfSinusoidalEntangledZeroOneFromFrequencyx7", + "KfSinusoidalEntangledZeroOneFromFrequencyx8", + "KfSinusoidalEntangledZeroOneFromFrequencyx9", + "KfSinusoidalEntangledZeroOneFromWavelengthx2", + "KfSinusoidalEntangledZeroOneFromWavelengthx3", + "KfSinusoidalEntangledZeroOneFromWavelengthx4", + "KfSinusoidalEntangledZeroOneFromWavelengthx5", + "KfSinusoidalEntangledZeroOneFromWavelengthx6", + "KfSinusoidalEntangledZeroOneFromWavelengthx7", + "KfSinusoidalEntangledZeroOneFromWavelengthx8", + "KfSinusoidalEntangledZeroOneFromWavelengthx9", + "KfSinusoidalGetAmplitude", + "KfSinusoidalGetFrequency", + "KfSinusoidalGetPhase", + "KfSinusoidalGetWavelength", + "KfSinusoidalWithFrequency", + "KfSinusoidalWithWavelength" + ], + { + "title_aux": "ComfyUI-Keyframed" + } + ], + "https://github.com/drago87/ComfyUI_Dragos_Nodes": [ + [ + "file_padding", + "image_info", + "lora_loader", + "vae_loader" + ], + { + "title_aux": "ComfyUI_Dragos_Nodes" + } + ], + "https://github.com/drustan-hawk/primitive-types": [ + [ + "float", + "int", + "string", + "string_multiline" + ], + { + "title_aux": "primitive-types" + } + ], + "https://github.com/e7mac/ComfyUI-ShadertoyGL": [ + [ + "ColorChannelOffset", + "Shader", + "Shadertoy" + ], + { + "title_aux": "ComfyUI-ShadertoyGL" + } + ], + "https://github.com/ealkanat/comfyui_easy_padding": [ + [ + "comfyui-easy-padding" + ], + { + "title_aux": "ComfyUI Easy Padding" + } + ], + "https://github.com/edenartlab/eden_comfy_pipelines": [ + [ + "Animation_RGB_Mask", + "CLIP_Interrogator", + "ConvertToGrayscale", + "Eden_Bool", + "Eden_Compare", + "Eden_DebugPrint", + "Eden_Float", + "Eden_Int", + "Eden_Lora_Loader", + "Eden_String", + "FolderScanner", + "GetRandomFile", + "Get_Prefixed_Imgs", + "HistogramMatching", + "IMG_blender", + "IMG_padder", + "IMG_resolution_multiple_of", + "IMG_scaler", + "IMG_unpadder", + "If ANY execute A else B", + "ImageDescriptionNode", + "LatentTypeConversion", + "Linear_Combine_IP_Embeds", + "LoadImagesByFilename", + "LoadRandomImage", + "Load_Embeddings_From_Folder", + "MaskFromRGB", + "MaskFromRGB_KMeans", + "Random_Style_Mixture", + "SaveImageAdvanced", + "SavePosEmbeds", + "VAEDecode_to_folder", + "VideoFrameSelector", + "WidthHeightPicker" + ], + { + "title_aux": "Various custom nodes by Eden.art" + } + ], + "https://github.com/evanspearman/ComfyMath": [ + [ + "CM_BoolBinaryOperation", + "CM_BoolToInt", + "CM_BoolUnaryOperation", + "CM_BreakoutVec2", + "CM_BreakoutVec3", + "CM_BreakoutVec4", + "CM_ComposeVec2", + "CM_ComposeVec3", + "CM_ComposeVec4", + "CM_FloatBinaryCondition", + "CM_FloatBinaryOperation", + "CM_FloatToInt", + "CM_FloatToNumber", + "CM_FloatUnaryCondition", + "CM_FloatUnaryOperation", + "CM_IntBinaryCondition", + "CM_IntBinaryOperation", + "CM_IntToBool", + "CM_IntToFloat", + "CM_IntToNumber", + "CM_IntUnaryCondition", + "CM_IntUnaryOperation", + "CM_NearestSDXLResolution", + "CM_NumberBinaryCondition", + "CM_NumberBinaryOperation", + "CM_NumberToFloat", + "CM_NumberToInt", + "CM_NumberUnaryCondition", + "CM_NumberUnaryOperation", + "CM_SDXLResolution", + "CM_Vec2BinaryCondition", + "CM_Vec2BinaryOperation", + "CM_Vec2ScalarOperation", + "CM_Vec2ToScalarBinaryOperation", + "CM_Vec2ToScalarUnaryOperation", + "CM_Vec2UnaryCondition", + "CM_Vec2UnaryOperation", + "CM_Vec3BinaryCondition", + "CM_Vec3BinaryOperation", + "CM_Vec3ScalarOperation", + "CM_Vec3ToScalarBinaryOperation", + "CM_Vec3ToScalarUnaryOperation", + "CM_Vec3UnaryCondition", + "CM_Vec3UnaryOperation", + "CM_Vec4BinaryCondition", + "CM_Vec4BinaryOperation", + "CM_Vec4ScalarOperation", + "CM_Vec4ToScalarBinaryOperation", + "CM_Vec4ToScalarUnaryOperation", + "CM_Vec4UnaryCondition", + "CM_Vec4UnaryOperation" + ], + { + "title_aux": "ComfyMath" + } + ], + "https://github.com/exdysa/comfyui-selector": [ + [ + "Fork", + "ForkClip", + "Recourse", + "Recourse+/-", + "RecourseCkpt", + "RecourseImage", + "Selector", + "Unite" + ], + { + "author": "\"\u02f6\ud835\udfa2\u292c\u2ad2\u2d56s\u143c\u02f6\"", + "description": "\"EXDYSA. Selector and Recourse. Presets & failsafes. Work flow.\"", + "nickname": "\"Selector\"", + "title": "\"Selector\"", + "title_aux": "comfyui-selector" + } + ], + "https://github.com/fablestudio/ComfyUI-Showrunner-Utils": [ + [ + "AlignFace" + ], + { + "title_aux": "ComfyUI-Showrunner-Utils" + } + ], + "https://github.com/fearnworks/ComfyUI_FearnworksNodes/raw/main/fw_nodes.py": [ + [ + "Count Files in Directory (FW)", + "Count Tokens (FW)", + "Token Count Ranker(FW)", + "Trim To Tokens (FW)" + ], + { + "title_aux": "Fearnworks Custom Nodes" + } + ], + "https://github.com/fexli/fexli-util-node-comfyui": [ + [ + "FEBCPrompt", + "FEBatchGenStringBCDocker", + "FEColor2Image", + "FEColorOut", + "FEDataInsertor", + "FEDataPacker", + "FEDataUnpacker", + "FEDeepClone", + "FEDictPacker", + "FEDictUnpacker", + "FEEncLoraLoader", + "FEExtraInfoAdd", + "FEGenStringBCDocker", + "FEGenStringGPT", + "FEImageNoiseGenerate", + "FEImagePadForOutpaint", + "FEImagePadForOutpaintByImage", + "FEOperatorIf", + "FEPythonStrOp", + "FERandomBool", + "FERandomLoraSelect", + "FERandomPrompt", + "FERandomizedColor2Image", + "FERandomizedColorOut", + "FERerouteWithName", + "FESaveEncryptImage", + "FETextCombine", + "FETextCombine2Any", + "FETextInput" + ], + { + "title_aux": "fexli-util-node-comfyui" + } + ], + "https://github.com/fexploit/ComfyUI-AutoLabel": [ + [ + "AutoLabel" + ], + { + "title_aux": "ComfyUI-AutoLabel" + } + ], + "https://github.com/fexploit/ComfyUI-AutoTrimBG": [ + [ + "RonLayers/TrimBg: RonLayersTrimBgUltraV2" + ], + { + "title_aux": "ComfyUI-AutoTrimBG" + } + ], + "https://github.com/fexploit/ComfyUI-Classifier": [ + [ + "ClassifierNode" + ], + { + "title_aux": "ComfyUI-Classifier" + } + ], + "https://github.com/filipemeneses/comfy_pixelization": [ + [ + "Pixelization" + ], + { + "title_aux": "Pixelization" + } + ], + "https://github.com/filliptm/ComfyUI_Fill-Nodes": [ + [ + "FL_Ascii", + "FL_AudioConverter", + "FL_AudioFrameCalculator", + "FL_AudioPreview", + "FL_BatchAlign", + "FL_CodeNode", + "FL_DirectoryCrawl", + "FL_Glitch", + "FL_HalftonePattern", + "FL_HexagonalPattern", + "FL_ImageCaptionSaver", + "FL_ImageCollage", + "FL_ImageDimensionDisplay", + "FL_ImageDurationSync", + "FL_ImageNotes", + "FL_ImagePixelator", + "FL_ImageRandomizer", + "FL_InfiniteZoom", + "FL_InpaintCrop", + "FL_Inpaint_Stitch", + "FL_KsamplerSettings", + "FL_NFTGenerator", + "FL_PaperDrawn", + "FL_PasteOnCanvas", + "FL_PixelArtShader", + "FL_PixelSort", + "FL_PromptSelector", + "FL_RandomNumber", + "FL_RetroEffect", + "FL_Ripple", + "FL_SDUltimate_Slices", + "FL_SeparateMaskComponents", + "FL_Shadertoy", + "FL_TD_Sampler", + "FL_VideoCropMask", + "FL_VideoRecompose" + ], + { + "title_aux": "ComfyUI_Fill-Nodes" + } + ], + "https://github.com/fitCorder/fcSuite/raw/main/fcSuite.py": [ + [ + "fcFloat", + "fcFloatMatic", + "fcHex", + "fcInteger" + ], + { + "title_aux": "fcSuite" + } + ], + "https://github.com/florestefano1975/ComfyUI-HiDiffusion": [ + [ + "HiDiffusionSD15", + "HiDiffusionSD21", + "HiDiffusionSDXL", + "HiDiffusionSDXLTurbo" + ], + { + "title_aux": "ComfyUI HiDiffusion" + } + ], + "https://github.com/florestefano1975/ComfyUI-StabilityAI-Suite": [ + [ + "StabilityAI Suite - Creative Upscale", + "StabilityAI Suite - Creative Upscale Recover File", + "StabilityAI Suite - Image Core + Style Preset", + "StabilityAI Suite - Inpainting", + "StabilityAI Suite - Outpainting", + "StabilityAI Suite - Remove Background", + "StabilityAI Suite - SD3", + "StabilityAI Suite - Search and Replace" + ], + { + "title_aux": "ComfyUI StabilityAI Suite" + } + ], + "https://github.com/florestefano1975/comfyui-portrait-master": [ + [ + "PortraitMaster" + ], + { + "title_aux": "comfyui-portrait-master" + } + ], + "https://github.com/florestefano1975/comfyui-prompt-composer": [ + [ + "PromptComposerCustomLists", + "PromptComposerEffect", + "PromptComposerGrouping", + "PromptComposerMerge", + "PromptComposerStyler", + "PromptComposerTextSingle", + "promptComposerTextMultiple" + ], + { + "title_aux": "comfyui-prompt-composer" + } + ], + "https://github.com/flowtyone/ComfyUI-Flowty-CRM": [ + [ + "CCMSampler", + "CRMModelLoader", + "CRMModeler", + "CRMModelerCuda", + "CRMPoseSampler", + "CRMPoserConfig", + "CRMPreprocessForPoser", + "CRMViewer" + ], + { + "title_aux": "ComfyUI-Flowty-CRM" + } + ], + "https://github.com/flowtyone/ComfyUI-Flowty-LDSR": [ + [ + "LDSRModelLoader", + "LDSRUpscale", + "LDSRUpscaler" + ], + { + "title_aux": "ComfyUI-Flowty-LDSR" + } + ], + "https://github.com/flowtyone/ComfyUI-Flowty-TripoSR": [ + [ + "TripoSRModelLoader", + "TripoSRSampler", + "TripoSRViewer" + ], + { + "title_aux": "ComfyUI-Flowty-TripoSR" + } + ], + "https://github.com/flyingshutter/As_ComfyUI_CustomNodes": [ + [ + "BatchIndex_AS", + "CropImage_AS", + "Eval_AS", + "ImageMixMasked_As", + "ImageToMask_AS", + "Increment_AS", + "Int2Any_AS", + "LatentAdd_AS", + "LatentMixMasked_As", + "LatentMix_AS", + "LatentToImages_AS", + "LoadLatent_AS", + "MapRange_AS", + "MaskToImage_AS", + "Math_AS", + "NoiseImage_AS", + "Number2Float_AS", + "Number2Int_AS", + "Number_AS", + "SaveLatent_AS", + "TextToImage_AS", + "TextWildcardList_AS" + ], + { + "title_aux": "As_ComfyUI_CustomNodes" + } + ], + "https://github.com/fmatray/ComfyUI_BattlemapGrid": [ + [ + "Battlemap Grid", + "Compass", + "Map Generator", + "Map Generator(Outdoors)" + ], + { + "title_aux": "ComfyUI_BattlemapGrid" + } + ], + "https://github.com/fofr/ComfyUI-HyperSDXL1StepUnetScheduler": [ + [ + "HyperSDXL1StepUnetScheduler" + ], + { + "title_aux": "ComfyUI-HyperSDXL1StepUnetScheduler (ByteDance)" + } + ], + "https://github.com/fofr/ComfyUI-Prompter-fofrAI": [ + [ + "List sampler \ud83e\udeb4", + "Prompt from template \ud83e\udeb4" + ], + { + "title_aux": "ComfyUI-Prompter-fofrAI" + } + ], + "https://github.com/forever22777/comfyui-self-guidance": [ + [ + "CLIPConditioning", + "CheckpointLoaderMixWithDiffusers", + "SelfGuidanceSampler" + ], + { + "title_aux": "Self-Guidance nodes" + } + ], + "https://github.com/foxtrot-roger/comfyui-rf-nodes": [ + [ + "LogBool", + "LogFloat", + "LogInt", + "LogNumber", + "LogString", + "LogVec2", + "LogVec3", + "RF_AtIndexString", + "RF_BoolToString", + "RF_FloatToString", + "RF_IntToString", + "RF_JsonStyleLoader", + "RF_MergeLines", + "RF_NumberToString", + "RF_OptionsString", + "RF_RangeFloat", + "RF_RangeInt", + "RF_RangeNumber", + "RF_SavePromptInfo", + "RF_SplitLines", + "RF_TextConcatenate", + "RF_TextInput", + "RF_TextReplace", + "RF_Timestamp", + "RF_ToString", + "RF_Vec2ToString", + "RF_Vec3ToString", + "TextLine" + ], + { + "title_aux": "RF Nodes" + } + ], + "https://github.com/frankchieng/ComfyUI_Aniportrait": [ + [ + "AniPortrait_Audio2Video", + "AniPortrait_Audio_Path", + "AniPortrait_LoadVideoPath", + "AniPortrait_Pose_Gen_Video", + "AniPortrait_Ref_Image_Path", + "AniPortrait_Video_Gen_Pose" + ], + { + "title_aux": "ComfyUI_Aniportrait" + } + ], + "https://github.com/frankchieng/ComfyUI_MagicClothing": [ + [ + "MagicClothing_Animatediff", + "MagicClothing_Generate", + "MagicClothing_Inpainting" + ], + { + "title_aux": "ComfyUI_MagicClothing" + } + ], + "https://github.com/frankchieng/ComfyUI_llm_easyanimiate": [ + [], + { + "nodename_pattern": "^FrankChiengEasyAnimate", + "title_aux": "ComfyUI_llm_easyanimiate" + } + ], + "https://github.com/fsdymy1024/ComfyUI_fsdymy": [ + [ + "IPAdapterLayerWeight", + "Preview Image Without Metadata", + "PreviewImageWithoutMetadata", + "Save Image Without Metadata", + "SaveImageWithoutMetadata", + "ShowText", + "ZhiPuAiNode" + ], + { + "title_aux": "ComfyUI_fsdymy" + } + ], + "https://github.com/gemell1/ComfyUI_GMIC": [ + [ + "GmicCliWrapper", + "GmicQtWrapper" + ], + { + "title_aux": "ComfyUI_GMIC" + } + ], + "https://github.com/get-salt-AI/SaltAI": [ + [ + "SAIPrimitiveConverter", + "SAIStringRegexSearchMatch", + "SAIStringRegexSearchReplace", + "SaltAIStableVideoDiffusion", + "SaltBatchCropDataExtractor", + "SaltCLIPSegLoader", + "SaltCLIPSegMasking", + "SaltCropImageLocation", + "SaltDisplayAny", + "SaltImagePasteCrop", + "SaltInfo", + "SaltInput", + "SaltLoadImageZip", + "SaltMaskCropRegion", + "SaltMasksToImages", + "SaltOutput", + "SaltRGBAFromMask", + "SaltWebsiteScreenshot" + ], + { + "title_aux": "SaltAI-Open-Resources" + } + ], + "https://github.com/get-salt-AI/SaltAI_Language_Toolkit": [ + [ + "AddTool", + "ChangeSystemMessage", + "ClearMemory", + "ConversableAgentCreator", + "ConversableAgentCreatorAdvanced", + "ConvertAgentAsTool", + "ConvertAgentToLlamaindex", + "CreateTavilySearchTool", + "Example", + "GenerateReply", + "GroupChat", + "GroupChatAdvanced", + "GroupChatManagerCreator", + "LLMCSVReader", + "LLMChat", + "LLMChatBot", + "LLMChatEngine", + "LLMChatMessageConcat", + "LLMChatMessages", + "LLMChatMessagesAdv", + "LLMComplete", + "LLMCustomNodeComposer", + "LLMDirectoryReader", + "LLMDocumentListAppend", + "LLMDocxReader", + "LLMEpubReader", + "LLMFlatReader", + "LLMHTMLTagReader", + "LLMHWPReader", + "LLMHtmlComposer", + "LLMHtmlRepair", + "LLMIPYNBReader", + "LLMImageCaptionReader", + "LLMImageTabularChartReader", + "LLMImageTextReader", + "LLMImageVisionLLMReader", + "LLMInputToDocuments", + "LLMJsonComposer", + "LLMJsonRepair", + "LLMLLaVANextImageEvaluator", + "LLMLLaVANextModelLoader", + "LLMMarkdownComposer", + "LLMMarkdownReader", + "LLMMarkdownRepair", + "LLMMboxReader", + "LLMMultiModalImageEvaluation", + "LLMNotionReader", + "LLMOpenAIModel", + "LLMOpenAIModelOpts", + "LLMPDFReader", + "LLMPagedCSVReader", + "LLMPandasCSVReader", + "LLMParquetDatasetSearcher", + "LLMPostProcessDocuments", + "LLMPptxReader", + "LLMPyMuPDFReader", + "LLMQueryEngine", + "LLMQueryEngineAdv", + "LLMQueryEngineAsTool", + "LLMRTFReader", + "LLMRegexCreator", + "LLMRegexRepair", + "LLMRssReaderNode", + "LLMSaltWebCrawler", + "LLMScaleSERPSearch", + "LLMSemanticSplitterNodeParser", + "LLMSentenceSplitterNodeCreator", + "LLMServiceContextAdv", + "LLMServiceContextDefault", + "LLMSimpleWebPageReader", + "LLMSimpleWebPageReaderAdv", + "LLMSummaryIndex", + "LLMTavilyResearch", + "LLMTrafilaturaWebReader", + "LLMTrafilaturaWebReaderAdv", + "LLMTreeIndex", + "LLMUnstructuredReader", + "LLMVectorStoreIndex", + "LLMVectorStoreIndexAdv", + "LLMVideoAudioReader", + "LLMXMLReader", + "LLMYamlComposer", + "LLMYamlRepair", + "SaltJSONQueryEngine", + "SendMessage", + "SimpleChat" + ], + { + "title_aux": "SaltAI Language Toolkit" + } + ], + "https://github.com/get-salt-AI/SaltAI_LlamaIndex": [ + [ + "AddTool", + "ChangeSystemMessage", + "ClearMemory", + "ConversableAgentCreator", + "ConversableAgentCreatorAdvanced", + "ConvertAgentAsTool", + "ConvertAgentToLlamaindex", + "CreateTavilySearchTool", + "Example", + "GenerateReply", + "GroupChat", + "GroupChatAdvanced", + "GroupChatManagerCreator", + "LLMCSVReader", + "LLMChat", + "LLMChatBot", + "LLMChatEngine", + "LLMChatMessageConcat", + "LLMChatMessages", + "LLMChatMessagesAdv", + "LLMComplete", + "LLMCustomNodeComposer", + "LLMDirectoryReader", + "LLMDocumentListAppend", + "LLMDocxReader", + "LLMEpubReader", + "LLMFlatReader", + "LLMHTMLTagReader", + "LLMHWPReader", + "LLMHtmlComposer", + "LLMHtmlRepair", + "LLMIPYNBReader", + "LLMImageCaptionReader", + "LLMImageTabularChartReader", + "LLMImageTextReader", + "LLMImageVisionLLMReader", + "LLMInputToDocuments", + "LLMJsonComposer", + "LLMJsonRepair", + "LLMLLaVANextImageEvaluator", + "LLMLLaVANextModelLoader", + "LLMMarkdownComposer", + "LLMMarkdownReader", + "LLMMarkdownRepair", + "LLMMboxReader", + "LLMMultiModalImageEvaluation", + "LLMNotionReader", + "LLMOpenAIModel", + "LLMOpenAIModelOpts", + "LLMPDFReader", + "LLMPagedCSVReader", + "LLMPandasCSVReader", + "LLMParquetDatasetSearcher", + "LLMPostProcessDocuments", + "LLMPptxReader", + "LLMPyMuPDFReader", + "LLMQueryEngine", + "LLMQueryEngineAdv", + "LLMQueryEngineAsTool", + "LLMRTFReader", + "LLMRegexCreator", + "LLMRegexRepair", + "LLMRssReaderNode", + "LLMSaltWebCrawler", + "LLMScaleSERPSearch", + "LLMSemanticSplitterNodeParser", + "LLMSentenceSplitterNodeCreator", + "LLMServiceContextAdv", + "LLMServiceContextDefault", + "LLMSimpleWebPageReader", + "LLMSimpleWebPageReaderAdv", + "LLMSummaryIndex", + "LLMTavilyResearch", + "LLMTrafilaturaWebReader", + "LLMTrafilaturaWebReaderAdv", + "LLMTreeIndex", + "LLMUnstructuredReader", + "LLMVectorStoreIndex", + "LLMVectorStoreIndexAdv", + "LLMVideoAudioReader", + "LLMXMLReader", + "LLMYamlComposer", + "LLMYamlRepair", + "SaltJSONQueryEngine", + "SendMessage", + "SimpleChat" + ], + { + "title_aux": "SaltAI_LlamaIndex" + } + ], + "https://github.com/giriss/comfy-image-saver": [ + [ + "Cfg Literal", + "Checkpoint Selector", + "Int Literal", + "Sampler Selector", + "Save Image w/Metadata", + "Scheduler Selector", + "Seed Generator", + "String Literal", + "Width/Height Literal" + ], + { + "title_aux": "Save Image with Generation Metadata" + } + ], + "https://github.com/githubYiheng/ComfyUI_Change_IMAGE_BOREDER": [ + [ + "ChangeImageBorder" + ], + { + "title_aux": "ComfyUI_Change_IMAGE_BOREDER" + } + ], + "https://github.com/githubYiheng/ComfyUI_GetFileNameFromURL": [ + [ + "GetFileNameFromURL" + ], + { + "title_aux": "ComfyUI_GetFileNameFromURL" + } + ], + "https://github.com/githubYiheng/comfyui_kmeans_filter": [ + [ + "ImageKmeansFilter" + ], + { + "title_aux": "comfyui_kmeans_filter" + } + ], + "https://github.com/githubYiheng/comfyui_meanshift_filter": [ + [ + "ImageMeanshiftFilter" + ], + { + "title_aux": "comfyui_meanshift_filter" + } + ], + "https://github.com/githubYiheng/comfyui_private_postprocessor": [ + [ + "ImageCPostprocessor", + "PrivateImageMask" + ], + { + "title_aux": "comfyui_private_postprocessor" + } + ], + "https://github.com/glibsonoran/Plush-for-ComfyUI": [ + [ + "AI Chooser", + "AdvPromptEnhancer", + "DalleImage", + "Enhancer", + "ImgTextSwitch", + "Plush-Exif Wrangler", + "Tagger", + "mulTextSwitch" + ], + { + "title_aux": "Plush-for-ComfyUI" + } + ], + "https://github.com/glifxyz/ComfyUI-GlifNodes": [ + [ + "GlifConsistencyDecoder", + "GlifPatchConsistencyDecoderTiled", + "GlifVariable", + "HFHubEmbeddingLoader", + "HFHubLoraLoader", + "ImageToMultipleOf", + "SDXLAspectRatio" + ], + { + "title_aux": "ComfyUI-GlifNodes" + } + ], + "https://github.com/glowcone/comfyui-base64-to-image": [ + [ + "LoadImageFromBase64" + ], + { + "title_aux": "Load Image From Base64 URI" + } + ], + "https://github.com/godspede/ComfyUI_Substring": [ + [ + "SubstringTheory" + ], + { + "title_aux": "ComfyUI Substring" + } + ], + "https://github.com/gokayfem/ComfyUI-Depth-Visualization": [ + [ + "DepthViewer" + ], + { + "title_aux": "ComfyUI-Depth-Visualization" + } + ], + "https://github.com/gokayfem/ComfyUI-Dream-Interpreter": [ + [ + "DreamViewer" + ], + { + "title_aux": "ComfyUI-Dream-Interpreter" + } + ], + "https://github.com/gokayfem/ComfyUI-Texture-Simple": [ + [ + "TextureViewer" + ], + { + "title_aux": "ComfyUI-Texture-Simple" + } + ], + "https://github.com/gokayfem/ComfyUI_VLM_nodes": [ + [ + "AudioLDM2Node", + "ChatMusician", + "CreativeArtPromptGenerator", + "Internlm", + "Joytag", + "JsonToText", + "KeywordExtraction", + "Kosmos2model", + "LLMLoader", + "LLMPromptGenerator", + "LLMSampler", + "LLava Loader Simple", + "LLavaOptionalMemoryFreeAdvanced", + "LLavaOptionalMemoryFreeSimple", + "LLavaPromptGenerator", + "LLavaSamplerAdvanced", + "LLavaSamplerSimple", + "LlavaClipLoader", + "MCLLaVAModel", + "MoonDream", + "Moondream2model", + "PlayMusic", + "PromptGenerateAPI", + "SaveAudioNode", + "SimpleText", + "StructuredOutput", + "Suggester", + "UformGen2QwenNode", + "ViewText" + ], + { + "title_aux": "VLM_nodes" + } + ], + "https://github.com/gonzalu/ComfyUI_YFG_Comical": [ + [ + "Image10Switcher_node", + "Image15Switcher_node", + "Image20Switcher_node", + "Image3Switcher_node", + "Image5Switcher_node", + "MonoClip_node", + "PixelArt_node", + "VAEDecodePreview_node", + "image2contrastMask_node", + "image2imbgg_node", + "image_halftone", + "image_histograms_node", + "image_histograms_node_compact", + "images_side_by_side", + "imgbbLoader_node", + "smartCheckpointLoader_node", + "storeURL_node", + "textMaskOverlay_node" + ], + { + "author": "Manny Gonzalez", + "description": "Utility custom nodes for special effects, image manipulation and quality of life tools.", + "nickname": "\ud83d\udc2f YFG Comical Nodes", + "title": "\ud83d\udc2f YFG Comical Nodes", + "title_aux": "\ud83d\ude38 YFG Comical Nodes" + } + ], + "https://github.com/griptape-ai/ComfyUI-Griptape": [ + [ + "Griptape Agent Config: Amazon Bedrock", + "Griptape Agent Config: Anthropic", + "Griptape Agent Config: Google", + "Griptape Agent Config: LM Studio", + "Griptape Agent Config: Ollama", + "Griptape Agent Config: OpenAI", + "Griptape Audio Driver: OpenAI", + "Griptape Combine: Merge Inputs", + "Griptape Combine: Merge Texts", + "Griptape Combine: Rules List", + "Griptape Combine: Tool List", + "Griptape Config: Environment Variables", + "Griptape Convert: Text to CLIP Encode", + "Griptape Convert: Text to Combo", + "Griptape Create: Agent", + "Griptape Create: CLIP Text Encode", + "Griptape Create: Image Variation", + "Griptape Create: Image from Text", + "Griptape Create: Rules", + "Griptape Create: Text", + "Griptape Display: Artifact", + "Griptape Display: Data as Text", + "Griptape Display: Image", + "Griptape Display: Text", + "Griptape Driver: Amazon Bedrock Stable Diffusion", + "Griptape Driver: Amazon Bedrock Titan", + "Griptape Driver: Leonardo.AI", + "Griptape Driver: OpenAI Image Generation", + "Griptape Expand: Agent Nodes", + "Griptape Load: Audio", + "Griptape Load: Image From URL", + "Griptape Run: Agent", + "Griptape Run: Audio Transcription", + "Griptape Run: Image Description", + "Griptape Run: Parallel Image Description", + "Griptape Run: Prompt Task", + "Griptape Run: Text Summary", + "Griptape Run: Tool Task", + "Griptape Run: Toolkit Task", + "Griptape Set: Default Agent", + "Griptape Tool: Audio Transcription", + "Griptape Tool: Calculator", + "Griptape Tool: DateTime", + "Griptape Tool: FileManager", + "Griptape Tool: Griptape Cloud KnowledgeBase", + "Griptape Tool: WebScraper", + "Griptape Tool: WebSearch" + ], + { + "author": "Jason Schleifer", + "description": "This extension offers various nodes that allow you to work with LLMs using the Griptape Python Framework (https://griptape.ai)", + "nickname": "ComfyUI-Griptape", + "title": "ComfyUI Griptape Nodes", + "title_aux": "ComfyUI Griptape Nodes" + } + ], + "https://github.com/guill/abracadabra-comfyui": [ + [ + "AbracadabraNode", + "AbracadabraNodeDefSummary" + ], + { + "title_aux": "abracadabra-comfyui" + } + ], + "https://github.com/guoyk93/yk-node-suite-comfyui": [ + [ + "YKImagePadForOutpaint", + "YKMaskToImage" + ], + { + "title_aux": "y.k.'s ComfyUI node suite" + } + ], + "https://github.com/hackkhai/ComfyUI-Image-Matting": [ + [ + "ApplyMatting", + "CreateTrimap", + "MattingModelLoader" + ], + { + "title_aux": "ComfyUI-Image-Matting" + } + ], + "https://github.com/haohaocreates/ComfyUI-HH-Image-Selector": [ + [ + "Image Selector" + ], + { + "title_aux": "ComfyUI-HH-Image-Selector" + } + ], + "https://github.com/hay86/ComfyUI_AceNodes": [ + [ + "ACE_AnyInputSwitchBool", + "ACE_AudioLoad", + "ACE_AudioPlay", + "ACE_AudioSave", + "ACE_Expression_Eval", + "ACE_Float", + "ACE_ImageColorFix", + "ACE_ImageConstrain", + "ACE_ImageFaceCrop", + "ACE_ImageGetSize", + "ACE_ImageLoadFromCloud", + "ACE_ImageQA", + "ACE_ImageRemoveBackground", + "ACE_ImageSaveToCloud", + "ACE_Integer", + "ACE_MaskBlur", + "ACE_Seed", + "ACE_Text", + "ACE_TextConcatenate", + "ACE_TextGoogleTranslate", + "ACE_TextInputSwitch2Way", + "ACE_TextInputSwitch4Way", + "ACE_TextInputSwitch8Way", + "ACE_TextList", + "ACE_TextPreview", + "ACE_TextSelector", + "ACE_TextToResolution", + "ACE_TextTranslate" + ], + { + "title_aux": "ComfyUI AceNodes" + } + ], + "https://github.com/hay86/ComfyUI_DDColor": [ + [ + "D_DDColor" + ], + { + "title_aux": "ComfyUI DDColor" + } + ], + "https://github.com/hay86/ComfyUI_Dreamtalk": [ + [ + "D_DreamTalk" + ], + { + "title_aux": "ComfyUI Dreamtalk" + } + ], + "https://github.com/hay86/ComfyUI_Hallo": [ + [ + "D_HalloNode" + ], + { + "title_aux": "ComfyUI Hallo" + } + ], + "https://github.com/hay86/ComfyUI_MiniCPM-V": [ + [ + "D_MiniCPM_VQA" + ], + { + "title_aux": "ComfyUI MiniCPM-V" + } + ], + "https://github.com/hay86/ComfyUI_OpenVoice": [ + [ + "D_OpenVoice_STS", + "D_OpenVoice_TTS", + "D_OpenVoice_TTS_V2" + ], + { + "title_aux": "ComfyUI OpenVoice" + } + ], + "https://github.com/hben35096/ComfyUI-ToolBox": [ + [ + "AutoDLDownload", + "FolderDeleter", + "FolderViewe" + ], + { + "title_aux": "ComfyUI-ToolBox" + } + ], + "https://github.com/heshengtao/comfyui_LLM_party": [ + [ + "About_us", + "CLIPTextEncode_party", + "CosyVoice", + "Dingding", + "Dingding_tool", + "KG_csv_toolkit_developer", + "KG_csv_toolkit_user", + "KG_json_toolkit_developer", + "KG_json_toolkit_user", + "KG_neo_toolkit_developer", + "KG_neo_toolkit_user", + "KSampler_party", + "LLM", + "LLM_api_loader", + "LLM_local", + "LLM_local_loader", + "LLavaLoader", + "VAEDecode_party", + "accuweather_tool", + "api_tool", + "arxiv_tool", + "bing_tool", + "check_web_tool", + "classify_function", + "classify_function_plus", + "classify_persona", + "classify_persona_plus", + "custom_persona", + "ebd_tool", + "end_dialog", + "end_workflow", + "feishu", + "feishu_tool", + "file_combine", + "file_combine_plus", + "get_string", + "github_tool", + "google_tool", + "image_iterator", + "interpreter_tool", + "json_get_value", + "json_parser", + "keyword_tool", + "listen_audio", + "llama_guff_loader", + "load_embeddings", + "load_excel", + "load_file", + "load_file_folder", + "load_keyword", + "load_name", + "load_persona", + "load_url", + "load_wikipedia", + "new_interpreter_tool", + "omost_decode", + "omost_setting", + "openai_tts", + "openai_whisper", + "play_audio", + "replace_string", + "show_text_party", + "start_dialog", + "start_workflow", + "story_json_tool", + "string_logic", + "substring", + "text_iterator", + "time_tool", + "tool_combine", + "tool_combine_plus", + "translate_persona", + "weather_tool", + "weekday_tool", + "wikipedia_tool", + "work_wechat", + "work_wechat_tool", + "workflow_tool", + "workflow_transfer" + ], + { + "title_aux": "comfyui_LLM_party" + } + ], + "https://github.com/hhhzzyang/Comfyui_Lama": [ + [ + "LamaApply", + "LamaModelLoader", + "YamlConfigLoader" + ], + { + "title_aux": "Comfyui-Lama" + } + ], + "https://github.com/hiforce/comfyui-hiforce-plugin": [ + [ + "HfBoolSwitchKSampleStatus", + "HfImageAutoExpansionSquare", + "HfImageToRGB", + "HfImageToRGBA", + "HfInitImageWithMaxSize", + "HfIterativeLatentUpscale", + "HfLoadImageWithCropper", + "HfLookbackSamplerLoader", + "HfLoopback", + "HfResizeImage", + "HfSampler", + "HfSamplerLoader", + "HfSamplerLoopback", + "HfSaveImage", + "HfSwitchKSampleStatus", + "HfTwoSamplersForMask", + "HfTwoStepSamplers", + "LoadImageFromURL" + ], + { + "title_aux": "Comfyui HiFORCE Plugin" + } + ], + "https://github.com/hinablue/ComfyUI_3dPoseEditor": [ + [ + "Hina.PoseEditor3D" + ], + { + "title_aux": "ComfyUI 3D Pose Editor" + } + ], + "https://github.com/holchan/ComfyUI-ModelDownloader": [ + [ + "LoRADownloader", + "ModelDownloader" + ], + { + "title_aux": "ComfyUI-ModelDownloader" + } + ], + "https://github.com/huagetai/ComfyUI-Gaffer": [ + [ + "ApplyICLight", + "CalculateNormalMap", + "GrayScaler", + "ICLightModelLoader", + "LightSource" + ], + { + "title_aux": "comfyui's gaffer(ComfyUI native implementation of IC-Light. )" + } + ], + "https://github.com/huagetai/ComfyUI_LightGradient": [ + [ + "ImageGradient", + "MaskGradient" + ], + { + "title_aux": "Light Gradient for ComfyUI" + } + ], + "https://github.com/huchenlei/ComfyUI-IC-Light-Native": [ + [ + "ICLightApplyMaskGrey", + "ICLightAppply", + "VAEEncodeArgMax" + ], + { + "title_aux": "ComfyUI-IC-Light-Native" + } + ], + "https://github.com/huchenlei/ComfyUI-layerdiffuse": [ + [ + "LayeredDiffusionApply", + "LayeredDiffusionCondApply", + "LayeredDiffusionCondJointApply", + "LayeredDiffusionDecode", + "LayeredDiffusionDecodeRGBA", + "LayeredDiffusionDecodeSplit", + "LayeredDiffusionDiffApply", + "LayeredDiffusionJointApply" + ], + { + "title_aux": "ComfyUI-layerdiffuse (layerdiffusion)" + } + ], + "https://github.com/huchenlei/ComfyUI-openpose-editor": [ + [ + "huchenlei.LoadOpenposeJSON" + ], + { + "title_aux": "ComfyUI-openpose-editor" + } + ], + "https://github.com/huchenlei/ComfyUI_DanTagGen": [ + [ + "PromptDanTagGen" + ], + { + "title_aux": "ComfyUI_DanTagGen" + } + ], + "https://github.com/huchenlei/ComfyUI_densediffusion": [ + [ + "DenseDiffusionAddCondNode", + "DenseDiffusionApplyNode" + ], + { + "title_aux": "ComfyUI DenseDiffusion" + } + ], + "https://github.com/huchenlei/ComfyUI_omost": [ + [ + "OmostDenseDiffusionLayoutNode", + "OmostGreedyBagsTextEmbeddingNode", + "OmostLLMChatNode", + "OmostLLMHTTPServerNode", + "OmostLLMLoaderNode", + "OmostLayoutCondNode", + "OmostLoadCanvasConditioningNode", + "OmostLoadCanvasPythonCodeNode", + "OmostRenderCanvasConditioningNode" + ], + { + "title_aux": "ComfyUI_omost" + } + ], + "https://github.com/hughescr/ComfyUI-OpenPose-Keypoint-Extractor": [ + [ + "Openpose Keypoint Extractor" + ], + { + "title_aux": "OpenPose Keypoint Extractor" + } + ], + "https://github.com/hustille/ComfyUI_Fooocus_KSampler": [ + [ + "KSampler With Refiner (Fooocus)" + ], + { + "title_aux": "ComfyUI_Fooocus_KSampler" + } + ], + "https://github.com/hustille/ComfyUI_hus_utils": [ + [ + "3way Prompt Styler", + "Batch State", + "Date Time Format", + "Debug Extra", + "Fetch widget value", + "Text Hash" + ], + { + "title_aux": "hus' utils for ComfyUI" + } + ], + "https://github.com/hwhaocool/ComfyUI-Select-Any": [ + [ + "SelectAnyValues" + ], + { + "title_aux": "ComfyUI-Select-Any" + } + ], + "https://github.com/hylarucoder/ComfyUI-Eagle-PNGInfo": [ + [ + "EagleImageNode", + "SDXLPromptStyler", + "SDXLPromptStylerAdvanced", + "SDXLResolutionPresets" + ], + { + "title_aux": "Eagle PNGInfo" + } + ], + "https://github.com/hyunamy/comfy-ui-on-complete-email-me": [ + [ + "OnCompleteEmailMe", + "OnCompleteWebhook" + ], + { + "title_aux": "Comfy-UI on-complete-email-me" + } + ], + "https://github.com/iFREEGROUP/comfyui-undistort": [ + [ + "IG_LoadCheckerboardImageForCalibrateCamera", + "IG_MatrixAndDistCoefToText", + "IG_Undistort" + ], + { + "title_aux": "comfyui-undistort" + } + ], + "https://github.com/icesun963/ComfyUI_HFDownLoad": [ + [ + "HFDownLoad_Tool" + ], + { + "title_aux": "HFDownLoad Node for ComfyUI" + } + ], + "https://github.com/idrirap/ComfyUI-Lora-Auto-Trigger-Words": [ + [ + "FusionText", + "LoraListNames", + "LoraLoaderAdvanced", + "LoraLoaderStackedAdvanced", + "LoraLoaderStackedVanilla", + "LoraLoaderVanilla", + "LoraTagsOnly", + "Randomizer", + "TagsFormater", + "TagsSelector", + "TextInputBasic" + ], + { + "title_aux": "ComfyUI-Lora-Auto-Trigger-Words" + } + ], + "https://github.com/iemesowum/ComfyUI_IsaacNodes": [ + [ + "I_BinaryAmplitudeGate", + "I_UnmixAudio", + "I_WeightsListToWeights" + ], + { + "author": "Isaac Emesowum", + "description": "This extension offers automatic drums extraction from audio files, as well as a few helper nodes to support my audio synchronization AnimateDiff workflows.", + "nickname": "Isaac's Nodes", + "title": "Isaac's Nodes", + "title_aux": "Isaac's Nodes" + } + ], + "https://github.com/if-ai/ComfyUI-IF_AI_HFDownloaderNode": [ + [ + "IF_HFDownload", + "IF_HFDownloadNode" + ], + { + "title_aux": "ComfyUI-IF_AI_HFDownloaderNode" + } + ], + "https://github.com/if-ai/ComfyUI-IF_AI_WishperSpeechNode": [ + [ + "IF_WhisperSpeech" + ], + { + "title_aux": "ComfyUI-IF_AI_WishperSpeechNode" + } + ], + "https://github.com/if-ai/ComfyUI-IF_AI_tools": [ + [ + "IF_ChatPrompt", + "IF_DisplayText", + "IF_ImagePrompt", + "IF_PromptMkr", + "IF_SaveText", + "IF_saveText" + ], + { + "title_aux": "ComfyUI-IF_AI_tools" + } + ], + "https://github.com/imb101/ComfyUI-FaceSwap": [ + [ + "FaceSwapNode" + ], + { + "title_aux": "FaceSwap" + } + ], + "https://github.com/iwanders/ComfyUI_nodes": [ + [ + "IW_JsonPickItem", + "IW_ModelHook", + "IW_StringConcat", + "IW_StringNode", + "IW_StringPrint", + "IW_StringReplace", + "IW_StringSave", + "IW_TokenizerVocab" + ], + { + "title_aux": "iwanders/ComfyUI_nodes" + } + ], + "https://github.com/jags111/ComfyUI_Jags_Audiotools": [ + [ + "BatchJoinAudio", + "BatchToList", + "BitCrushAudioFX", + "BulkVariation", + "ChorusAudioFX", + "ClippingAudioFX", + "CompressorAudioFX", + "ConcatAudioList", + "ConvolutionAudioFX", + "CutAudio", + "DelayAudioFX", + "DistortionAudioFX", + "DuplicateAudio", + "GainAudioFX", + "GenerateAudioSample", + "GenerateAudioWave", + "GetAudioFromFolderIndex", + "GetSingle", + "GetStringByIndex", + "HighShelfFilter", + "HighpassFilter", + "ImageToSpectral", + "InvertAudioFX", + "JoinAudio", + "LadderFilter", + "LimiterAudioFX", + "ListToBatch", + "LoadAudioDir", + "LoadAudioFile", + "LoadAudioModel (DD)", + "LoadVST3", + "LowShelfFilter", + "LowpassFilter", + "MP3CompressorAudioFX", + "MixAudioTensors", + "NoiseGateAudioFX", + "OTTAudioFX", + "PeakFilter", + "PhaserEffectAudioFX", + "PitchShiftAudioFX", + "PlotSpectrogram", + "PreviewAudioFile", + "PreviewAudioTensor", + "ResampleAudio", + "ReverbAudioFX", + "ReverseAudio", + "SaveAudioTensor", + "SequenceVariation", + "SliceAudio", + "SoundPlayer", + "StretchAudio", + "samplerate" + ], + { + "author": "jags111", + "description": "This extension offers various audio generation tools", + "nickname": "Audiotools", + "title": "Jags_Audiotools", + "title_aux": "Jags_Audiotools" + } + ], + "https://github.com/jags111/ComfyUI_Jags_VectorMagic": [ + [ + "CircularVAEDecode", + "JagsCLIPSeg", + "JagsClipseg", + "JagsCombineMasks", + "SVG", + "YoloSEGdetectionNode", + "YoloSegNode", + "color_drop", + "xy_Tiling_KSampler" + ], + { + "author": "jags111", + "description": "This extension offers various vector manipulation and generation tools", + "nickname": "Jags_VectorMagic", + "title": "Jags_VectorMagic", + "title_aux": "Jags_VectorMagic" + } + ], + "https://github.com/jags111/efficiency-nodes-comfyui": [ + [ + "AnimateDiff Script", + "Apply ControlNet Stack", + "Control Net Stacker", + "Eff. Loader SDXL", + "Efficient Loader", + "HighRes-Fix Script", + "Image Overlay", + "Join XY Inputs of Same Type", + "KSampler (Efficient)", + "KSampler Adv. (Efficient)", + "KSampler SDXL (Eff.)", + "LatentUpscaler", + "LoRA Stack to String converter", + "LoRA Stacker", + "Manual XY Entry Info", + "NNLatentUpscale", + "Noise Control Script", + "Pack SDXL Tuple", + "Tiled Upscaler Script", + "Unpack SDXL Tuple", + "XY Input: Add/Return Noise", + "XY Input: Aesthetic Score", + "XY Input: CFG Scale", + "XY Input: Checkpoint", + "XY Input: Clip Skip", + "XY Input: Control Net", + "XY Input: Control Net Plot", + "XY Input: Denoise", + "XY Input: LoRA", + "XY Input: LoRA Plot", + "XY Input: LoRA Stacks", + "XY Input: Manual XY Entry", + "XY Input: Prompt S/R", + "XY Input: Refiner On/Off", + "XY Input: Sampler/Scheduler", + "XY Input: Seeds++ Batch", + "XY Input: Steps", + "XY Input: VAE", + "XY Plot" + ], + { + "title_aux": "Efficiency Nodes for ComfyUI Version 2.0+" + } + ], + "https://github.com/jakechai/ComfyUI-JakeUpgrade": [ + [ + "Animation Prompt JK", + "Animation Value JK", + "Base Image Parameters Extract JK", + "Base Model Parameters Extract JK", + "Base Model Parameters JK", + "Base Model Pipe Extract JK", + "Base Model Pipe JK", + "CM_BoolBinaryOperation JK", + "CM_BoolToInt JK", + "CM_BoolUnaryOperation JK", + "CM_BreakoutVec2 JK", + "CM_BreakoutVec3 JK", + "CM_BreakoutVec4 JK", + "CM_ComposeVec2 JK", + "CM_ComposeVec3 JK", + "CM_ComposeVec4 JK", + "CM_FloatBinaryCondition JK", + "CM_FloatBinaryOperation JK", + "CM_FloatToInt JK", + "CM_FloatToNumber JK", + "CM_FloatUnaryCondition JK", + "CM_FloatUnaryOperation JK", + "CM_IntBinaryCondition JK", + "CM_IntBinaryOperation JK", + "CM_IntToBool JK", + "CM_IntToFloat JK", + "CM_IntToNumber JK", + "CM_IntUnaryCondition JK", + "CM_IntUnaryOperation JK", + "CM_NumberBinaryCondition JK", + "CM_NumberBinaryOperation JK", + "CM_NumberToFloat JK", + "CM_NumberToInt JK", + "CM_NumberUnaryCondition JK", + "CM_NumberUnaryOperation JK", + "CM_Vec2BinaryCondition JK", + "CM_Vec2BinaryOperation JK", + "CM_Vec2FloatOperation_JK", + "CM_Vec2ToFloatBinaryOperation JK", + "CM_Vec2ToFloatUnaryOperation JK", + "CM_Vec2UnaryCondition JK", + "CM_Vec2UnaryOperation JK", + "CM_Vec3BinaryCondition JK", + "CM_Vec3BinaryOperation JK", + "CM_Vec3FloatOperation_JK", + "CM_Vec3ToFloatBinaryOperation JK", + "CM_Vec3ToFloatUnaryOperation JK", + "CM_Vec3UnaryCondition JK", + "CM_Vec3UnaryOperation JK", + "CM_Vec4BinaryCondition JK", + "CM_Vec4BinaryOperation JK", + "CM_Vec4FloatOperation_JK", + "CM_Vec4ToFloatBinaryOperation JK", + "CM_Vec4ToFloatUnaryOperation JK", + "CM_Vec4UnaryCondition JK", + "CM_Vec4UnaryOperation JK", + "CR Apply ControlNet JK", + "CR Apply Multi-ControlNet JK", + "CR Boolean JK", + "CR Clip Input Switch JK", + "CR Conditioning Input Switch JK", + "CR ControlNet Input Switch JK", + "CR Float Input Switch JK", + "CR Image Input Switch JK", + "CR Impact Pipe Input Switch JK", + "CR Int Input Switch JK", + "CR Latent Input Switch JK", + "CR LoRA Stack JK", + "CR Load LoRA JK", + "CR Mask Input Switch JK", + "CR Model Input Switch JK", + "CR Multi-ControlNet Stack JK", + "CR Pipe Input Switch JK", + "CR SD1.5 Aspect Ratio JK", + "CR SDXL Aspect Ratio JK", + "CR Switch Model and CLIP JK", + "CR Text Input Switch JK", + "CR VAE Input Switch JK", + "Ckpt Loader JK", + "Detailer Parameters JK", + "Embedding Picker JK", + "Embedding Picker Multi JK", + "Evaluate Examples JK", + "Evaluate Floats JK", + "Evaluate Ints JK", + "Evaluate Strings JK", + "HintImageEnchance JK", + "Image Upscale Parameters Extract JK", + "Ksampler Parameters JK", + "Latent Upscale Parameters Extract JK", + "Load Image With Metadata JK", + "Metadata Pipe Extract JK", + "Metadata Pipe JK", + "NodesState JK", + "Noise Injection Parameters JK", + "Orbit Poses JK", + "Pipe End JK", + "Project Setting JK", + "Refine 1 Parameters Extract JK", + "Refine 2 Parameters Extract JK", + "Refine Model Parameters JK", + "Refine Pipe Extract JK", + "Refine Pipe JK", + "Reroute Ckpt JK", + "Reroute List JK", + "Reroute Resize JK", + "Reroute Sampler JK", + "Reroute Upscale JK", + "Reroute Vae JK", + "SDXLPromptStylerAll", + "SDXLPromptStylerHorror", + "SDXLPromptStylerMisc", + "SDXLPromptStylerbyArtist", + "SDXLPromptStylerbyCamera", + "SDXLPromptStylerbyComposition", + "SDXLPromptStylerbyCyberpunkSurrealism", + "SDXLPromptStylerbyDepth", + "SDXLPromptStylerbyDiva", + "SDXLPromptStylerbyEnvironment", + "SDXLPromptStylerbyFantasySetting", + "SDXLPromptStylerbyFilter", + "SDXLPromptStylerbyFocus", + "SDXLPromptStylerbyFooocus", + "SDXLPromptStylerbyImpressionism", + "SDXLPromptStylerbyLighting", + "SDXLPromptStylerbyMarc", + "SDXLPromptStylerbyMileHigh", + "SDXLPromptStylerbyMood", + "SDXLPromptStylerbyMre", + "SDXLPromptStylerbyMythicalCreature", + "SDXLPromptStylerbyOriginal", + "SDXLPromptStylerbyQuantumRealism", + "SDXLPromptStylerbySai", + "SDXLPromptStylerbySteamPunkRealism", + "SDXLPromptStylerbySubject", + "SDXLPromptStylerbySurrealism", + "SDXLPromptStylerbyTheme", + "SDXLPromptStylerbyTimeofDay", + "SDXLPromptStylerbyTwri", + "SDXLPromptStylerbyWyvern", + "SDXLPromptbyCelticArt", + "SDXLPromptbyContemporaryNordicArt", + "SDXLPromptbyFashionArt", + "SDXLPromptbyGothicRevival", + "SDXLPromptbyIrishFolkArt", + "SDXLPromptbyRomanticNationalismArt", + "SDXLPromptbySportsArt", + "SDXLPromptbyStreetArt", + "SDXLPromptbyVikingArt", + "SDXLPromptbyWildlifeArt", + "Sampler Loader JK", + "Save Image with Metadata Flow JK", + "Save Image with Metadata JK", + "Upscale Model Loader JK", + "Upscale Model Parameters Extract JK", + "Upscale Model Parameters JK", + "Vae Loader JK" + ], + { + "title_aux": "ComfyUI-JakeUpgrade" + } + ], + "https://github.com/jamal-alkharrat/ComfyUI_rotate_image": [ + [ + "RotateImage" + ], + { + "title_aux": "ComfyUI_rotate_image" + } + ], + "https://github.com/jamesWalker55/comfyui-p2ldgan": [ + [ + "P2LDGAN" + ], + { + "title_aux": "ComfyUI - P2LDGAN Node" + } + ], + "https://github.com/jamesWalker55/comfyui-various": [ + [ + "BatchLoadImage", + "BatchSaveImage", + "GroupInfoExtractFloat", + "GroupInfoExtractInt", + "GroupLoadBatchImages", + "GroupLoadImage", + "JWDatetimeString", + "JWImageBatchCount", + "JWImageContrast", + "JWImageExtractFromBatch", + "JWImageFlip", + "JWImageLevels", + "JWImageLoadRGB", + "JWImageLoadRGBA", + "JWImageLoadRGBIfExists", + "JWImageMix", + "JWImageResize", + "JWImageResizeByFactor", + "JWImageResizeByLongerSide", + "JWImageResizeByShorterSide", + "JWImageResizeToSquare", + "JWImageSaturation", + "JWImageSaveToPath", + "JWImageSequenceExtractFromBatch", + "JWImageStackChannels", + "JWInfoHashExtractFloat", + "JWInfoHashExtractInteger", + "JWInfoHashExtractString", + "JWInfoHashFromInfoHashList", + "JWInfoHashFromRangedInfo", + "JWInfoHashListExtractStringList", + "JWInfoHashListFromRangedInfo", + "JWInfoHashPrint", + "JWLoadImageSequence", + "JWLoadImagesFromString", + "JWLoopImageSequence", + "JWMaskLikeImageSize", + "JWMaskResize", + "JWMaskSequenceApplyToLatent", + "JWMaskSequenceFromMask", + "JWMaskSequenceJoin", + "JWPrintFloat", + "JWPrintImage", + "JWPrintInteger", + "JWPrintLatent", + "JWPrintMask", + "JWPrintString", + "JWRangedInfoCalculateSubBatch", + "JWReferenceOnly", + "JWSaveImageSequence", + "JWStringListCLIPEncode", + "JWStringListFromString", + "JWStringListFromStrings", + "JWStringListJoin", + "JWStringListRepeat", + "JWStringListToFormatedString", + "JWStringListToString", + "JWUncropCrop", + "JWUncropNewRect", + "JWUncropUncrop", + "JamesLoadImageGroup", + "RAFTEstimate", + "RAFTFlowToImage", + "RAFTLoadFlowFromEXRChannels", + "RCReceiveFloat", + "RCReceiveFloatList", + "RCReceiveInt", + "RCReceiveIntList", + "RCReceiveLatent", + "RCSendLatent" + ], + { + "nodename_pattern": "^JW", + "title_aux": "Various ComfyUI Nodes by Type" + } + ], + "https://github.com/jax-explorer/fast_video_comfyui": [ + [ + "FastImageListToImageBatch" + ], + { + "title_aux": "fast_video_comfyui" + } + ], + "https://github.com/jeffy5/comfyui-faceless-node": [ + [ + "FacelessFaceRestore", + "FacelessFaceSwap", + "FacelessLoadFrames", + "FacelessLoadImageUrl", + "FacelessLoadVideo", + "FacelessLoadVideoUrl", + "FacelessMergeVideos", + "FacelessRemoveBackground", + "FacelessSaveVideo", + "FacelessUploadVideo", + "FacelessVideoFaceRestore", + "FacelessVideoFaceSwap", + "FacelessVideoRemoveBackground" + ], + { + "title_aux": "Faceless Node for ComfyUI" + } + ], + "https://github.com/jesenzhang/ComfyUI_StreamDiffusion": [ + [ + "StreamDiffusion_Loader", + "StreamDiffusion_Sampler" + ], + { + "title_aux": "ComfyUI_StreamDiffusion" + } + ], + "https://github.com/jiaxiangc/ComfyUI-ResAdapter": [ + [ + "ResAdapterLoader" + ], + { + "title_aux": "ResAdapter for ComfyUI" + } + ], + "https://github.com/jitcoder/lora-info": [ + [ + "ImageFromURL", + "LoraInfo" + ], + { + "title_aux": "LoraInfo" + } + ], + "https://github.com/jjkramhoeft/ComfyUI-Jjk-Nodes": [ + [ + "JjkConcat", + "JjkShowText", + "JjkText", + "SDXLRecommendedImageSize" + ], + { + "title_aux": "ComfyUI-Jjk-Nodes" + } + ], + "https://github.com/jkrauss82/ultools-comfyui": [ + [ + "CLIPTextEncodeWithStats", + "OpenPoseEditorAdv", + "SaveImgAdv", + "SolidMaskAdv" + ], + { + "title_aux": "ULTools for ComfyUI" + } + ], + "https://github.com/jojkaart/ComfyUI-sampler-lcm-alternative": [ + [ + "LCMScheduler", + "SamplerLCMAlternative", + "SamplerLCMCycle", + "SamplerLCMDualNoise" + ], + { + "title_aux": "ComfyUI-sampler-lcm-alternative" + } + ], + "https://github.com/jordoh/ComfyUI-Deepface": [ + [ + "DeepfaceExtractFaces", + "DeepfaceVerify" + ], + { + "title_aux": "ComfyUI Deepface" + } + ], + "https://github.com/jroc22/ComfyUI-CSV-prompt-builder": [ + [ + "BuildPromptFromCSV" + ], + { + "title_aux": "ComfyUI-CSV-prompt-builder" + } + ], + "https://github.com/jtrue/ComfyUI-JaRue": [ + [ + "Text2Image_jru", + "YouTube2Prompt_jru" + ], + { + "nodename_pattern": "_jru$", + "title_aux": "ComfyUI-JaRue" + } + ], + "https://github.com/jtydhr88/ComfyUI-LayerDivider": [ + [ + "LayerDivider - Color Base", + "LayerDivider - Divide Layer", + "LayerDivider - Load SAM Mask Generator", + "LayerDivider - Segment Mask" + ], + { + "title_aux": "ComfyUI LayerDivider" + } + ], + "https://github.com/jtydhr88/ComfyUI-Unique3D": [ + [ + "Unique3DLoadPipeline", + "Unique3DRun - Geo Reconstruct", + "Unique3DRun - MVPrediction" + ], + { + "title_aux": "ComfyUI Unique3D" + } + ], + "https://github.com/ka-puna/comfyui-yanc": [ + [ + "YANC.ConcatStrings", + "YANC.FormatDatetimeString", + "YANC.GetWidgetValueString", + "YANC.IntegerCaster", + "YANC.MultilineString", + "YANC.TruncateString" + ], + { + "title_aux": "comfyui-yanc" + } + ], + "https://github.com/kaanyalova/ComfyUI_ExtendedImageFormats": [ + [ + "ExtendedSaveImage" + ], + { + "title_aux": "Extended Image Formats for ComfyUI" + } + ], + "https://github.com/kadirnar/ComfyUI-Transformers": [ + [ + "DepthEstimationInference", + "ImageClassificationPipeline", + "ImageSegmentationPipeline", + "LoadDepthModel", + "ObjectDetectionPipeline" + ], + { + "title_aux": "ComfyUI-Transformers" + } + ], + "https://github.com/kadirnar/ComfyUI-YOLO": [ + [ + "BBoxToCoco", + "BBoxToXYWH", + "BBoxVisNode", + "CocoToNumber", + "ConvertToDict", + "CustomUltralyticsModelLoader", + "GetImageSize", + "ImageResizeAdvanced", + "UltralyticsInference", + "UltralyticsModelLoader", + "UltralyticsVisualization", + "ViewText" + ], + { + "title_aux": "ComfyUI-YOLO" + } + ], + "https://github.com/kale4eat/ComfyUI-path-util": [ + [ + "path_util_PathAbspath", + "path_util_PathBasename", + "path_util_PathDirname", + "path_util_PathExists", + "path_util_PathIsdir", + "path_util_PathIsfile", + "path_util_PathJoin", + "path_util_PathRelpath", + "path_util_PathSplitext" + ], + { + "title_aux": "ComfyUI_demucus" + } + ], + "https://github.com/kale4eat/ComfyUI-speech-dataset-toolkit": [ + [ + "SDT_AudioProperty", + "SDT_ConcatAudio", + "SDT_CutAudio", + "SDT_DemucsApply", + "SDT_DemucsLoader", + "SDT_FasterWhisperListSegments", + "SDT_FasterWhisperLoader", + "SDT_FasterWhisperSegmentProperty", + "SDT_FasterWhisperTextFromSegments", + "SDT_FasterWhisperTranscribe", + "SDT_GriffinLim", + "SDT_JoinAudio", + "SDT_KotobaWhisperListSegments", + "SDT_KotobaWhisperLoaderLong", + "SDT_KotobaWhisperLoaderShort", + "SDT_KotobaWhisperSegmentProperty", + "SDT_KotobaWhisperTranscribeLong", + "SDT_KotobaWhisperTranscribeShort", + "SDT_LFCC", + "SDT_LoadAudio", + "SDT_LoadAudios", + "SDT_MFCC", + "SDT_MakeSilenceAudio", + "SDT_MelSpectrogram", + "SDT_NemoAsrListSegments", + "SDT_NemoAsrListSubwords", + "SDT_NemoAsrLoader", + "SDT_NemoAsrSegmentProperty", + "SDT_NemoAsrSubwordProperty", + "SDT_NemoAsrTranscribe", + "SDT_NueAsrLoader", + "SDT_NueAsrTranscribe", + "SDT_PlayAudio", + "SDT_PlotMelFilterBank", + "SDT_PlotPitch", + "SDT_PlotSpecgram", + "SDT_PlotSpectrogram", + "SDT_PlotWaveForm", + "SDT_ResampleAudio", + "SDT_SaveAudio", + "SDT_SaveAudioWithSequentialNumbering", + "SDT_SilenceAudio", + "SDT_SileroVADApply", + "SDT_SileroVADCollectChunks", + "SDT_SileroVADListTimestamps", + "SDT_SileroVADLoader", + "SDT_SileroVADTimestampProperty", + "SDT_Spectrogram", + "SDT_SpeechMOSLoader", + "SDT_SpeechMOSScore", + "SDT_SplitAudio", + "SDT_TrimAudio", + "SDT_TrimAudioBySample" + ], + { + "title_aux": "ComfyUI-speech-dataset-toolkit" + } + ], + "https://github.com/kale4eat/ComfyUI-string-util": [ + [ + "string_util_Str", + "string_util_StrConcat", + "string_util_StrCount", + "string_util_StrEndsWith", + "string_util_StrEqual", + "string_util_StrFind", + "string_util_StrFormat", + "string_util_StrJoin", + "string_util_StrLen", + "string_util_StrLower", + "string_util_StrLstrip", + "string_util_StrNotEqual", + "string_util_StrReplace", + "string_util_StrRstrip", + "string_util_StrSlice", + "string_util_StrSplit", + "string_util_StrStartsWith", + "string_util_StrStrip", + "string_util_StrUpper" + ], + { + "title_aux": "ComfyUI-string-util" + } + ], + "https://github.com/kale4eat/ComfyUI-text-file-util": [ + [ + "text_file_util_ReadAllLines", + "text_file_util_ReadAllText", + "text_file_util_WriteText", + "text_file_util_WriteTextLines", + "text_file_util_WriteTextWithSequentialNumbering" + ], + { + "title_aux": "ComfyUI-text-file-util" + } + ], + "https://github.com/katalist-ai/comfyUI-nsfw-detection": [ + [ + "NudenetDetector" + ], + { + "title_aux": "comfyUI-nsfw-detection" + } + ], + "https://github.com/kealiu/ComfyUI-S3-Tools": [ + [ + "Load Image From S3", + "Save Image To S3" + ], + { + "title_aux": "ComfyUI Load and Save file to S3" + } + ], + "https://github.com/kealiu/ComfyUI-Zero123-Porting": [ + [ + "Zero123: Image Preprocess", + "Zero123: Image Rotate in 3D" + ], + { + "title_aux": "ComfyUI-Zero123-Porting" + } + ], + "https://github.com/kealiu/ComfyUI-ZeroShot-MTrans": [ + [ + "ZeST: Grayout Subject" + ], + { + "title_aux": "ComfyUI-ZeroShot-MTrans" + } + ], + "https://github.com/kenjiqq/qq-nodes-comfyui": [ + [ + "Any List", + "Any List Iterator", + "Any To Any", + "Axis Pack", + "Axis To Any", + "Axis Unpack", + "Image Accumulator End", + "Image Accumulator Start", + "Load Lines From Text File", + "Slice List", + "Text Splitter", + "XY Grid Helper" + ], + { + "title_aux": "qq-nodes-comfyui" + } + ], + "https://github.com/kft334/Knodes": [ + [ + "Image(s) To Websocket (Base64)", + "ImageOutput", + "Load Image (Base64)", + "Load Images (Base64)" + ], + { + "title_aux": "Knodes" + } + ], + "https://github.com/kijai/ComfyUI-ADMotionDirector": [ + [ + "ADMD_AdditionalModelSelect", + "ADMD_CheckpointLoader", + "ADMD_ComfyModelLoader", + "ADMD_DiffusersLoader", + "ADMD_InitializeTraining", + "ADMD_LoadLora", + "ADMD_MakeBatchList", + "ADMD_SaveLora", + "ADMD_TrainLora", + "ADMD_ValidationSampler", + "ADMD_ValidationSettings" + ], + { + "title_aux": "Animatediff MotionLoRA Trainer" + } + ], + "https://github.com/kijai/ComfyUI-APISR-KJ": [ + [ + "APISR_upscale" + ], + { + "title_aux": "ComfyUI-APISR" + } + ], + "https://github.com/kijai/ComfyUI-BrushNet-Wrapper": [ + [ + "brushnet_ella_loader", + "brushnet_ipadapter_matteo", + "brushnet_model_loader", + "brushnet_sampler", + "brushnet_sampler_ella", + "powerpaint_brushnet_sampler" + ], + { + "title_aux": "ComfyUI-BrushNet-Wrapper" + } + ], + "https://github.com/kijai/ComfyUI-CCSR": [ + [ + "CCSR_Model_Select", + "CCSR_Upscale", + "DownloadAndLoadCCSRModel" + ], + { + "title_aux": "ComfyUI-CCSR" + } + ], + "https://github.com/kijai/ComfyUI-DDColor": [ + [ + "DDColor_Colorize" + ], + { + "title_aux": "ComfyUI-DDColor" + } + ], + "https://github.com/kijai/ComfyUI-DepthAnythingV2": [ + [ + "DepthAnything_V2", + "DownloadAndLoadDepthAnythingV2Model" + ], + { + "title_aux": "ComfyUI-DepthAnythingV2" + } + ], + "https://github.com/kijai/ComfyUI-DiffusionLight": [ + [ + "chrome_ball_to_envmap", + "exposure_to_hdr" + ], + { + "title_aux": "DiffusionLight implementation for ComfyUI" + } + ], + "https://github.com/kijai/ComfyUI-DynamiCrafterWrapper": [ + [ + "DownloadAndLoadCLIPModel", + "DownloadAndLoadCLIPVisionModel", + "DownloadAndLoadDynamiCrafterModel", + "DynamiCrafterBatchInterpolation", + "DynamiCrafterI2V", + "DynamiCrafterLoadInitNoise", + "DynamiCrafterModelLoader", + "ToonCrafterDecode", + "ToonCrafterInterpolation" + ], + { + "title_aux": "ComfyUI-DynamiCrafterWrapper" + } + ], + "https://github.com/kijai/ComfyUI-ELLA-wrapper": [ + [ + "diffusers_model_loader", + "diffusers_sampler", + "ella_model_loader", + "ella_sampler", + "ella_t5_embeds" + ], + { + "title_aux": "ComfyUI-ELLA-wrapper" + } + ], + "https://github.com/kijai/ComfyUI-Florence2": [ + [ + "DownloadAndLoadFlorence2Model", + "Florence2Run" + ], + { + "title_aux": "ComfyUI-Florence2" + } + ], + "https://github.com/kijai/ComfyUI-Geowizard": [ + [ + "geowizard_model_loader", + "geowizard_sampler" + ], + { + "title_aux": "Geowizard depth and normal estimation in ComfyUI" + } + ], + "https://github.com/kijai/ComfyUI-IC-Light": [ + [ + "BackgroundScaler", + "CalculateNormalsFromImages", + "DetailTransfer", + "ICLightConditioning", + "LightSource", + "LoadAndApplyICLightUnet", + "LoadHDRImage" + ], + { + "title_aux": "ComfyUI-IC-Light" + } + ], + "https://github.com/kijai/ComfyUI-KJNodes": [ + [ + "AddLabel", + "AppendInstanceDiffusionTracking", + "BatchCLIPSeg", + "BatchCropFromMask", + "BatchCropFromMaskAdvanced", + "BatchUncrop", + "BatchUncropAdvanced", + "BboxToInt", + "BboxVisualize", + "CameraPoseVisualizer", + "CheckpointPerturbWeights", + "ColorMatch", + "ColorToMask", + "CondPassThrough", + "ConditioningMultiCombine", + "ConditioningSetMaskAndCombine", + "ConditioningSetMaskAndCombine3", + "ConditioningSetMaskAndCombine4", + "ConditioningSetMaskAndCombine5", + "CreateAudioMask", + "CreateFadeMask", + "CreateFadeMaskAdvanced", + "CreateFluidMask", + "CreateGradientFromCoords", + "CreateGradientMask", + "CreateInstanceDiffusionTracking", + "CreateMagicMask", + "CreateShapeImageOnPath", + "CreateShapeMask", + "CreateShapeMaskOnPath", + "CreateTextMask", + "CreateTextOnPath", + "CreateVoronoiMask", + "CrossFadeImages", + "CustomSigmas", + "DownloadAndLoadCLIPSeg", + "DrawInstanceDiffusionTracking", + "DummyLatentOut", + "EmptyLatentImagePresets", + "FilterZeroMasksAndCorrespondingImages", + "FlipSigmasAdjusted", + "FloatConstant", + "FloatToMask", + "FloatToSigmas", + "GLIGENTextBoxApplyBatchCoords", + "GenerateNoise", + "GetImageRangeFromBatch", + "GetImageSizeAndCount", + "GetImagesFromBatchIndexed", + "GetLatentsFromBatchIndexed", + "GetMaskSizeAndCount", + "GradientToFloat", + "GrowMaskWithBlur", + "INTConstant", + "ImageAddMulti", + "ImageAndMaskPreview", + "ImageBatchMulti", + "ImageBatchRepeatInterleaving", + "ImageBatchTestPattern", + "ImageConcanate", + "ImageConcatMulti", + "ImageGrabPIL", + "ImageGridComposite2x2", + "ImageGridComposite3x3", + "ImageNormalize_Neg1_To_1", + "ImagePadForOutpaintMasked", + "ImagePadForOutpaintTargetSize", + "ImagePass", + "ImageResizeKJ", + "ImageTransformByNormalizedAmplitude", + "ImageUpscaleWithModelBatched", + "InjectNoiseToLatent", + "InsertImageBatchByIndexes", + "InsertImagesToBatchIndexed", + "InterpolateCoords", + "Intrinsic_lora_sampling", + "JoinStringMulti", + "JoinStrings", + "LoadAndResizeImage", + "LoadResAdapterNormalization", + "MaskBatchMulti", + "MaskOrImageToWeight", + "MergeImageChannels", + "ModelPassThrough", + "NormalizedAmplitudeToFloatList", + "NormalizedAmplitudeToMask", + "OffsetMask", + "OffsetMaskByNormalizedAmplitude", + "PlotCoordinates", + "PreviewAnimation", + "RemapImageRange", + "RemapMaskRange", + "ReplaceImagesInBatch", + "ResizeMask", + "ReverseImageBatch", + "RoundMask", + "SV3D_BatchSchedule", + "SaveImageWithAlpha", + "ScaleBatchPromptSchedule", + "Sleep", + "SomethingToString", + "SoundReactive", + "SplineEditor", + "SplitBboxes", + "SplitImageChannels", + "StabilityAPI_SD3", + "StableZero123_BatchSchedule", + "StringConstant", + "StringConstantMultiline", + "Superprompt", + "VRAM_Debug", + "WeightScheduleConvert", + "WeightScheduleExtend", + "WidgetToString" + ], + { + "title_aux": "KJNodes for ComfyUI" + } + ], + "https://github.com/kijai/ComfyUI-KwaiKolorsWrapper": [ + [ + "DownloadAndLoadChatGLM3", + "DownloadAndLoadKolorsModel", + "KolorsSampler", + "KolorsTextEncode", + "LoadChatGLM3" + ], + { + "title_aux": "ComfyUI-KwaiKolorsWrapper" + } + ], + "https://github.com/kijai/ComfyUI-LaVi-Bridge-Wrapper": [ + [ + "lavi_bridge_llama_encoder", + "lavi_bridge_t5_encoder", + "lavibridge_model_loader", + "lavibridge_sampler" + ], + { + "title_aux": "ComfyUI-LaVi-Bridge-Wrapper" + } + ], + "https://github.com/kijai/ComfyUI-LivePortraitKJ": [ + [ + "DownloadAndLoadLivePortraitModels", + "LivePortraitProcess" + ], + { + "title_aux": "ComfyUI-LivePortraitKJ" + } + ], + "https://github.com/kijai/ComfyUI-LuminaWrapper": [ + [ + "DownloadAndLoadGemmaModel", + "DownloadAndLoadLuminaModel", + "GemmaSampler", + "LuminaGemmaTextEncode", + "LuminaGemmaTextEncodeArea", + "LuminaT2ISampler", + "LuminaTextAreaAppend" + ], + { + "title_aux": "ComfyUI-LuminaWrapper" + } + ], + "https://github.com/kijai/ComfyUI-Marigold": [ + [ + "ColorizeDepthmap", + "MarigoldDepthEstimation", + "MarigoldDepthEstimationVideo", + "MarigoldDepthEstimation_v2", + "MarigoldDepthEstimation_v2_video", + "MarigoldModelLoader", + "RemapDepth", + "SaveImageOpenEXR" + ], + { + "title_aux": "Marigold depth estimation in ComfyUI" + } + ], + "https://github.com/kijai/ComfyUI-MimicMotionWrapper": [ + [ + "DiffusersScheduler", + "DownloadAndLoadMimicMotionModel", + "MimicMotionDecode", + "MimicMotionGetPoses", + "MimicMotionSampler" + ], + { + "title_aux": "ComfyUI-MimicMotionWrapper" + } + ], + "https://github.com/kijai/ComfyUI-OpenDiTWrapper": [ + [ + "DownloadAndLoadOpenDiTT5Model", + "DownloadAndLoadOpenSoraModel", + "DownloadAndLoadOpenSoraVAE", + "OpenDiTConditioning", + "OpenDiTSampler", + "OpenSoraDecode", + "OpenSoraEncodeReference" + ], + { + "title_aux": "ComfyUI-OpenDiTWrapper" + } + ], + "https://github.com/kijai/ComfyUI-SUPIR": [ + [ + "SUPIR_Upscale", + "SUPIR_conditioner", + "SUPIR_decode", + "SUPIR_encode", + "SUPIR_first_stage", + "SUPIR_model_loader", + "SUPIR_model_loader_v2", + "SUPIR_model_loader_v2_clip", + "SUPIR_sample", + "SUPIR_tiles" + ], + { + "title_aux": "ComfyUI-SUPIR" + } + ], + "https://github.com/kijai/ComfyUI-depth-fm": [ + [ + "Depth_fm" + ], + { + "title_aux": "ComfyUI-depth-fm" + } + ], + "https://github.com/kijai/ComfyUI-moondream": [ + [ + "MoondreamQuery", + "MoondreamQueryCaptions" + ], + { + "title_aux": "ComfyUI-moondream" + } + ], + "https://github.com/kinfolk0117/ComfyUI_GradientDeepShrink": [ + [ + "GradientPatchModelAddDownscale", + "GradientPatchModelAddDownscaleAdvanced" + ], + { + "title_aux": "ComfyUI_GradientDeepShrink" + } + ], + "https://github.com/kinfolk0117/ComfyUI_Pilgram": [ + [ + "Pilgram" + ], + { + "title_aux": "ComfyUI_Pilgram" + } + ], + "https://github.com/kinfolk0117/ComfyUI_SimpleTiles": [ + [ + "DynamicTileMerge", + "DynamicTileSplit", + "TileCalc", + "TileMerge", + "TileSplit" + ], + { + "title_aux": "SimpleTiles" + } + ], + "https://github.com/klinter007/klinter_nodes": [ + [ + "Filter", + "Florence2Captions2IPA", + "PresentString", + "SingleString", + "SizeSelector", + "YellowBus", + "concat" + ], + { + "title_aux": "Klinter_nodes" + } + ], + "https://github.com/knuknX/ComfyUI-Image-Tools": [ + [ + "BatchImagePathLoader", + "ImageBgRemoveProcessor", + "ImageCheveretoUploader", + "ImageStandardResizeProcessor", + "JSONMessageNotifyTool", + "PreviewJSONNode", + "SingleImagePathLoader", + "SingleImageUrlLoader" + ], + { + "title_aux": "ComfyUI-Image-Tools" + } + ], + "https://github.com/kohya-ss/ControlNet-LLLite-ComfyUI": [ + [ + "LLLiteLoader" + ], + { + "title_aux": "ControlNet-LLLite-ComfyUI" + } + ], + "https://github.com/komojini/ComfyUI_SDXL_DreamBooth_LoRA_CustomNodes": [ + [ + "S3 Bucket LoRA", + "S3Bucket_Load_LoRA", + "XL DreamBooth LoRA", + "XLDB_LoRA" + ], + { + "title_aux": "ComfyUI_SDXL_DreamBooth_LoRA_CustomNodes" + } + ], + "https://github.com/komojini/komojini-comfyui-nodes": [ + [ + "BatchCreativeInterpolationNodeDynamicSettings", + "CachedGetter", + "DragNUWAImageCanvas", + "FlowBuilder", + "FlowBuilder (adv)", + "FlowBuilder (advanced)", + "FlowBuilder (advanced) Setter", + "FlowBuilderSetter", + "FlowBuilderSetter (adv)", + "Getter", + "ImageCropByRatio", + "ImageCropByRatioAndResize", + "ImageGetter", + "ImageMerger", + "ImagesCropByRatioAndResizeBatch", + "KSamplerAdvancedCacheable", + "KSamplerCacheable", + "Setter", + "UltimateVideoLoader", + "UltimateVideoLoader (simple)", + "YouTubeVideoLoader" + ], + { + "title_aux": "komojini-comfyui-nodes" + } + ], + "https://github.com/kunieone/ComfyUI_alkaid": [ + [ + "A_EmptyLatentImageLongside", + "A_Face3DSwapper", + "A_FaceCrop", + "A_FacePaste", + "A_GetImageSize", + "A_OpenPosePreprocessor", + "AdapterFace", + "AdapterFaceLoader", + "AdapterStyle", + "AdapterStyleLoader", + "AlkaidLoader", + "ApplyAdapter", + "ApplyControlNet_KPS", + "CombineAdapterPatch", + "KSamplerHires" + ], + { + "title_aux": "ComfyUI_alkaid" + } + ], + "https://github.com/kwaroran/abg-comfyui": [ + [ + "Remove Image Background (abg)" + ], + { + "title_aux": "abg-comfyui" + } + ], + "https://github.com/l20richo/ComfyUI-Azure-Blob-Storage": [ + [ + "DownloadFileBLOB", + "LoadImageBLOB", + "SaveImageBLOB", + "SaveVideoFilesBLOB", + "UploadFileBLOB" + ], + { + "title_aux": "ComfyUI-Azure-Blob-Storage" + } + ], + "https://github.com/laksjdjf/Batch-Condition-ComfyUI": [ + [ + "Batch String", + "CLIP Text Encode (Batch)", + "String Input" + ], + { + "title_aux": "Batch-Condition-ComfyUI" + } + ], + "https://github.com/laksjdjf/LCMSampler-ComfyUI": [ + [ + "SamplerLCM", + "TAESDLoader" + ], + { + "title_aux": "LCMSampler-ComfyUI" + } + ], + "https://github.com/laksjdjf/LoRTnoC-ComfyUI": [ + [ + "LortnocLoader" + ], + { + "title_aux": "LoRTnoC-ComfyUI" + } + ], + "https://github.com/laksjdjf/cd-tuner_negpip-ComfyUI": [ + [ + "CDTuner", + "Negapip", + "Negpip" + ], + { + "title_aux": "cd-tuner_negpip-ComfyUI" + } + ], + "https://github.com/laksjdjf/cgem156-ComfyUI": [ + [ + "GradualLatentSampler", + "LCMSamplerRCFG", + "LoadAestheticShadow", + "PredictAesthetic", + "TCDSampler", + "TextScheduler" + ], + { + "title_aux": "cgem156-ComfyUI\ud83c\udf4c" + } + ], + "https://github.com/laksjdjf/pfg-ComfyUI": [ + [ + "PFG" + ], + { + "title_aux": "pfg-ComfyUI" + } + ], + "https://github.com/larsupb/LoRA-Merger-ComfyUI": [ + [ + "PM LoRA Apply", + "PM LoRA Loader", + "PM LoRA Merger", + "PM LoRA Resizer", + "PM LoRA SVD Merger", + "PM LoRA Save", + "XY: PM LoRA Modes", + "XY: PM LoRA SVD Rank", + "XY: PM LoRA Strengths" + ], + { + "title_aux": "LoRA Power-Merger ComfyUI" + } + ], + "https://github.com/latenightlabs/ComfyUI-LNL": [ + [ + "LNL_FrameSelector", + "LNL_FrameSelectorV2", + "LNL_FrameSelectorV3" + ], + { + "title_aux": "LNL Frame Selector" + } + ], + "https://github.com/leiweiqiang/ComfyUI-TRA": [ + [ + "TclEbSynth", + "TclEbSynthBatch", + "TclExtractFramesFromVideo", + "TclExtractFramesFromVideoFile", + "TclFrames2Video", + "TclSaveVideoFromFrames", + "TclYoloV8Segmentation", + "TclYoloV9Segmentation" + ], + { + "title_aux": "ComfyUI-TRA" + } + ], + "https://github.com/leoleelxh/ComfyUI-LLMs": [ + [ + "\ud83d\uddbc\ufe0f LLMs_Vison_Ali", + "\ud83d\uddbc\ufe0f LLMs_Vison_GLM4", + "\ud83d\uddbc\ufe0f LLMs_Vison_Gemini", + "\ud83d\ude00 LLMs_Chat", + "\ud83d\ude00 LLMs_Chat_GLM4_Only" + ], + { + "title_aux": "ComfyUI-LLMs" + } + ], + "https://github.com/linshier/comfyui-remote-tools": [ + [ + "LoadBase64(js)", + "LoadBase64FromRemote", + "SendBase64ToRemote" + ], + { + "title_aux": "comfyui-remote-tools" + } + ], + "https://github.com/liusida/ComfyUI-AutoCropFaces": [ + [ + "AutoCropFaces" + ], + { + "title_aux": "ComfyUI-AutoCropFaces" + } + ], + "https://github.com/liusida/ComfyUI-B-LoRA": [ + [ + "LoadBLoRA" + ], + { + "title_aux": "ComfyUI-B-LoRA" + } + ], + "https://github.com/liusida/ComfyUI-Debug": [ + [ + "DebugInspectorNode", + "DebugModelInspectorNode", + "DebugModelPrintOutNode" + ], + { + "title_aux": "ComfyUI-Debug" + } + ], + "https://github.com/liusida/ComfyUI-Login": [ + [ + "LoadImageIncognito" + ], + { + "title_aux": "ComfyUI-Login" + } + ], + "https://github.com/liusida/ComfyUI-SD3-nodes": [ + [ + "SD3EmptyLatent", + "SD3LoadCLIPs", + "SD3LoadCheckpoint" + ], + { + "title_aux": "ComfyUI-SD3-nodes" + } + ], + "https://github.com/ljleb/comfy-mecha": [ + [ + "Blocks Mecha Hyper", + "Float Mecha Hyper", + "Lora Mecha Recipe", + "Mecha Deserializer", + "Mecha Merger", + "Mecha Recipe List", + "Mecha Serializer", + "Model Mecha Recipe" + ], + { + "title_aux": "Mecha Merge Node Pack" + } + ], + "https://github.com/lks-ai/ComfyUI-StableAudioSampler": [ + [ + "StableAudioConditioning", + "StableAudioLoadModel", + "StableAudioPrompt", + "StableAudioSampler" + ], + { + "author": "lks-ai", + "description": "A Simple integration of Stable Audio Diffusion with knobs and stuff!", + "nickname": "stableaudio", + "title": "StableAudioSampler", + "title_aux": "ComfyUI Stable Audio Open 1.0 Sampler" + } + ], + "https://github.com/lks-ai/anynode": [ + [ + "AnyNode", + "AnyNodeAnthropic", + "AnyNodeCodeViewer", + "AnyNodeExport", + "AnyNodeGemini", + "AnyNodeLocal" + ], + { + "author": "newsbubbles", + "description": "This single node uses an LLM to generate a functionality based on your request. You can make the node do anything.", + "nickname": "AnyNode", + "title": "AnyNode v0.1.1", + "title_aux": "ComfyUI AnyNode: Any Node you ask for" + } + ], + "https://github.com/lldacing/comfyui-easyapi-nodes": [ + [ + "Base64ToImage", + "Base64ToMask", + "ColorPicker", + "GetImageBatchSize", + "ImageEqual", + "ImageToBase64", + "ImageToBase64Advanced", + "InsightFaceBBOXDetect", + "IntToList", + "IntToNumber", + "JoinList", + "ListMerge", + "LoadImageFromURL", + "LoadImageToBase64", + "LoadMaskFromURL", + "MaskImageToBase64", + "MaskToBase64", + "MaskToBase64Image", + "SDBaseVerNumber", + "SamAutoMaskSEGS", + "ShowBoolean", + "ShowFloat", + "ShowInt", + "ShowNumber", + "ShowString", + "StringToList" + ], + { + "title_aux": "comfyui-easyapi-nodes" + } + ], + "https://github.com/logtd/ComfyUI-FLATTEN": [ + [ + "ApplyFlattenAttentionNode", + "CreateFlowNoiseNode", + "FlattenCheckpointLoaderNode", + "KSamplerFlattenNode", + "TrajectoryNode", + "UnsamplerFlattenNode" + ], + { + "title_aux": "ComfyUI-FLATTEN" + } + ], + "https://github.com/logtd/ComfyUI-InstanceDiffusion": [ + [ + "ApplyScaleUModelNode", + "DownloadInstanceDiffusionModels", + "InstanceDiffusionTrackingPrompt", + "LoadInstanceFusersNode", + "LoadInstancePositionNetModel", + "LoadInstanceScaleUNode" + ], + { + "title_aux": "InstanceDiffusion Nodes" + } + ], + "https://github.com/logtd/ComfyUI-InversedNoise": [ + [ + "CombineNoiseLatentNode", + "MixNoiseNode", + "SamplerInversedEulerNode" + ], + { + "title_aux": "ComfyUI-InversedNoise" + } + ], + "https://github.com/logtd/ComfyUI-RAVE_ATTN": [ + [ + "ApplyRaveAttentionNode", + "AttentionOverrideSD15Node", + "AttentionOverrideSDXLNode" + ], + { + "title_aux": "ComfyUI-RAVE Attention" + } + ], + "https://github.com/logtd/ComfyUI-RefSampling": [ + [ + "ApplyRefContentNode", + "ApplyRefStyleNode", + "ApplyRefUNetNode" + ], + { + "title_aux": "ComfyUI-RefSampling" + } + ], + "https://github.com/logtd/ComfyUI-TrackingNodes": [ + [ + "OpenPoseTrackerNode", + "YOLOTrackerNode" + ], + { + "title_aux": "Tracking Nodes for Videos" + } + ], + "https://github.com/longgui0318/comfyui-common-util": [ + [ + "Added Layer Info To Array", + "Enhanced Random Light Source", + "Float Relay", + "Image Relay", + "Init Layer Info Array", + "Int Relay", + "Layer Image Seleted", + "Layer Images IPAdapter Advanced", + "Layer Info Array Fuse", + "Mask Relay", + "String Relay" + ], + { + "title_aux": "comfyui-common-util" + } + ], + "https://github.com/longgui0318/comfyui-llm-assistant": [ + [ + "Chat With LLM", + "Generate Stable Diffsution Prompt With LLM", + "Translate Text With LLM" + ], + { + "title_aux": "comfyui-llm-assistant" + } + ], + "https://github.com/longgui0318/comfyui-magic-clothing": [ + [ + "Add Magic Clothing Attention", + "Change Pipeline Dtype And Device", + "Change Pixel Value Normalization", + "Diffusers Model Makeup &MC", + "Diffusers Scheduler Loader &MC", + "Load Magic Clothing Adapter", + "Load Magic Clothing Model", + "Load Magic Clothing Pipeline", + "Load Magic Clothing Pipeline With Path", + "RUN Magic Clothing Diffusers Model" + ], + { + "title_aux": "comfyui-magic-clothing" + } + ], + "https://github.com/longgui0318/comfyui-mask-util": [ + [ + "Image Adaptive Crop M&R", + "Image Adaptive Crop With Mask", + "Image Change DType", + "Image Change Device", + "Image Resolution Adaptive With X", + "Image Resolution Limit With 8K", + "Load Image With Name", + "Mask Change DType", + "Mask Change Device", + "Mask Selection Of Masks", + "Model Change Device", + "Model Change Device Repeaters", + "Output Image To Input", + "Split Masks" + ], + { + "title_aux": "comfyui-mask-util" + } + ], + "https://github.com/longgui0318/comfyui-oms-diffusion": [ + [ + "Add Magic Clothing Attention", + "Change Pipeline Dtype And Device", + "Change Pixel Value Normalization", + "Diffusers Model Makeup &MC", + "Diffusers Scheduler Loader &MC", + "Load Magic Clothing Adapter", + "Load Magic Clothing Model", + "Load Magic Clothing Pipeline", + "Load Magic Clothing Pipeline With Path", + "RUN Magic Clothing Diffusers Model" + ], + { + "title_aux": "comfyui-oms-diffusion" + } + ], + "https://github.com/lordgasmic/ComfyUI-Wildcards/raw/master/wildcards.py": [ + [ + "CLIPTextEncodeWithWildcards" + ], + { + "title_aux": "Wildcards" + } + ], + "https://github.com/lordgasmic/comfyui_save_image_with_options": [ + [ + "SaveImageWithOptions" + ], + { + "title_aux": "comfyui_save_image_with_options" + } + ], + "https://github.com/lordgasmic/comfyui_wildcards": [ + [ + "CLIPTextEncodeWithWildcards" + ], + { + "title_aux": "comfyui_wildcards" + } + ], + "https://github.com/lquesada/ComfyUI-Inpaint-CropAndStitch": [ + [ + "InpaintCrop", + "InpaintExtendOutpaint", + "InpaintResize", + "InpaintStitch" + ], + { + "title_aux": "ComfyUI-Inpaint-CropAndStitch" + } + ], + "https://github.com/lquesada/ComfyUI-Prompt-Combinator": [ + [ + "PromptCombinator", + "PromptCombinatorExportGallery", + "PromptCombinatorMerger", + "PromptCombinatorRandomPrompt" + ], + { + "title_aux": "ComfyUI-Prompt-Combinator" + } + ], + "https://github.com/lrzjason/ComfyUIJasonNode/raw/main/SDXLMixSampler.py": [ + [ + "SDXLMixSampler" + ], + { + "title_aux": "ComfyUIJasonNode" + } + ], + "https://github.com/ltdrdata/ComfyUI-Impact-Pack": [ + [ + "AddMask", + "BasicPipeToDetailerPipe", + "BasicPipeToDetailerPipeSDXL", + "BboxDetectorCombined", + "BboxDetectorCombined_v2", + "BboxDetectorForEach", + "BboxDetectorSEGS", + "BitwiseAndMask", + "BitwiseAndMaskForEach", + "CLIPSegDetectorProvider", + "CfgScheduleHookProvider", + "CombineRegionalPrompts", + "CoreMLDetailerHookProvider", + "CustomNoiseDetailerHookProvider", + "DenoiseScheduleHookProvider", + "DenoiseSchedulerDetailerHookProvider", + "DetailerForEach", + "DetailerForEachDebug", + "DetailerForEachDebugPipe", + "DetailerForEachPipe", + "DetailerForEachPipeForAnimateDiff", + "DetailerHookCombine", + "DetailerPipeToBasicPipe", + "EditBasicPipe", + "EditDetailerPipe", + "EditDetailerPipeSDXL", + "EmptySegs", + "FaceDetailer", + "FaceDetailerPipe", + "FromBasicPipe", + "FromBasicPipe_v2", + "FromDetailerPipe", + "FromDetailerPipeSDXL", + "FromDetailerPipe_v2", + "GITSSchedulerFuncProvider", + "ImageListToImageBatch", + "ImageMaskSwitch", + "ImageReceiver", + "ImageSender", + "ImpactAssembleSEGS", + "ImpactCombineConditionings", + "ImpactCompare", + "ImpactConcatConditionings", + "ImpactConditionalBranch", + "ImpactConditionalBranchSelMode", + "ImpactConditionalStopIteration", + "ImpactControlBridge", + "ImpactControlNetApplyAdvancedSEGS", + "ImpactControlNetApplySEGS", + "ImpactControlNetClearSEGS", + "ImpactConvertDataType", + "ImpactCount_Elts_in_SEGS", + "ImpactDecomposeSEGS", + "ImpactDilateMask", + "ImpactDilateMaskInSEGS", + "ImpactDilate_Mask_SEG_ELT", + "ImpactDummyInput", + "ImpactEdit_SEG_ELT", + "ImpactFloat", + "ImpactFrom_SEG_ELT", + "ImpactFrom_SEG_ELT_bbox", + "ImpactFrom_SEG_ELT_crop_region", + "ImpactGaussianBlurMask", + "ImpactGaussianBlurMaskInSEGS", + "ImpactHFTransformersClassifierProvider", + "ImpactIPAdapterApplySEGS", + "ImpactIfNone", + "ImpactImageBatchToImageList", + "ImpactImageInfo", + "ImpactInt", + "ImpactInversedSwitch", + "ImpactIsNotEmptySEGS", + "ImpactKSamplerAdvancedBasicPipe", + "ImpactKSamplerBasicPipe", + "ImpactLatentInfo", + "ImpactLogger", + "ImpactLogicalOperators", + "ImpactMakeImageBatch", + "ImpactMakeImageList", + "ImpactMakeTileSEGS", + "ImpactMinMax", + "ImpactNeg", + "ImpactNodeSetMuteState", + "ImpactQueueTrigger", + "ImpactQueueTriggerCountdown", + "ImpactRemoteBoolean", + "ImpactRemoteInt", + "ImpactSEGSClassify", + "ImpactSEGSConcat", + "ImpactSEGSLabelAssign", + "ImpactSEGSLabelFilter", + "ImpactSEGSOrderedFilter", + "ImpactSEGSPicker", + "ImpactSEGSRangeFilter", + "ImpactSEGSToMaskBatch", + "ImpactSEGSToMaskList", + "ImpactScaleBy_BBOX_SEG_ELT", + "ImpactSchedulerAdapter", + "ImpactSegsAndMask", + "ImpactSegsAndMaskForEach", + "ImpactSetWidgetValue", + "ImpactSimpleDetectorSEGS", + "ImpactSimpleDetectorSEGSPipe", + "ImpactSimpleDetectorSEGS_for_AD", + "ImpactSleep", + "ImpactStringSelector", + "ImpactSwitch", + "ImpactValueReceiver", + "ImpactValueSender", + "ImpactWildcardEncode", + "ImpactWildcardProcessor", + "IterativeImageUpscale", + "IterativeLatentUpscale", + "KSamplerAdvancedProvider", + "KSamplerProvider", + "LatentPixelScale", + "LatentReceiver", + "LatentSender", + "LatentSwitch", + "MMDetDetectorProvider", + "MMDetLoader", + "MaskDetailerPipe", + "MaskListToMaskBatch", + "MaskPainter", + "MaskToSEGS", + "MaskToSEGS_for_AnimateDiff", + "MasksToMaskList", + "MediaPipeFaceMeshToSEGS", + "NoiseInjectionDetailerHookProvider", + "NoiseInjectionHookProvider", + "ONNXDetectorProvider", + "ONNXDetectorSEGS", + "PixelKSampleHookCombine", + "PixelKSampleUpscalerProvider", + "PixelKSampleUpscalerProviderPipe", + "PixelTiledKSampleUpscalerProvider", + "PixelTiledKSampleUpscalerProviderPipe", + "PreviewBridge", + "PreviewBridgeLatent", + "PreviewDetailerHookProvider", + "ReencodeLatent", + "ReencodeLatentPipe", + "RegionalPrompt", + "RegionalSampler", + "RegionalSamplerAdvanced", + "RemoveImageFromSEGS", + "RemoveNoiseMask", + "SAMDetectorCombined", + "SAMDetectorSegmented", + "SAMLoader", + "SEGSDetailer", + "SEGSDetailerForAnimateDiff", + "SEGSLabelFilterDetailerHookProvider", + "SEGSOrderedFilterDetailerHookProvider", + "SEGSPaste", + "SEGSPreview", + "SEGSPreviewCNet", + "SEGSRangeFilterDetailerHookProvider", + "SEGSSwitch", + "SEGSToImageList", + "SEGSUpscaler", + "SEGSUpscalerPipe", + "SegmDetectorCombined", + "SegmDetectorCombined_v2", + "SegmDetectorForEach", + "SegmDetectorSEGS", + "Segs Mask", + "Segs Mask ForEach", + "SegsMaskCombine", + "SegsToCombinedMask", + "SetDefaultImageForSEGS", + "StepsScheduleHookProvider", + "StringListToString", + "SubtractMask", + "SubtractMaskForEach", + "TiledKSamplerProvider", + "ToBasicPipe", + "ToBinaryMask", + "ToDetailerPipe", + "ToDetailerPipeSDXL", + "TwoAdvancedSamplersForMask", + "TwoSamplersForMask", + "TwoSamplersForMaskUpscalerProvider", + "TwoSamplersForMaskUpscalerProviderPipe", + "UltralyticsDetectorProvider", + "UnsamplerDetailerHookProvider", + "UnsamplerHookProvider", + "VariationNoiseDetailerHookProvider", + "WildcardPromptFromString" + ], + { + "author": "Dr.Lt.Data", + "description": "This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler.", + "nickname": "Impact Pack", + "preemptions": [ + "SAMLoader" + ], + "title": "Impact Pack", + "title_aux": "ComfyUI Impact Pack" + } + ], + "https://github.com/ltdrdata/ComfyUI-Inspire-Pack": [ + [ + "AnimeLineArt_Preprocessor_Provider_for_SEGS //Inspire", + "ApplyRegionalIPAdapters //Inspire", + "BindImageListPromptList //Inspire", + "CLIPTextEncodeWithWeight //Inspire", + "CacheBackendData //Inspire", + "CacheBackendDataList //Inspire", + "CacheBackendDataNumberKey //Inspire", + "CacheBackendDataNumberKeyList //Inspire", + "Canny_Preprocessor_Provider_for_SEGS //Inspire", + "ChangeImageBatchSize //Inspire", + "ChangeLatentBatchSize //Inspire", + "CheckpointLoaderSimpleShared //Inspire", + "ColorMapToMasks //Inspire", + "ColorMaskToDepthMask //Inspire", + "Color_Preprocessor_Provider_for_SEGS //Inspire", + "CompositeNoise //Inspire", + "ConcatConditioningsWithMultiplier //Inspire", + "ConditioningStretch //Inspire", + "ConditioningUpscale //Inspire", + "DWPreprocessor_Provider_for_SEGS //Inspire", + "FakeScribblePreprocessor_Provider_for_SEGS //Inspire", + "FloatRange //Inspire", + "FromIPAdapterPipe //Inspire", + "GlobalSampler //Inspire", + "GlobalSeed //Inspire", + "HEDPreprocessor_Provider_for_SEGS //Inspire", + "HyperTile //Inspire", + "IPAdapterModelHelper //Inspire", + "ImageBatchSplitter //Inspire", + "InpaintPreprocessor_Provider_for_SEGS //Inspire", + "KSampler //Inspire", + "KSamplerAdvanced //Inspire", + "KSamplerAdvancedPipe //Inspire", + "KSamplerAdvancedProgress //Inspire", + "KSamplerPipe //Inspire", + "KSamplerProgress //Inspire", + "LatentBatchSplitter //Inspire", + "LeRes_DepthMap_Preprocessor_Provider_for_SEGS //Inspire", + "LineArt_Preprocessor_Provider_for_SEGS //Inspire", + "ListCounter //Inspire", + "LoadImage //Inspire", + "LoadImageListFromDir //Inspire", + "LoadImagesFromDir //Inspire", + "LoadPromptsFromDir //Inspire", + "LoadPromptsFromFile //Inspire", + "LoadSinglePromptFromFile //Inspire", + "LoraBlockInfo //Inspire", + "LoraLoaderBlockWeight //Inspire", + "MakeBasicPipe //Inspire", + "Manga2Anime_LineArt_Preprocessor_Provider_for_SEGS //Inspire", + "MediaPipeFaceMeshDetectorProvider //Inspire", + "MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS //Inspire", + "MeshGraphormerDepthMapPreprocessorProvider_for_SEGS //Inspire", + "MiDaS_DepthMap_Preprocessor_Provider_for_SEGS //Inspire", + "OpenPose_Preprocessor_Provider_for_SEGS //Inspire", + "PromptBuilder //Inspire", + "PromptExtractor //Inspire", + "RGB_HexToHSV //Inspire", + "RandomGeneratorForList //Inspire", + "RandomNoise //Inspire", + "RegionalCFG //Inspire", + "RegionalConditioningColorMask //Inspire", + "RegionalConditioningSimple //Inspire", + "RegionalIPAdapterColorMask //Inspire", + "RegionalIPAdapterEncodedColorMask //Inspire", + "RegionalIPAdapterEncodedMask //Inspire", + "RegionalIPAdapterMask //Inspire", + "RegionalPromptColorMask //Inspire", + "RegionalPromptSimple //Inspire", + "RegionalSeedExplorerColorMask //Inspire", + "RegionalSeedExplorerMask //Inspire", + "RemoveBackendData //Inspire", + "RemoveBackendDataNumberKey //Inspire", + "RemoveControlNet //Inspire", + "RemoveControlNetFromRegionalPrompts //Inspire", + "RetrieveBackendData //Inspire", + "RetrieveBackendDataNumberKey //Inspire", + "ScheduledCFGGuider //Inspire", + "ScheduledPerpNegCFGGuider //Inspire", + "SeedExplorer //Inspire", + "SelectNthMask //Inspire", + "ShowCachedInfo //Inspire", + "StableCascade_CheckpointLoader //Inspire", + "TilePreprocessor_Provider_for_SEGS //Inspire", + "ToIPAdapterPipe //Inspire", + "UnzipPrompt //Inspire", + "WildcardEncode //Inspire", + "XY Input: Lora Block Weight //Inspire", + "ZipPrompt //Inspire", + "Zoe_DepthMap_Preprocessor_Provider_for_SEGS //Inspire" + ], + { + "author": "Dr.Lt.Data", + "description": "This extension provides various nodes to support Lora Block Weight and the Impact Pack.", + "nickname": "Inspire Pack", + "nodename_pattern": "Inspire$", + "title": "Inspire Pack", + "title_aux": "ComfyUI Inspire Pack" + } + ], + "https://github.com/luandev/ComfyUI-CrewAI": [ + [ + "\ud83d\udcceCrewAI Agent", + "\ud83d\udcceCrewAI Agent List", + "\ud83d\udcceCrewAI Crew", + "\ud83d\udcceCrewAI LLM Chat GPT", + "\ud83d\udcceCrewAI LLM Hugging Face", + "\ud83d\udcceCrewAI LLM OpenAI", + "\ud83d\udcceCrewAI Task", + "\ud83d\udcceCrewAI Task List" + ], + { + "title_aux": "ComfyUI CrewAI" + } + ], + "https://github.com/m-sokes/ComfyUI-Sokes-Nodes": [ + [ + "Custom Date Format | sokes \ud83e\uddac", + "Latent Switch x9 | sokes \ud83e\uddac" + ], + { + "title_aux": "ComfyUI Sokes Nodes" + } + ], + "https://github.com/m957ymj75urz/ComfyUI-Custom-Nodes/raw/main/clip-text-encode-split/clip_text_encode_split.py": [ + [ + "RawText", + "RawTextCombine", + "RawTextEncode", + "RawTextReplace" + ], + { + "title_aux": "m957ymj75urz/ComfyUI-Custom-Nodes" + } + ], + "https://github.com/mape/ComfyUI-mape-Helpers": [ + [ + "mape Variable" + ], + { + "author": "mape", + "description": "Various QoL improvements like prompt tweaking, variable assignment, image preview, fuzzy search, error reporting, organizing and node navigation.", + "nickname": "\ud83d\udfe1 mape's helpers", + "title": "mape's helpers", + "title_aux": "mape's helpers" + } + ], + "https://github.com/maracman/ComfyUI-SubjectStyle-CSV": [ + [ + "CSVPromptProcessor" + ], + { + "title_aux": "ComfyUI-SubjectStyle-CSV" + } + ], + "https://github.com/marduk191/comfyui-marnodes": [ + [ + "marduk191_5_text_string", + "marduk191_5way_text_switch", + "marduk191_workflow_settings" + ], + { + "author": "\u02f6marduk191", + "description": "marduk191s nodes.", + "nickname": "marduk191 workflow settings", + "title": "marduk191 workflow settings", + "title_aux": "marduk191 workflow settings" + } + ], + "https://github.com/marhensa/sdxl-recommended-res-calc": [ + [ + "RecommendedResCalc" + ], + { + "title_aux": "Recommended Resolution Calculator" + } + ], + "https://github.com/martijnat/comfyui-previewlatent": [ + [ + "PreviewLatent", + "PreviewLatentAdvanced", + "PreviewLatentXL" + ], + { + "title_aux": "comfyui-previewlatent" + } + ], + "https://github.com/massao000/ComfyUI_aspect_ratios": [ + [ + "Aspect Ratios Node" + ], + { + "title_aux": "ComfyUI_aspect_ratios" + } + ], + "https://github.com/matan1905/ComfyUI-Serving-Toolkit": [ + [ + "DiscordServing", + "ServingInputNumber", + "ServingInputText", + "ServingOutput", + "WebSocketServing" + ], + { + "title_aux": "ComfyUI Serving toolkit" + } + ], + "https://github.com/mav-rik/facerestore_cf": [ + [ + "CropFace", + "FaceRestoreCFWithModel", + "FaceRestoreModelLoader" + ], + { + "title_aux": "Facerestore CF (Code Former)" + } + ], + "https://github.com/mbrostami/ComfyUI-HF": [ + [ + "GPT2Node" + ], + { + "title_aux": "ComfyUI-HF" + } + ], + "https://github.com/mbrostami/ComfyUI-TITrain": [ + [ + "TextualInversionTraining", + "TextualInversionTrainingSDXL" + ], + { + "title_aux": "ComfyUI-TITrain" + } + ], + "https://github.com/mcmonkeyprojects/sd-dynamic-thresholding": [ + [ + "DynamicThresholdingFull", + "DynamicThresholdingSimple" + ], + { + "title_aux": "Stable Diffusion Dynamic Thresholding (CFG Scale Fix)" + } + ], + "https://github.com/meap158/ComfyUI-Background-Replacement": [ + [ + "BackgroundReplacement", + "ImageComposite" + ], + { + "title_aux": "ComfyUI-Background-Replacement" + } + ], + "https://github.com/meap158/ComfyUI-GPU-temperature-protection": [ + [ + "GPUTemperatureProtection" + ], + { + "title_aux": "GPU temperature protection" + } + ], + "https://github.com/meap158/ComfyUI-Prompt-Expansion": [ + [ + "PromptExpansion" + ], + { + "title_aux": "ComfyUI-Prompt-Expansion" + } + ], + "https://github.com/melMass/comfy_mtb": [ + [ + "Animation Builder (mtb)", + "Any To String (mtb)", + "Batch Float (mtb)", + "Batch Float Assemble (mtb)", + "Batch Float Fill (mtb)", + "Batch Make (mtb)", + "Batch Merge (mtb)", + "Batch Shake (mtb)", + "Batch Shape (mtb)", + "Batch Transform (mtb)", + "Bbox (mtb)", + "Bbox From Mask (mtb)", + "Blur (mtb)", + "Color Correct (mtb)", + "Colored Image (mtb)", + "Concat Images (mtb)", + "Crop (mtb)", + "Debug (mtb)", + "Deep Bump (mtb)", + "Export With Ffmpeg (mtb)", + "Face Swap (mtb)", + "Film Interpolation (mtb)", + "Fit Number (mtb)", + "Float To Number (mtb)", + "Get Batch From History (mtb)", + "Image Compare (mtb)", + "Image Premultiply (mtb)", + "Image Remove Background Rembg (mtb)", + "Image Resize Factor (mtb)", + "Image Tile Offset (mtb)", + "Int To Bool (mtb)", + "Int To Number (mtb)", + "Interpolate Clip Sequential (mtb)", + "Latent Lerp (mtb)", + "Load Face Analysis Model (mtb)", + "Load Face Enhance Model (mtb)", + "Load Face Swap Model (mtb)", + "Load Film Model (mtb)", + "Load Image From Url (mtb)", + "Load Image Sequence (mtb)", + "Mask To Image (mtb)", + "Math Expression (mtb)", + "Model Patch Seamless (mtb)", + "Pick From Batch (mtb)", + "Qr Code (mtb)", + "Restore Face (mtb)", + "Save Gif (mtb)", + "Save Image Grid (mtb)", + "Save Image Sequence (mtb)", + "Save Tensors (mtb)", + "Sharpen (mtb)", + "Smart Step (mtb)", + "Stack Images (mtb)", + "String Replace (mtb)", + "Styles Loader (mtb)", + "Text To Image (mtb)", + "Transform Image (mtb)", + "Uncrop (mtb)", + "Unsplash Image (mtb)", + "Vae Decode (mtb)" + ], + { + "nodename_pattern": "\\(mtb\\)$", + "title_aux": "MTB Nodes" + } + ], + "https://github.com/mephisto83/petty-paint-comfyui-node": [ + [ + "PettyImageImageColorToMask", + "PettyPaintAppend", + "PettyPaintApplyLoRAStack", + "PettyPaintBlurs", + "PettyPaintComponent", + "PettyPaintConditioningSetMaskAndCombine", + "PettyPaintConvert", + "PettyPaintCountFiles", + "PettyPaintEnsureDirectory", + "PettyPaintExec", + "PettyPaintFakeConvert", + "PettyPaintFileExists", + "PettyPaintImageColorsToMasks", + "PettyPaintImageCompositeMasked", + "PettyPaintImageDims", + "PettyPaintImageMaskCropper", + "PettyPaintImagePlacement", + "PettyPaintImageSave", + "PettyPaintImageStore", + "PettyPaintImageToMask", + "PettyPaintImagesToMasks", + "PettyPaintJsonMap", + "PettyPaintJsonRead", + "PettyPaintJsonReadArray", + "PettyPaintKSampler", + "PettyPaintKSamplerAdvanced", + "PettyPaintLoRAStack", + "PettyPaintLoadImage", + "PettyPaintLoadImageMasks", + "PettyPaintLoadImages", + "PettyPaintMap", + "PettyPaintMasksToImages", + "PettyPaintNot", + "PettyPaintPassThroughNode", + "PettyPaintProcessor", + "PettyPaintRemoveAddText", + "PettyPaintSDTurboScheduler", + "PettyPaintStoryImage", + "PettyPaintText", + "PettyPaintTexts_to_Conditioning", + "PettyPaintToJson", + "PettyPaintVAEDecode" + ], + { + "title_aux": "petty-paint-comfyui-node" + } + ], + "https://github.com/meshmesh-io/ComfyUI-MeshMesh": [ + [ + "ColorPicker", + "MasksToColoredMasks" + ], + { + "title_aux": "ComfyUI-MeshMesh" + } + ], + "https://github.com/meshmesh-io/mm-comfyui-loopback": [ + [ + "Loop", + "LoopEnd", + "LoopEnd_SEGIMAGE", + "LoopStart", + "LoopStart_SEGIMAGE" + ], + { + "title_aux": "mm-comfyui-loopback" + } + ], + "https://github.com/meshmesh-io/mm-comfyui-megamask": [ + [ + "ColorListMaskToImage", + "FlattenAndCombineMaskImages" + ], + { + "title_aux": "mm-comfyui-megamask" + } + ], + "https://github.com/metncelik/comfyui_met_suite": [ + [ + "BBOXPadding", + "BBOXResize", + "ImageResizeKeepRatio", + "PrimitiveBBOX", + "RaiseError" + ], + { + "title_aux": "comfyui_met_suite" + } + ], + "https://github.com/mihaiiancu/ComfyUI_Inpaint": [ + [ + "InpaintMediapipe" + ], + { + "title_aux": "mihaiiancu/Inpaint" + } + ], + "https://github.com/mikkel/ComfyUI-text-overlay": [ + [ + "Image Text Overlay" + ], + { + "title_aux": "ComfyUI - Text Overlay Plugin" + } + ], + "https://github.com/mikkel/comfyui-mask-boundingbox": [ + [ + "Mask Bounding Box" + ], + { + "title_aux": "ComfyUI - Mask Bounding Box" + } + ], + "https://github.com/mingqizhang/ComfyUI_InSPyResNet_zmq": [ + [ + "INSPY removebg Apply", + "INSPY removebg ModelLoader" + ], + { + "title_aux": "ComfyUI_InSPyResNet_zmq" + } + ], + "https://github.com/mirabarukaso/ComfyUI_Mira": [ + [ + "BooleanListInterpreter1", + "BooleanListInterpreter4", + "BooleanListInterpreter8", + "CanvasCreatorAdvanced", + "CanvasCreatorBasic", + "CanvasCreatorSimple", + "CircleCreator", + "CirclesGenerator", + "CreateCircleMask", + "CreateMaskWithCanvas", + "CreateNestedPNGMask", + "CreateSimpleMask", + "CreateTillingPNGMask", + "CreateWatermarkRemovalMask", + "EightBooleanTrigger", + "EightFloats", + "EvenOrOdd", + "EvenOrOddList", + "FloatListInterpreter1", + "FloatListInterpreter4", + "FloatListInterpreter8", + "FloatMultiplication", + "FourBooleanTrigger", + "FourFloats", + "FunctionSwap", + "IntMultiplication", + "IntSubtraction", + "IntToFloatMultiplication", + "LogicNot", + "NoneToZero", + "NumeralToString", + "OneFloat", + "PngColorMasksToMaskList", + "PngColorMasksToRGB", + "PngColorMasksToString", + "PngColorMasksToStringList", + "PngRectanglesToMask", + "PngRectanglesToMaskList", + "RandomNestedLayouts", + "RandomTillingLayouts", + "SN74HC1G86", + "SN74HC86", + "SN74LVC1G125", + "SeedGenerator", + "SingleBooleanTrigger", + "SixBooleanTrigger", + "StepsAndCfg", + "TextBox", + "TextCombinerSix", + "TextCombinerTwo", + "TextWithBooleanSwitchAndCommonTextInput", + "TwoBooleanTrigger", + "TwoFloats" + ], + { + "title_aux": "ComfyUI_Mira" + } + ], + "https://github.com/modusCell/ComfyUI-dimension-node-modusCell": [ + [ + "DimensionProviderFree modusCell", + "DimensionProviderRatio modusCell", + "String Concat modusCell" + ], + { + "title_aux": "Preset Dimensions" + } + ], + "https://github.com/moyi7712/ComfyUI_Seamless_Patten": [ + [ + "SeamlessApply", + "SeamlessKSampler", + "SeamlessKSamplerAdvanced", + "SeamlessVae" + ], + { + "title_aux": "ComfyUI_Seamless_Patten" + } + ], + "https://github.com/mpiquero7164/ComfyUI-SaveImgPrompt": [ + [ + "Save IMG Prompt" + ], + { + "title_aux": "SaveImgPrompt" + } + ], + "https://github.com/mullakhmetov/comfyui_dynamic_util_nodes": [ + [ + "ConcatStrings", + "FormatString", + "GetFiles", + "LoadImageByPath" + ], + { + "title_aux": "comfyui_dynamic_util_nodes" + } + ], + "https://github.com/muzi12888/ComfyUI-PoseKeypoint-Mask": [ + [ + "Image Brightness", + "Openpose Keypoint Mask" + ], + { + "title_aux": "PoseKeypoint Mask" + } + ], + "https://github.com/my-opencode/ComfyUI_IndustrialMagick": [ + [ + "IndustrialMagick", + "IndustrialMagickImageIngest" + ], + { + "title_aux": "ComfyUI_IndustrialMagick" + } + ], + "https://github.com/my-opencode/ComfyUI_KSamplerTimer": [ + [ + "KSamplerTimer" + ], + { + "author": "Ludovic Anterieur", + "description": "This extension provides a wrapper of the native KSampler which outputs generation time.", + "nickname": "\u23f1", + "title": "KSampler (timer)", + "title_aux": "ComfyUI_KSamplerTimer" + } + ], + "https://github.com/nagolinc/ComfyUI_FastVAEDecorder_SDXL": [ + [ + "FastLatentToImage" + ], + { + "title_aux": "ComfyUI_FastVAEDecorder_SDXL" + } + ], + "https://github.com/nagolinc/comfyui_openai_node": [ + [ + "OpenAINode" + ], + { + "title_aux": "comfyui_openai_node" + } + ], + "https://github.com/natto-maki/ComfyUI-NegiTools": [ + [ + "NegiTools_CompositeImages", + "NegiTools_DepthEstimationByMarigold", + "NegiTools_DetectFaceRotationForInpainting", + "NegiTools_ImageProperties", + "NegiTools_LatentProperties", + "NegiTools_NoiseImageGenerator", + "NegiTools_OpenAiDalle3", + "NegiTools_OpenAiGpt", + "NegiTools_OpenAiGpt4v", + "NegiTools_OpenAiTranslate", + "NegiTools_OpenPoseToPointList", + "NegiTools_PointListToMask", + "NegiTools_RandomImageLoader", + "NegiTools_SaveImageToDirectory", + "NegiTools_SeedGenerator", + "NegiTools_StereoImageGenerator", + "NegiTools_StringFunction" + ], + { + "title_aux": "ComfyUI-NegiTools" + } + ], + "https://github.com/nickve28/ComfyUI-Nich-Utils": [ + [ + "Image from Dir Selector (Nich)", + "Select Text with Regular Expression (Nich)" + ], + { + "title_aux": "ComfyUI Nich Utils" + } + ], + "https://github.com/nicolai256/comfyUI_Nodes_nicolai256/raw/main/yugioh-presets.py": [ + [ + "yugioh_Presets" + ], + { + "title_aux": "comfyUI_Nodes_nicolai256" + } + ], + "https://github.com/ningxiaoxiao/comfyui-NDI": [ + [ + "NDI_LoadImage", + "NDI_SendImage" + ], + { + "title_aux": "comfyui-NDI" + } + ], + "https://github.com/nirbhay-faaya/ImgProcessing_ComfyUI": [ + [ + "ImageConcat", + "ImageCropMultEight", + "ImageCut", + "LightingPreprocessor" + ], + { + "title_aux": "ImgProcessing_ComfyUI" + } + ], + "https://github.com/nirex0/ComfyUI_pytorch_openpose": [ + [ + "pytorch_openpose" + ], + { + "title_aux": "ComfyUI_pytorch_openpose" + } + ], + "https://github.com/nkchocoai/ComfyUI-Dart": [ + [ + "DanbooruTagsTransformerBanTagsFromRegex", + "DanbooruTagsTransformerComposePrompt", + "DanbooruTagsTransformerComposePromptV2", + "DanbooruTagsTransformerDecode", + "DanbooruTagsTransformerDecodeBySplitedParts", + "DanbooruTagsTransformerGenerate", + "DanbooruTagsTransformerGenerateAdvanced", + "DanbooruTagsTransformerGenerationConfig", + "DanbooruTagsTransformerGetAspectRatio", + "DanbooruTagsTransformerLoader", + "DanbooruTagsTransformerRearrangedByAnimagine", + "DanbooruTagsTransformerRemoveTagToken" + ], + { + "title_aux": "ComfyUI-Dart" + } + ], + "https://github.com/nkchocoai/ComfyUI-PromptUtilities": [ + [ + "PromptUtilitiesConstString", + "PromptUtilitiesConstStringMultiLine", + "PromptUtilitiesFormatString", + "PromptUtilitiesJoinStringList", + "PromptUtilitiesLoadPreset", + "PromptUtilitiesLoadPresetAdvanced", + "PromptUtilitiesRandomPreset", + "PromptUtilitiesRandomPresetAdvanced" + ], + { + "title_aux": "ComfyUI-PromptUtilities" + } + ], + "https://github.com/nkchocoai/ComfyUI-SaveImageWithMetaData": [ + [ + "SaveImageWithMetaData" + ], + { + "title_aux": "ComfyUI-SaveImageWithMetaData" + } + ], + "https://github.com/nkchocoai/ComfyUI-SizeFromPresets": [ + [ + "EmptyLatentImageFromPresetsSD15", + "EmptyLatentImageFromPresetsSDXL", + "GetSimilarResolution", + "GetSimilarResolutionEmptyLatent", + "RandomEmptyLatentImageFromPresetsSD15", + "RandomEmptyLatentImageFromPresetsSDXL", + "RandomSizeFromPresetsSD15", + "RandomSizeFromPresetsSDXL", + "SizeFromPresetsSD15", + "SizeFromPresetsSDXL" + ], + { + "title_aux": "ComfyUI-SizeFromPresets" + } + ], + "https://github.com/nkchocoai/ComfyUI-TextOnSegs": [ + [ + "CalcMaxFontSize", + "ExtractDominantColor", + "GetComplementaryColor", + "SegsToRegion", + "TextOnSegsFloodFill" + ], + { + "title_aux": "ComfyUI-TextOnSegs" + } + ], + "https://github.com/noembryo/ComfyUI-noEmbryo": [ + [ + "PromptTermList1", + "PromptTermList2", + "PromptTermList3", + "PromptTermList4", + "PromptTermList5", + "PromptTermList6" + ], + { + "author": "noEmbryo", + "description": "Some useful nodes for ComfyUI", + "nickname": "noEmbryo", + "title": "noEmbryo nodes", + "title_aux": "noEmbryo nodes" + } + ], + "https://github.com/nosiu/comfyui-instantId-faceswap": [ + [ + "FaceEmbed", + "FaceSwapGenerationInpaint", + "FaceSwapSetupPipeline", + "LCMLora" + ], + { + "title_aux": "ComfyUI InstantID Faceswapper" + } + ], + "https://github.com/noxinias/ComfyUI_NoxinNodes": [ + [ + "NoxinChime", + "NoxinPromptLoad", + "NoxinPromptSave", + "NoxinScaledResolution", + "NoxinSimpleMath", + "NoxinSplitPrompt" + ], + { + "title_aux": "ComfyUI_NoxinNodes" + } + ], + "https://github.com/ntc-ai/ComfyUI-DARE-LoRA-Merge": [ + [ + "Apply LoRA", + "DARE Merge LoRA Stack", + "Save LoRA" + ], + { + "title_aux": "ComfyUI - Apply LoRA Stacker with DARE" + } + ], + "https://github.com/ntdviet/comfyui-ext/raw/main/custom_nodes/gcLatentTunnel/gcLatentTunnel.py": [ + [ + "gcLatentTunnel" + ], + { + "title_aux": "ntdviet/comfyui-ext" + } + ], + "https://github.com/nuanarchy/ComfyUI-NuA-BIRD": [ + [ + "Bird_Deblurring_NuA", + "Bird_Denoising_NuA", + "Bird_Inpainting_NuA", + "Bird_Loader_NuA", + "Bird_Non_Uniform_Deblurring_NuA", + "Bird_Super_Resolution_NuA" + ], + { + "title_aux": "ComfyUI-NuA-BIRD" + } + ], + "https://github.com/nuanarchy/ComfyUI-NuA-FlashFace": [ + [ + "FlashFace_Loader_NuA", + "FlashFace_Sampler_NuA" + ], + { + "title_aux": "ComfyUI-NuA-FlashFace" + } + ], + "https://github.com/nullquant/ComfyUI-BrushNet": [ + [ + "BlendInpaint", + "BrushNet", + "BrushNetLoader", + "CutForInpaint", + "PowerPaint", + "PowerPaintCLIPLoader", + "RAUNet", + "Terminal" + ], + { + "author": "nullquant", + "description": "These are custom nodes for ComfyUI native implementation of BrushNet, PowerPaint and RAUNet models", + "nickname": "BrushName nodes", + "title": "BrushNet", + "title_aux": "BrushNet" + } + ], + "https://github.com/olduvai-jp/ComfyUI-HfLoader": [ + [ + "Lora Loader From HF" + ], + { + "title_aux": "ComfyUI-HfLoader" + } + ], + "https://github.com/omar92/ComfyUI-QualityOfLifeSuit_Omar92": [ + [ + "CLIPStringEncode _O", + "Chat completion _O", + "ChatGPT Simple _O", + "ChatGPT _O", + "ChatGPT compact _O", + "Chat_Completion _O", + "Chat_Message _O", + "Chat_Message_fromString _O", + "Concat Text _O", + "ConcatRandomNSP_O", + "Debug String _O", + "Debug Text _O", + "Debug Text route _O", + "Edit_image _O", + "Equation1param _O", + "Equation2params _O", + "GetImage_(Width&Height) _O", + "GetLatent_(Width&Height) _O", + "ImageScaleFactor _O", + "ImageScaleFactorSimple _O", + "LatentUpscaleFactor _O", + "LatentUpscaleFactorSimple _O", + "LatentUpscaleMultiply", + "Note _O", + "RandomNSP _O", + "Replace Text _O", + "String _O", + "Text _O", + "Text2Image _O", + "Trim Text _O", + "VAEDecodeParallel _O", + "combine_chat_messages _O", + "compine_chat_messages _O", + "concat Strings _O", + "create image _O", + "create_image _O", + "debug Completeion _O", + "debug messages_O", + "float _O", + "floatToInt _O", + "floatToText _O", + "int _O", + "intToFloat _O", + "load_openAI _O", + "replace String _O", + "replace String advanced _O", + "saveTextToFile _O", + "seed _O", + "selectLatentFromBatch _O", + "string2Image _O", + "trim String _O", + "variation_image _O" + ], + { + "title_aux": "Quality of life Suit:V2" + } + ], + "https://github.com/opvelll/ComfyUI_TextListProduct": [ + [ + "ProductedString", + "TextListProduct", + "TextListProductWithSingleA", + "TextListProductWithSingleB", + "TextListProductWithSingleBoth" + ], + { + "title_aux": "Comfy UI Text List Product" + } + ], + "https://github.com/osi1880vr/prompt_quill_comfyui": [ + [ + "PromptQuillGenerate", + "PromptQuillGenerateConditioning", + "PromptQuillSail", + "PromptQuillSailConditioning" + ], + { + "title_aux": "ComfyUI_Prompt-Quill" + } + ], + "https://github.com/ostris/ostris_nodes_comfyui": [ + [ + "LLM Pipe Loader - Ostris", + "LLM Prompt Upsampling - Ostris", + "One Seed - Ostris", + "Text Box - Ostris" + ], + { + "nodename_pattern": "- Ostris$", + "title_aux": "Ostris Nodes ComfyUI" + } + ], + "https://github.com/ownimage/ComfyUI-ownimage": [ + [ + "Caching Image Loader" + ], + { + "title_aux": "ComfyUI-ownimage" + } + ], + "https://github.com/oyvindg/ComfyUI-TrollSuite": [ + [ + "BinaryImageMask", + "ImagePadding", + "LoadLastImage", + "RandomMask", + "TransparentImage" + ], + { + "title_aux": "ComfyUI-TrollSuite" + } + ], + "https://github.com/oztrkoguz/ComfyUI_StoryCreator": [ + [ + "Kosmos2SamplerSimple2", + "KosmosLoader2", + "StoryLoader", + "StorySamplerSimple", + "Write2" + ], + { + "title_aux": "ComfyUI StoryCreater" + } + ], + "https://github.com/palant/extended-saveimage-comfyui": [ + [ + "SaveImageExtended" + ], + { + "title_aux": "Extended Save Image for ComfyUI" + } + ], + "https://github.com/palant/image-resize-comfyui": [ + [ + "ImageResize" + ], + { + "title_aux": "Image Resize for ComfyUI" + } + ], + "https://github.com/pamparamm/ComfyUI-vectorscope-cc": [ + [ + "NormalizeLatent", + "VectorscopeCC" + ], + { + "title_aux": "ComfyUI Vectorscope CC" + } + ], + "https://github.com/pamparamm/sd-perturbed-attention": [ + [ + "PerturbedAttention" + ], + { + "title_aux": "Perturbed-Attention Guidance" + } + ], + "https://github.com/pants007/comfy-pants": [ + [ + "CLIPTextEncodeAIO", + "Image Make Square" + ], + { + "title_aux": "pants" + } + ], + "https://github.com/paulo-coronado/comfy_clip_blip_node": [ + [ + "CLIPTextEncodeBLIP", + "CLIPTextEncodeBLIP-2", + "Example" + ], + { + "title_aux": "comfy_clip_blip_node" + } + ], + "https://github.com/philz1337x/ComfyUI-ClarityAI": [ + [ + "Clarity AI Upscaler" + ], + { + "title_aux": "\u2728 Clarity AI - Creative Image Upscaler and Enhancer for ComfyUI" + } + ], + "https://github.com/picturesonpictures/comfy_PoP": [ + [ + "AdaptiveCannyDetector_PoP", + "AnyAspectRatio", + "ConditioningMultiplier_PoP", + "ConditioningNormalizer_PoP", + "DallE3_PoP", + "EfficientAttention", + "LoadImageResizer_PoP", + "LoraStackLoader10_PoP", + "LoraStackLoader_PoP", + "VAEDecoderPoP", + "VAEEncoderPoP" + ], + { + "title_aux": "comfy_PoP" + } + ], + "https://github.com/pkpkTech/ComfyUI-SaveAVIF": [ + [ + "SaveAvif" + ], + { + "title_aux": "ComfyUI-SaveAVIF" + } + ], + "https://github.com/pkpkTech/ComfyUI-TemporaryLoader": [ + [ + "LoadTempCheckpoint", + "LoadTempLoRA", + "LoadTempMultiLoRA" + ], + { + "title_aux": "ComfyUI-TemporaryLoader" + } + ], + "https://github.com/portu-sim/comfyui_bmab": [ + [ + "BMAB Alpha Composit", + "BMAB Basic", + "BMAB Blend", + "BMAB Clip Text Encoder SDXL", + "BMAB Conditioning To Bind", + "BMAB Context", + "BMAB ControlNet", + "BMAB ControlNet IPAdapter", + "BMAB ControlNet Openpose", + "BMAB Crop", + "BMAB Detail Anything", + "BMAB Detect And Mask", + "BMAB Detection Crop", + "BMAB Detector", + "BMAB Edge", + "BMAB Extractor", + "BMAB Face Detailer", + "BMAB Google Gemini Prompt", + "BMAB Import Integrator", + "BMAB Integrator", + "BMAB KSampler", + "BMAB KSamplerHiresFix", + "BMAB KSamplerHiresFixWithUpscaler", + "BMAB KSamplerKohyaDeepShrink", + "BMAB Lama Inpaint", + "BMAB LoRA Loader", + "BMAB Load Image", + "BMAB Load Output Image", + "BMAB Masks To Images", + "BMAB Model To Bind", + "BMAB Noise Generator", + "BMAB Openpose Hand Detailer", + "BMAB Person Detailer", + "BMAB Preview Text", + "BMAB Prompt", + "BMAB Remove Background", + "BMAB Resize By Person", + "BMAB Resize By Ratio", + "BMAB Resize and Fill", + "BMAB SD-WebUI API BMAB Extension", + "BMAB SD-WebUI API ControlNet", + "BMAB SD-WebUI API I2I", + "BMAB SD-WebUI API Server", + "BMAB SD-WebUI API T2I", + "BMAB SD-WebUI API T2I Hires.Fix", + "BMAB Save Image", + "BMAB SeedGenerator", + "BMAB Segment Anything", + "BMAB Simple Hand Detailer", + "BMAB Subframe Hand Detailer", + "BMAB Text", + "BMAB Upscale With Model", + "BMAB Upscaler", + "BMAB Watermark" + ], + { + "title_aux": "comfyui_bmab" + } + ], + "https://github.com/prodogape/ComfyUI-EasyOCR": [ + [ + "Apply EasyOCR" + ], + { + "title_aux": "ComfyUI-EasyOCR" + } + ], + "https://github.com/prodogape/ComfyUI-Minio": [ + [ + "Load Image From Minio", + "Save Image To Minio", + "Set Minio Config" + ], + { + "title_aux": "Comfyui-Minio" + } + ], + "https://github.com/prodogape/ComfyUI-OmDet": [ + [ + "Apply OmDet" + ], + { + "title_aux": "ComfyUI-OmDet" + } + ], + "https://github.com/prodogape/Comfyui-Yolov8-JSON": [ + [ + "Apply Yolov8 Model", + "Apply Yolov8 Model Seg", + "Draw Labelme Json", + "Load Yolov8 Model", + "Load Yolov8 Model From Path", + "Save Labelme Json" + ], + { + "title_aux": "Comfyui-Yolov8-JSON" + } + ], + "https://github.com/pythongosssss/ComfyUI-Custom-Scripts": [ + [ + "CheckpointLoader|pysssss", + "ConstrainImageforVideo|pysssss", + "ConstrainImage|pysssss", + "LoadText|pysssss", + "LoraLoader|pysssss", + "MathExpression|pysssss", + "MultiPrimitive|pysssss", + "PlaySound|pysssss", + "Repeater|pysssss", + "ReroutePrimitive|pysssss", + "SaveText|pysssss", + "ShowText|pysssss", + "StringFunction|pysssss", + "SystemNotification|pysssss" + ], + { + "title_aux": "pythongosssss/ComfyUI-Custom-Scripts" + } + ], + "https://github.com/pythongosssss/ComfyUI-WD14-Tagger": [ + [ + "WD14Tagger|pysssss" + ], + { + "title_aux": "ComfyUI WD 1.4 Tagger" + } + ], + "https://github.com/qwixiwp/queuetools": [ + [ + "load images (queue tools)" + ], + { + "title_aux": "queuetools" + } + ], + "https://github.com/ramyma/A8R8_ComfyUI_nodes": [ + [ + "AttentionCouple", + "AttentionCoupleRegion", + "AttentionCoupleRegions", + "Base64ImageInput", + "Base64ImageOutput" + ], + { + "title_aux": "A8R8 ComfyUI Nodes" + } + ], + "https://github.com/randjtw/advance-aesthetic-score": [ + [ + "Adv_Scoring" + ], + { + "title_aux": "advance-aesthetic-score" + } + ], + "https://github.com/ratulrafsan/Comfyui-SAL-VTON": [ + [ + "SALVTON_Apply", + "SV_random" + ], + { + "title_aux": "Comfyui-SAL-VTON" + } + ], + "https://github.com/rcfcu2000/zhihuige-nodes-comfyui": [ + [ + "Combine ZHGMasks", + "Cover ZHGMasks", + "From ZHG pip", + "GroundingDinoModelLoader (zhihuige)", + "GroundingDinoPIPESegment (zhihuige)", + "GroundingDinoSAMSegment (zhihuige)", + "InvertMask (zhihuige)", + "SAMModelLoader (zhihuige)", + "To ZHG pip", + "ZHG FaceIndex", + "ZHG GetMaskArea", + "ZHG Image Levels", + "ZHG SaveImage", + "ZHG SmoothEdge", + "ZHG UltimateSDUpscale" + ], + { + "title_aux": "zhihuige-nodes-comfyui" + } + ], + "https://github.com/rcsaquino/comfyui-custom-nodes": [ + [ + "BackgroundRemover | rcsaquino", + "VAELoader | rcsaquino", + "VAEProcessor | rcsaquino" + ], + { + "title_aux": "rcsaquino/comfyui-custom-nodes" + } + ], + "https://github.com/receyuki/comfyui-prompt-reader-node": [ + [ + "SDAnyConverter", + "SDBatchLoader", + "SDLoraLoader", + "SDLoraSelector", + "SDParameterExtractor", + "SDParameterGenerator", + "SDPromptMerger", + "SDPromptReader", + "SDPromptSaver", + "SDTypeConverter" + ], + { + "author": "receyuki", + "description": "The ultimate solution for managing image metadata and multi-tool compatibility. ComfyUI node version of the SD Prompt Reader", + "nickname": "SD Prompt Reader", + "title": "SD Prompt Reader", + "title_aux": "SD Prompt Reader" + } + ], + "https://github.com/redhottensors/ComfyUI-Prediction": [ + [ + "AvoidErasePrediction", + "CFGPrediction", + "CharacteristicGuidancePrediction", + "CombinePredictions", + "ConditionedPrediction", + "EarlyMiddleLatePrediction", + "InterpolatePredictions", + "LogSigmas", + "PerpNegPrediction", + "SamplerCustomPrediction", + "ScalePrediction", + "ScaledGuidancePrediction", + "SelectSigmas", + "SplitAtSigma", + "SwitchPredictions" + ], + { + "author": "RedHotTensors", + "description": "Fully customizable Classifer Free Guidance for ComfyUI", + "nickname": "ComfyUI-Prediction", + "title": "ComfyUI-Prediction", + "title_aux": "ComfyUI-Prediction" + } + ], + "https://github.com/rgthree/rgthree-comfy": [ + [], + { + "author": "rgthree", + "description": "A bunch of nodes I created that I also find useful.", + "nickname": "rgthree", + "nodename_pattern": " \\(rgthree\\)$", + "title": "Comfy Nodes", + "title_aux": "rgthree's ComfyUI Nodes" + } + ], + "https://github.com/rhdunn/comfyui-bus-plugin": [ + [ + "ComfyBus.CLIPEncodedPromptBusNode", + "ComfyBus.CheckpointBusNode", + "ComfyBus.ImageBusNode", + "ComfyBus.ImageParameterBusNode", + "ComfyBus.ImageScaleToSideParameterBusNode", + "ComfyBus.ImageSizeBusNode", + "ComfyBus.LatentImageBusNode", + "ComfyBus.LatentImageParameterBusNode", + "ComfyBus.PromptBusNode", + "ComfyBus.PromptSDXLBusNode" + ], + { + "title_aux": "comfyui-bus-plugin" + } + ], + "https://github.com/richinsley/Comfy-LFO": [ + [ + "LFO_Pulse", + "LFO_Sawtooth", + "LFO_Sine", + "LFO_Square", + "LFO_Triangle" + ], + { + "title_aux": "Comfy-LFO" + } + ], + "https://github.com/ricklove/comfyui-ricklove": [ + [ + "RL_Crop_Resize", + "RL_Crop_Resize_Batch", + "RL_Finetune_Analyze", + "RL_Finetune_Analyze_Batch", + "RL_Finetune_Variable", + "RL_Image_Shadow", + "RL_Image_Threshold_Channels", + "RL_Internet_Search", + "RL_LoadImageSequence", + "RL_Optical_Flow_Dip", + "RL_SaveImageSequence", + "RL_Uncrop", + "RL_Warp_Image", + "RL_Zoe_Depth_Map_Preprocessor", + "RL_Zoe_Depth_Map_Preprocessor_Raw_Infer", + "RL_Zoe_Depth_Map_Preprocessor_Raw_Process" + ], + { + "title_aux": "comfyui-ricklove" + } + ], + "https://github.com/risunobushi/comfyUI_FrequencySeparation_RGB-HSV": [ + [ + "FrequencyCombination", + "FrequencyCombinationHSV", + "FrequencySeparation", + "FrequencySeparationHSV" + ], + { + "title_aux": "comfyUI_FrequencySeparation_RGB-HSV" + } + ], + "https://github.com/rklaffehn/rk-comfy-nodes": [ + [ + "RK_CivitAIAddHashes", + "RK_CivitAIMetaChecker" + ], + { + "title_aux": "rk-comfy-nodes" + } + ], + "https://github.com/romeobuilderotti/ComfyUI-PNG-Metadata": [ + [ + "SetMetadataAll", + "SetMetadataString" + ], + { + "title_aux": "ComfyUI PNG Metadata" + } + ], + "https://github.com/ronniebasak/ComfyUI-Tara-LLM-Integration": [ + [ + "TaraAdvancedComposition", + "TaraApiKeyLoader", + "TaraApiKeySaver", + "TaraDaisyChainNode", + "TaraLLMConfig", + "TaraPresetLLMConfig", + "TaraPrompter", + "TaraPrompterAdvanced" + ], + { + "title_aux": "ComfyUI-Tara-LLM-Integration" + } + ], + "https://github.com/royceschultz/ComfyUI-Notifications": [ + [ + "Notif-PlaySound", + "Notif-SystemNotification", + "Notif-UnifiedNotification", + "Notif-Webhook" + ], + { + "title_aux": "ComfyUI-Notifications" + } + ], + "https://github.com/royceschultz/ComfyUI-TranscriptionTools": [ + [ + "TT-AudioSink", + "TT-ConvertVhsAudioToAudio", + "TT-LoadAudio", + "TT-LoadBatch", + "TT-LoadVideoAudio", + "TT-LoadWhisperModel", + "TT-WhisperTranscription", + "TT-WhisperTranscriptionBatch" + ], + { + "title_aux": "ComfyUI-TranscriptionTools" + } + ], + "https://github.com/rui40000/RUI-Nodes": [ + [ + "ABCondition", + "CharacterCount" + ], + { + "title_aux": "RUI-Nodes" + } + ], + "https://github.com/ruiqutech/ComfyUI-RuiquNodes": [ + [ + "EvaluateListMultiple1", + "EvaluateListMultiple3", + "EvaluateListMultiple6", + "EvaluateListMultiple9", + "EvaluateMultiple1", + "EvaluateMultiple3", + "EvaluateMultiple6", + "EvaluateMultiple9", + "ImageDilate", + "ImageErode", + "ListPath", + "MaskDilate", + "MaskErode", + "PreviewMask", + "RangeSplit", + "SaveMask", + "StringAsAny", + "StringConcat1", + "StringConcat3", + "StringConcat6", + "StringConcat9", + "StringPathStem", + "TermsToList", + "VAEDecodeSave" + ], + { + "title_aux": "RuiquNodes for ComfyUI" + } + ], + "https://github.com/runtime44/comfyui_r44_nodes": [ + [ + "Runtime44ColorMatch", + "Runtime44DynamicKSampler", + "Runtime44FilmGrain", + "Runtime44ImageEnhance", + "Runtime44ImageOverlay", + "Runtime44ImageResizer", + "Runtime44ImageToNoise", + "Runtime44IterativeUpscaleFactor", + "Runtime44MaskSampler", + "Runtime44TiledMaskSampler", + "Runtime44Upscaler" + ], + { + "title_aux": "Runtime44 ComfyUI Nodes" + } + ], + "https://github.com/s1dlx/comfy_meh/raw/main/meh.py": [ + [ + "MergingExecutionHelper" + ], + { + "title_aux": "comfy_meh" + } + ], + "https://github.com/saftle/suplex_comfy_nodes": [ + [ + "ControlNet Selector", + "ControlNetOptionalLoader", + "DiffusersSelector", + "SaveImageJPGNoMeta" + ], + { + "title_aux": "Suplex Misc ComfyUI Nodes" + } + ], + "https://github.com/sdfxai/SDFXBridgeForComfyUI": [ + [ + "SDFXClipTextEncode" + ], + { + "title_aux": "SDFXBridgeForComfyUI - ComfyUI Custom Node for SDFX Integration" + } + ], + "https://github.com/seanlynch/comfyui-optical-flow": [ + [ + "Apply optical flow", + "Compute optical flow", + "Visualize optical flow" + ], + { + "title_aux": "ComfyUI Optical Flow" + } + ], + "https://github.com/seanlynch/srl-nodes": [ + [ + "SRL Conditional Interrrupt", + "SRL Eval", + "SRL Filter Image List", + "SRL Format String" + ], + { + "title_aux": "SRL's nodes" + } + ], + "https://github.com/seghier/ComfyUI_LibreTranslate/raw/main/translate_node.py": [ + [ + "LibreTranslate" + ], + { + "title_aux": "ComfyUI_LibreTranslate" + } + ], + "https://github.com/sergekatzmann/ComfyUI_Nimbus-Pack": [ + [ + "AdjustAndRoundDimensions", + "AspectRatioMobileDevices", + "ImageResizeAndCropNode", + "ImageSquareAdapterNode", + "PopularScreenResolutions" + ], + { + "title_aux": "ComfyUI_Nimbus-Pack" + } + ], + "https://github.com/shadowcz007/comfyui-Image-reward": [ + [ + "ImageBatchToList_", + "ImageRewardScore_" + ], + { + "title_aux": "comfyui-Image-reward" + } + ], + "https://github.com/shadowcz007/comfyui-consistency-decoder": [ + [ + "VAEDecodeConsistencyDecoder", + "VAELoaderConsistencyDecoder" + ], + { + "title_aux": "Consistency Decoder" + } + ], + "https://github.com/shadowcz007/comfyui-edit-mask": [ + [ + "EditMask" + ], + { + "title_aux": "comfyui-edit-mask" + } + ], + "https://github.com/shadowcz007/comfyui-liveportrait": [ + [ + "FaceCropInfo", + "LivePortraitNode", + "Retargeting" + ], + { + "title_aux": "comfyui-liveportrait" + } + ], + "https://github.com/shadowcz007/comfyui-mixlab-nodes": [ + [ + "3DImage", + "AppInfo", + "ApplyVisualStylePrompting_", + "AreaToMask", + "AudioPlay", + "CenterImage", + "CkptNames_", + "Color", + "ComparingTwoFrames_", + "CompositeImages_", + "DynamicDelayProcessor", + "EmbeddingPrompt", + "EnhanceImage", + "FaceToMask", + "FeatheredMask", + "FloatSlider", + "FloatingVideo", + "Font", + "GLIGENTextBoxApply_Advanced", + "GetImageSize_", + "GradientImage", + "GridDisplayAndSave", + "GridInput", + "GridOutput", + "ImageColorTransfer", + "ImageCropByAlpha", + "ImageListToBatch_", + "ImagesPrompt_", + "IncrementingListNode_", + "IntNumber", + "JoinWithDelimiter", + "LimitNumber", + "ListSplit_", + "LoadImagesFromPath", + "LoadImagesFromURL", + "LoadImagesToBatch", + "LoraNames_", + "LoraPrompt", + "MaskListMerge_", + "MaskListReplace_", + "MergeLayers", + "MirroredImage", + "MultiplicationNode", + "NewLayer", + "NoiseImage", + "OutlineMask", + "PreviewMask_", + "PromptImage", + "PromptSimplification", + "PromptSlide", + "RandomPrompt", + "ResizeImageMixlab", + "SamplerNames_", + "SaveImageAndMetadata_", + "SaveImageToLocal", + "ScreenShare", + "Seed_", + "ShowLayer", + "SmoothMask", + "SpeechRecognition", + "SpeechSynthesis", + "SplitImage", + "SplitLongMask", + "StyleAlignedBatchAlign_", + "StyleAlignedReferenceSampler_", + "StyleAlignedSampleReferenceLatents_", + "SvgImage", + "SwitchByIndex", + "TESTNODE_", + "TESTNODE_TOKEN", + "TextImage", + "TextInput_", + "TextToNumber", + "TransparentImage", + "VAEDecodeConsistencyDecoder", + "VAELoaderConsistencyDecoder" + ], + { + "title_aux": "comfyui-mixlab-nodes" + } + ], + "https://github.com/shadowcz007/comfyui-sound-lab": [ + [ + "AudioPlay", + "Musicgen_", + "StableAudio_" + ], + { + "title_aux": "comfyui-sound-lab" + } + ], + "https://github.com/shadowcz007/comfyui-ultralytics-yolo": [ + [ + "DetectByLabel" + ], + { + "title_aux": "comfyui-ultralytics-yolo" + } + ], + "https://github.com/shi3z/ComfyUI_Memeplex_DALLE": [ + [ + "DallERender", + "GPT", + "MemeplexCustomSDXLRender", + "MemeplexRender", + "TextInput", + "TextSend" + ], + { + "title_aux": "ComfyUI_Memeplex_DALLE" + } + ], + "https://github.com/shiimizu/ComfyUI-PhotoMaker-Plus": [ + [ + "PhotoMakerEncodePlus", + "PhotoMakerStyles", + "PrepImagesForClipVisionFromPath" + ], + { + "title_aux": "ComfyUI PhotoMaker Plus" + } + ], + "https://github.com/shiimizu/ComfyUI-TiledDiffusion": [ + [ + "NoiseInversion", + "TiledDiffusion", + "VAEDecodeTiled_TiledDiffusion", + "VAEEncodeTiled_TiledDiffusion" + ], + { + "title_aux": "Tiled Diffusion & VAE for ComfyUI" + } + ], + "https://github.com/shiimizu/ComfyUI_smZNodes": [ + [ + "smZ CLIPTextEncode", + "smZ Settings" + ], + { + "title_aux": "smZNodes" + } + ], + "https://github.com/shingo1228/ComfyUI-SDXL-EmptyLatentImage": [ + [ + "SDXL Empty Latent Image" + ], + { + "title_aux": "ComfyUI-SDXL-EmptyLatentImage" + } + ], + "https://github.com/shingo1228/ComfyUI-send-eagle-slim": [ + [ + "Send Eagle with text", + "Send Webp Image to Eagle" + ], + { + "title_aux": "ComfyUI-send-Eagle(slim)" + } + ], + "https://github.com/shobhitic/ComfyUI-PlusMinusTextClip": [ + [ + "PlusMinusTextClip" + ], + { + "title_aux": "PlusMinusTextClip - Single node for Positive and Negative Prompts" + } + ], + "https://github.com/shockz0rz/ComfyUI_InterpolateEverything": [ + [ + "OpenposePreprocessorInterpolate" + ], + { + "title_aux": "InterpolateEverything" + } + ], + "https://github.com/shockz0rz/comfy-easy-grids": [ + [ + "FloatToText", + "GridFloatList", + "GridFloats", + "GridIntList", + "GridInts", + "GridLoras", + "GridStringList", + "GridStrings", + "ImageGridCommander", + "IntToText", + "SaveImageGrid", + "TextConcatenator" + ], + { + "title_aux": "comfy-easy-grids" + } + ], + "https://github.com/sipherxyz/comfyui-art-venture": [ + [ + "AV_AwsBedrockClaudeApi", + "AV_AwsBedrockMistralApi", + "AV_CheckpointMerge", + "AV_CheckpointModelsToParametersPipe", + "AV_CheckpointSave", + "AV_ClaudeApi", + "AV_ControlNetEfficientLoader", + "AV_ControlNetEfficientLoaderAdvanced", + "AV_ControlNetEfficientStacker", + "AV_ControlNetEfficientStackerSimple", + "AV_ControlNetLoader", + "AV_ControlNetPreprocessor", + "AV_LLMApiConfig", + "AV_LLMChat", + "AV_LLMCompletion", + "AV_LLMMessage", + "AV_LoraListLoader", + "AV_LoraListStacker", + "AV_LoraLoader", + "AV_OpenAIApi", + "AV_ParametersPipeToCheckpointModels", + "AV_ParametersPipeToPrompts", + "AV_PromptsToParametersPipe", + "AV_SAMLoader", + "AV_VAELoader", + "AspectRatioSelector", + "BLIPCaption", + "BLIPLoader", + "BooleanPrimitive", + "CheckpointNameSelector", + "ColorBlend", + "ColorCorrect", + "DeepDanbooruCaption", + "DependenciesEdit", + "Fooocus_KSampler", + "Fooocus_KSamplerAdvanced", + "GetBoolFromJson", + "GetFloatFromJson", + "GetIntFromJson", + "GetObjectFromJson", + "GetSAMEmbedding", + "GetTextFromJson", + "ISNetLoader", + "ISNetSegment", + "ImageAlphaComposite", + "ImageApplyChannel", + "ImageExtractChannel", + "ImageGaussianBlur", + "ImageMuxer", + "ImageRepeat", + "ImageScaleDown", + "ImageScaleDownBy", + "ImageScaleDownToSize", + "ImageScaleToMegapixels", + "LaMaInpaint", + "LoadImageAsMaskFromUrl", + "LoadImageFromUrl", + "LoadJsonFromUrl", + "MergeModels", + "NumberScaler", + "OverlayInpaintedImage", + "OverlayInpaintedLatent", + "PrepareImageAndMaskForInpaint", + "QRCodeGenerator", + "RandomFloat", + "RandomInt", + "SAMEmbeddingToImage", + "SDXLAspectRatioSelector", + "SDXLPromptStyler", + "SeedSelector", + "StringToInt", + "StringToNumber" + ], + { + "title_aux": "comfyui-art-venture" + } + ], + "https://github.com/skfoo/ComfyUI-Coziness": [ + [ + "LoraTextExtractor-b1f83aa2", + "MultiLoraLoader-70bf3d77" + ], + { + "title_aux": "ComfyUI-Coziness" + } + ], + "https://github.com/slyt/comfyui-ollama-nodes": [ + [ + "BooleanToString", + "DownloadHuggingfaceModel", + "FloatToString", + "GenerateOllama", + "IntToString", + "ListModels", + "ListToString", + "PullModel" + ], + { + "title_aux": "comfyui-ollama-nodes" + } + ], + "https://github.com/smagnetize/kb-comfyui-nodes": [ + [ + "SingleImageDataUrlLoader" + ], + { + "title_aux": "kb-comfyui-nodes" + } + ], + "https://github.com/smthemex/ComfyUI_AnyDoor": [ + [ + "AnyDoor_LoadModel", + "AnyDoor_img2img" + ], + { + "title_aux": "ComfyUI_AnyDoor" + } + ], + "https://github.com/smthemex/ComfyUI_ChatGLM_API": [ + [ + "Glm_4_9b_Chat", + "Glm_4v_9b", + "Glm_Lcoal_Or_Repo", + "ZhipuaiApi_Character", + "ZhipuaiApi_Txt", + "ZhipuaiApi_img" + ], + { + "title_aux": "ComfyUI_ChatGLM_API" + } + ], + "https://github.com/smthemex/ComfyUI_CustomNet": [ + [ + "CustomNet_Plus" + ], + { + "title_aux": "ComfyUI_CustomNet" + } + ], + "https://github.com/smthemex/ComfyUI_HiDiffusion_Pro": [ + [ + "HI_Diffusers_Model_Loader", + "Hi_Sampler" + ], + { + "title_aux": "ComfyUI_HiDiffusion_Pro" + } + ], + "https://github.com/smthemex/ComfyUI_ID_Animator": [ + [ + "ID_Animator", + "ID_Repo_Choice" + ], + { + "title_aux": "ComfyUI_ID_Animator" + } + ], + "https://github.com/smthemex/ComfyUI_Llama3_8B": [ + [ + "ChatQA_1p5_8b", + "Local_Or_Repo_Choice", + "Meta_Llama3_8B", + "MiniCPM_Llama3_V25" + ], + { + "title_aux": "ComfyUI_Llama3_8B" + } + ], + "https://github.com/smthemex/ComfyUI_MS_Diffusion": [ + [ + "MS_Comic_Type", + "MSdiffusion_Model_Loader", + "MSdiffusion_Sampler" + ], + { + "title_aux": "ComfyUI_MS_Diffusion" + } + ], + "https://github.com/smthemex/ComfyUI_ParlerTTS": [ + [ + "PromptToAudio" + ], + { + "title_aux": "ComfyUI_ParlerTTS" + } + ], + "https://github.com/smthemex/ComfyUI_Pic2Story": [ + [ + "Pic2Story" + ], + { + "title_aux": "ComfyUI_Pic2Story" + } + ], + "https://github.com/smthemex/ComfyUI_Pipeline_Tool": [ + [ + "Pipeline_Tool" + ], + { + "title_aux": "ComfyUI_Pipeline_Tool" + } + ], + "https://github.com/smthemex/ComfyUI_Pops": [ + [ + "Imgae_To_Path", + "Pops_Prior_Embedding", + "Pops_Repo_Choice", + "Pops_Sampler" + ], + { + "title_aux": "ComfyUI_Pops" + } + ], + "https://github.com/smthemex/ComfyUI_StableAudio_Open": [ + [ + "StableAudio_Open", + "Use_LocalModel_Or_Repo" + ], + { + "title_aux": "ComfyUI_StableAudio_Open" + } + ], + "https://github.com/smthemex/ComfyUI_StoryDiffusion": [ + [ + "Comic_Type", + "Pre_Translate_prompt", + "Storydiffusion_Model_Loader", + "Storydiffusion_Sampler" + ], + { + "title_aux": "ComfyUI_StoryDiffusion" + } + ], + "https://github.com/smthemex/ComfyUI_Streamv2v_Plus": [ + [ + "Load_Stream", + "Text2IMG", + "Video2Video", + "WebCam2Video" + ], + { + "title_aux": "ComfyUI_Streamv2v_Plus" + } + ], + "https://github.com/space-nuko/ComfyUI-Disco-Diffusion": [ + [ + "DiscoDiffusion_DiscoDiffusion", + "DiscoDiffusion_DiscoDiffusionExtraSettings", + "DiscoDiffusion_GuidedDiffusionLoader", + "DiscoDiffusion_OpenAICLIPLoader" + ], + { + "title_aux": "Disco Diffusion" + } + ], + "https://github.com/space-nuko/ComfyUI-OpenPose-Editor": [ + [ + "Nui.OpenPoseEditor" + ], + { + "title_aux": "OpenPose Editor" + } + ], + "https://github.com/space-nuko/nui-suite": [ + [ + "Nui.DynamicPromptsTextGen", + "Nui.FeelingLuckyTextGen", + "Nui.OutputString" + ], + { + "title_aux": "nui suite" + } + ], + "https://github.com/spacepxl/ComfyUI-Florence-2": [ + [ + "Florence2", + "Florence2Postprocess", + "Florence2PostprocessAll", + "LoadFlorence2Model" + ], + { + "title_aux": "ComfyUI-Florence-2" + } + ], + "https://github.com/spacepxl/ComfyUI-HQ-Image-Save": [ + [ + "LoadEXR", + "LoadEXRFrames", + "LoadLatentEXR", + "SaveEXR", + "SaveEXRFrames", + "SaveLatentEXR", + "SaveTiff" + ], + { + "title_aux": "ComfyUI-HQ-Image-Save" + } + ], + "https://github.com/spacepxl/ComfyUI-Image-Filters": [ + [ + "AdainFilterLatent", + "AdainImage", + "AdainLatent", + "AlphaClean", + "AlphaMatte", + "BatchAlign", + "BatchAverageImage", + "BatchAverageUnJittered", + "BatchNormalizeImage", + "BatchNormalizeLatent", + "BetterFilmGrain", + "BilateralFilterImage", + "BlurImageFast", + "BlurMaskFast", + "ClampOutliers", + "ColorMatchImage", + "ConvertNormals", + "DifferenceChecker", + "DilateErodeMask", + "EnhanceDetail", + "ExposureAdjust", + "FrequencyCombine", + "FrequencySeparate", + "GameOfLife", + "GuidedFilterAlpha", + "GuidedFilterImage", + "ImageConstant", + "ImageConstantHSV", + "InstructPixToPixConditioningAdvanced", + "JitterImage", + "Keyer", + "LatentNormalizeShuffle", + "LatentStats", + "MedianFilterImage", + "NormalMapSimple", + "OffsetLatentImage", + "PrintSigmas", + "RelightSimple", + "RemapRange", + "RestoreDetail", + "SharpenFilterLatent", + "ShuffleChannels", + "Tonemap", + "UnJitterImage", + "UnTonemap", + "VisualizeLatents" + ], + { + "title_aux": "ComfyUI-Image-Filters" + } + ], + "https://github.com/spacepxl/ComfyUI-RAVE": [ + [ + "ConditioningDebug", + "ImageGridCompose", + "ImageGridDecompose", + "KSamplerRAVE", + "LatentGridCompose", + "LatentGridDecompose" + ], + { + "title_aux": "ComfyUI-RAVE" + } + ], + "https://github.com/spacepxl/ComfyUI-StyleGan": [ + [ + "BatchAverageStyleGANLatents", + "BlendStyleGANLatents", + "GenerateStyleGANLatent", + "LoadStyleGAN", + "StyleGANInversion", + "StyleGANLatentFromBatch", + "StyleGANSampler" + ], + { + "title_aux": "ComfyUI-StyleGan" + } + ], + "https://github.com/spinagon/ComfyUI-seam-carving": [ + [ + "SeamCarving" + ], + { + "title_aux": "ComfyUI-seam-carving" + } + ], + "https://github.com/spinagon/ComfyUI-seamless-tiling": [ + [ + "CircularVAEDecode", + "MakeCircularVAE", + "OffsetImage", + "SeamlessTile" + ], + { + "title_aux": "Seamless tiling Node for ComfyUI" + } + ], + "https://github.com/spro/comfyui-mirror": [ + [ + "LatentMirror" + ], + { + "title_aux": "Latent Mirror node for ComfyUI" + } + ], + "https://github.com/ssitu/ComfyUI_UltimateSDUpscale": [ + [ + "UltimateSDUpscale", + "UltimateSDUpscaleCustomSample", + "UltimateSDUpscaleNoUpscale" + ], + { + "title_aux": "UltimateSDUpscale" + } + ], + "https://github.com/ssitu/ComfyUI_fabric": [ + [ + "FABRICPatchModel", + "FABRICPatchModelAdv", + "KSamplerAdvFABRICAdv", + "KSamplerFABRIC", + "KSamplerFABRICAdv" + ], + { + "title_aux": "ComfyUI fabric" + } + ], + "https://github.com/ssitu/ComfyUI_restart_sampling": [ + [ + "KRestartSampler", + "KRestartSamplerAdv", + "KRestartSamplerCustom", + "KRestartSamplerSimple", + "RestartSampler", + "RestartScheduler" + ], + { + "title_aux": "Restart Sampling" + } + ], + "https://github.com/ssitu/ComfyUI_roop": [ + [ + "RoopImproved", + "roop" + ], + { + "title_aux": "ComfyUI roop" + } + ], + "https://github.com/stavsap/comfyui-ollama": [ + [ + "OllamaGenerate", + "OllamaGenerateAdvance", + "OllamaVision" + ], + { + "title_aux": "ComfyUI Ollama" + } + ], + "https://github.com/storyicon/comfyui_musev_evolved": [ + [ + "AnimationZoom (comfyui_musev_evolved)", + "ImageSelector (comfyui_musev_evolved)", + "MuseVImg2Vid V1 (comfyui_musev_evolved)", + "MuseVPredictor V1 (comfyui_musev_evolved)" + ], + { + "author": "infguo", + "title_aux": "ComfyUI MuseV Evolved" + } + ], + "https://github.com/storyicon/comfyui_segment_anything": [ + [ + "GroundingDinoModelLoader (segment anything)", + "GroundingDinoSAMSegment (segment anything)", + "InvertMask (segment anything)", + "IsMaskEmpty", + "SAMModelLoader (segment anything)" + ], + { + "title_aux": "segment anything" + } + ], + "https://github.com/strimmlarn/ComfyUI_Strimmlarns_aesthetic_score": [ + [ + "AesthetlcScoreSorter", + "CalculateAestheticScore", + "LoadAesteticModel", + "ScoreToNumber" + ], + { + "title_aux": "ComfyUI_Strimmlarns_aesthetic_score" + } + ], + "https://github.com/styler00dollar/ComfyUI-deepcache": [ + [ + "DeepCache" + ], + { + "title_aux": "ComfyUI-deepcache" + } + ], + "https://github.com/styler00dollar/ComfyUI-sudo-latent-upscale": [ + [ + "SudoLatentUpscale" + ], + { + "title_aux": "ComfyUI-sudo-latent-upscale" + } + ], + "https://github.com/sugarkwork/comfyui_cohere": [ + [ + "SimpleCohereNode" + ], + { + "title_aux": "comfyui_cohere" + } + ], + "https://github.com/sugarkwork/comfyui_tag_fillter": [ + [ + "TagFilter", + "TagMerger", + "TagRemover", + "TagReplace", + "TagSwitcher" + ], + { + "title_aux": "comfyui_tag_filter" + } + ], + "https://github.com/superyoman/comfyui_lumaAPI": [ + [ + "LUMA_API_YoC", + "LUMA_API_result_YoC" + ], + { + "title_aux": "comfyui_lumaAPI" + } + ], + "https://github.com/syllebra/bilbox-comfyui": [ + [ + "BilboXLut", + "BilboXPhotoPrompt", + "BilboXVignette" + ], + { + "title_aux": "BilboX's ComfyUI Custom Nodes" + } + ], + "https://github.com/sylym/comfy_vid2vid": [ + [ + "CheckpointLoaderSimpleSequence", + "DdimInversionSequence", + "KSamplerSequence", + "LoadImageMaskSequence", + "LoadImageSequence", + "LoraLoaderSequence", + "SetLatentNoiseSequence", + "TrainUnetSequence", + "VAEEncodeForInpaintSequence" + ], + { + "title_aux": "Vid2vid" + } + ], + "https://github.com/szhublox/ambw_comfyui": [ + [ + "Auto Merge Block Weighted", + "CLIPMergeSimple", + "CheckpointSave", + "ModelMergeBlocks", + "ModelMergeSimple" + ], + { + "title_aux": "Auto-MBW" + } + ], + "https://github.com/taabata/Comfy_Syrian_Falcon_Nodes/raw/main/SyrianFalconNodes.py": [ + [ + "CompositeImage", + "KSamplerAlternate", + "KSamplerPromptEdit", + "KSamplerPromptEditAndAlternate", + "LoopBack", + "QRGenerate", + "WordAsImage" + ], + { + "title_aux": "Syrian Falcon Nodes" + } + ], + "https://github.com/taabata/LCM_Inpaint-Outpaint_Comfy": [ + [ + "ComfyNodesToSaveCanvas", + "FloatNumber", + "FreeU_LCM", + "ImageDims", + "ImageOutputToComfyNodes", + "ImageResize", + "ImageShuffle", + "ImageSwitch", + "LCMGenerate", + "LCMGenerate_ReferenceOnly", + "LCMGenerate_SDTurbo", + "LCMGenerate_img2img", + "LCMGenerate_img2img_IPAdapter", + "LCMGenerate_img2img_controlnet", + "LCMGenerate_inpaintv2", + "LCMGenerate_inpaintv3", + "LCMLoader", + "LCMLoader_RefInpaint", + "LCMLoader_ReferenceOnly", + "LCMLoader_SDTurbo", + "LCMLoader_controlnet", + "LCMLoader_controlnet_inpaint", + "LCMLoader_img2img", + "LCMLoraLoader_inpaint", + "LCMLoraLoader_ipadapter", + "LCMLora_inpaint", + "LCMLora_inpaintV2", + "LCMLora_ipadapter", + "LCMT2IAdapter", + "LCM_IPAdapter", + "LCM_IPAdapter_inpaint", + "LCM_outpaint_prep", + "LoadImageNode_LCM", + "Loader_SegmindVega", + "OutpaintCanvasTool", + "SaveImage_Canvas", + "SaveImage_LCM", + "SaveImage_Puzzle", + "SaveImage_PuzzleV2", + "SegmindVega", + "SettingsSwitch", + "stitch" + ], + { + "title_aux": "LCM_Inpaint-Outpaint_Comfy" + } + ], + "https://github.com/talesofai/comfyui-browser": [ + [ + "DifyTextGenerator //Browser", + "LoadImageByUrl //Browser", + "SelectInputs //Browser", + "UploadToRemote //Browser", + "XyzPlot //Browser" + ], + { + "title_aux": "ComfyUI Browser" + } + ], + "https://github.com/teward/ComfyUI-Helper-Nodes": [ + [ + "HelperNodes_CfgScale", + "HelperNodes_CheckpointSelector", + "HelperNodes_MultilineStringLiteral", + "HelperNodes_Prompt", + "HelperNodes_SDXLCommonResolutions", + "HelperNodes_SamplerSelector", + "HelperNodes_SaveImage", + "HelperNodes_SchedulerSelector", + "HelperNodes_SeedSelector", + "HelperNodes_Steps", + "HelperNodes_StringLiteral", + "HelperNodes_VAESelector", + "HelperNodes_WidthHeight" + ], + { + "title_aux": "ComfyUI-Helper-Nodes" + } + ], + "https://github.com/theUpsider/ComfyUI-Logic": [ + [ + "Bool-\ud83d\udd2c", + "Compare-\ud83d\udd2c", + "DebugPrint-\ud83d\udd2c", + "Float-\ud83d\udd2c", + "If ANY return A else B-\ud83d\udd2c", + "Int-\ud83d\udd2c", + "String-\ud83d\udd2c" + ], + { + "title_aux": "ComfyUI-Logic" + } + ], + "https://github.com/theUpsider/ComfyUI-Styles_CSV_Loader": [ + [ + "Load Styles CSV" + ], + { + "title_aux": "Styles CSV Loader Extension for ComfyUI" + } + ], + "https://github.com/thecooltechguy/ComfyUI-MagicAnimate": [ + [ + "MagicAnimate", + "MagicAnimateModelLoader" + ], + { + "title_aux": "ComfyUI-MagicAnimate" + } + ], + "https://github.com/thecooltechguy/ComfyUI-Stable-Video-Diffusion": [ + [ + "SVDDecoder", + "SVDModelLoader", + "SVDSampler", + "SVDSimpleImg2Vid" + ], + { + "title_aux": "ComfyUI Stable Video Diffusion" + } + ], + "https://github.com/tiankuan93/ComfyUI-V-Express": [ + [ + "Load_Audio_Path", + "Load_Audio_Path_From_Video", + "Load_Image_Path", + "Load_Kps_Path", + "Load_Kps_Path_From_Video", + "Load_Video_Path", + "VEINTConstant", + "VEPreview_Video", + "VEStringConstant", + "V_Express_Loader", + "V_Express_Sampler" + ], + { + "title_aux": "V-Express: Conditional Dropout for Progressive Training of Portrait Video Generation" + } + ], + "https://github.com/tianlang0704/ComfyUI-StableProjectorzBridge": [ + [ + "ProjectorzControlnetInput", + "ProjectorzControlnetParameter", + "ProjectorzInitInput", + "ProjectorzOutput", + "ProjectorzParameter", + "ProjectorzStringToFloat", + "ProjectorzStringToInt" + ], + { + "title_aux": "Stable Projectorz Bridge" + } + ], + "https://github.com/time-river/ComfyUI-CLIPSeg/raw/main/custom_nodes/clipseg.py": [ + [ + "CLIPSeg", + "CombineSegMasks" + ], + { + "title_aux": "CLIPSeg" + } + ], + "https://github.com/tmagara/ComfyUI-Prediction-Boost": [ + [ + "PredictionBoost" + ], + { + "title_aux": "ComfyUI-Prediction-Boost" + } + ], + "https://github.com/tocubed/ComfyUI-AudioReactor": [ + [ + "AudioFrameTransformBeats", + "AudioFrameTransformShadertoy", + "AudioLoadPath", + "Shadertoy" + ], + { + "title_aux": "ComfyUI-AudioReactor" + } + ], + "https://github.com/tooldigital/ComfyUI-Yolo-Cropper": [ + [ + "ToolYoloCropper" + ], + { + "title_aux": "Easy automatic (square) image cropper using Yolo" + } + ], + "https://github.com/toxicwind/ComfyUI-TTools": [ + [ + "TTools Extract JSON", + "TTools SD3 Resolution Solver" + ], + { + "title_aux": "TTools for ComfyUI" + } + ], + "https://github.com/toyxyz/ComfyUI_toyxyz_test_nodes": [ + [ + "CaptureWebcam", + "ImageResize_Padding", + "LatentDelay", + "LoadWebcamImage", + "SaveImagetoPath" + ], + { + "title_aux": "ComfyUI_toyxyz_test_nodes" + } + ], + "https://github.com/traugdor/ComfyUI-quadMoons-nodes": [ + [ + "quadmoonCLIPTextEncode", + "quadmoonChangeBackground", + "quadmoonConvertBoolToString", + "quadmoonConvertFloatToString", + "quadmoonConvertIntToString", + "quadmoonConvertNormalizeHW", + "quadmoonConvertNumberToString", + "quadmoonINTConditionalOperation", + "quadmoonKSampler", + "quadmoonKSamplerAdvanced", + "quadmoonLoadConfigs", + "quadmoonModelLoader", + "quadmoonSaveNeg", + "quadmoonSavePrompt", + "quadmoonSmartNeg", + "quadmoonSmartPrompt", + "quadmoonThebutton" + ], + { + "author": "quadmoon (https://github.com/traugdor)", + "description": "These are just some nodes I wanted and couldn't find where anyone else had made them yet.", + "nickname": "quadmoon's Nodes", + "title": "quadmoon's ComfyUI nodes", + "title_aux": "quadmoon's ComfyUI nodes" + } + ], + "https://github.com/tritant/ComfyUI_CreaPrompt": [ + [ + "CreaPrompt", + "CreaPrompt List" + ], + { + "title_aux": "ComfyUI-CreaPrompt" + } + ], + "https://github.com/trojblue/trNodes": [ + [ + "trColorCorrection", + "trLayering", + "trRouter", + "trRouterLonger" + ], + { + "title_aux": "trNodes" + } + ], + "https://github.com/trumanwong/ComfyUI-NSFW-Detection": [ + [ + "NSFWDetection" + ], + { + "title_aux": "ComfyUI-NSFW-Detection" + } + ], + "https://github.com/tsogzark/ComfyUI-load-image-from-url": [ + [ + "LoadImageFromUrlOrPath" + ], + { + "title_aux": "ComfyUI-load-image-from-url" + } + ], + "https://github.com/ttulttul/ComfyUI-Iterative-Mixer": [ + [ + "Batch Unsampler", + "Iterative Mixing KSampler", + "Iterative Mixing KSampler Advanced", + "IterativeMixingSampler", + "IterativeMixingScheduler", + "IterativeMixingSchedulerAdvanced", + "Latent Batch Comparison Plot", + "Latent Batch Statistics Plot", + "MixingMaskGenerator" + ], + { + "title_aux": "ComfyUI Iterative Mixing Nodes" + } + ], + "https://github.com/ttulttul/ComfyUI-Tensor-Operations": [ + [ + "Fast Image to Noise", + "Image Match Normalize", + "Latent Match Normalize" + ], + { + "title_aux": "ComfyUI-Tensor-Operations" + } + ], + "https://github.com/tudal/Hakkun-ComfyUI-nodes/raw/main/hakkun_nodes.py": [ + [ + "Any Converter", + "Calculate Upscale", + "Image Resize To Height", + "Image Resize To Width", + "Image size to string", + "Load Random Image", + "Load Text", + "Multi Text Merge", + "Prompt Parser", + "Random Line", + "Random Line 4" + ], + { + "title_aux": "Hakkun-ComfyUI-nodes" + } + ], + "https://github.com/tusharbhutt/Endless-Nodes": [ + [ + "ESS Aesthetic Scoring", + "ESS Combo Parameterizer", + "ESS Combo Parameterizer & Prompts", + "ESS Eight Input Text Switch", + "ESS Float to Integer", + "ESS Float to Number", + "ESS Float to String", + "ESS Float to X", + "ESS Image Reward", + "ESS Image Saver with JSON", + "ESS Integer to Float", + "ESS Integer to Number", + "ESS Integer to String", + "ESS Integer to X", + "ESS Number to Float", + "ESS Number to Integer", + "ESS Number to String", + "ESS Number to X", + "ESS Parameterizer", + "ESS Parameterizer & Prompts", + "ESS Six Float Output", + "ESS Six Input Text Switch", + "ESS Six Integer IO Switch", + "ESS Six Integer IO Widget", + "ESS String to Float", + "ESS String to Integer", + "ESS String to Num", + "ESS String to X", + "\u267e\ufe0f\ud83c\udf0a\u2728 Image Saver with JSON" + ], + { + "author": "BiffMunky", + "description": "A small set of nodes I created for various numerical and text inputs. Features image saver with ability to have JSON saved to separate folder, parameter collection nodes, two aesthetic scoring models, switches for text and numbers, and conversion of string to numeric and vice versa.", + "nickname": "\u267e\ufe0f\ud83c\udf0a\u2728", + "title": "Endless \ufe0f\ud83c\udf0a\u2728 Nodes", + "title_aux": "Endless \ufe0f\ud83c\udf0a\u2728 Nodes" + } + ], + "https://github.com/twri/sdxl_prompt_styler": [ + [ + "SDXLPromptStyler", + "SDXLPromptStylerAdvanced" + ], + { + "title_aux": "SDXL Prompt Styler" + } + ], + "https://github.com/ty0x2333/ComfyUI-Dev-Utils": [ + [ + "TY_ExecutionTime", + "TY_UploadAnything", + "TY_UrlDownload" + ], + { + "title_aux": "ComfyUI-Dev-Utils" + } + ], + "https://github.com/uarefans/ComfyUI-Fans": [ + [ + "Fans Prompt Styler Negative", + "Fans Prompt Styler Positive", + "Fans Styler", + "Fans Text Concatenate" + ], + { + "title_aux": "ComfyUI-Fans" + } + ], + "https://github.com/uetuluk/comfyui-webcam-node": [ + [ + "webcam_capture_node" + ], + { + "title_aux": "comfyui-webcam-node" + } + ], + "https://github.com/unwdef/unwdef-nodes-comfyui": [ + [ + "RandomTextFromMultiline", + "RandomizeLoras", + "RandomizeLorasStack", + "TextMultilineWithVariables" + ], + { + "title_aux": "unwdef-nodes" + } + ], + "https://github.com/vanche1212/ComfyUI-ZMG-Nodes": [ + [ + "VC_Load_Video_Path_Unified_Output", + "VC_Load_Video_Upload_Unified_Output", + "VC_Video_Combine_Unified_Output", + "Waveform2Audio", + "\ud83d\ude0bAPI Request Node", + "\ud83d\ude0bJSON Parser Node", + "\ud83d\ude0bOld Photo Colorization Node", + "\ud83d\ude0bOllama Request Node", + "\ud83d\ude0bSave Image Unified Output" + ], + { + "title_aux": "ZMG PLUGIN" + } + ], + "https://github.com/vanillacode314/SimpleWildcardsComfyUI": [ + [ + "SimpleConcat", + "SimpleWildcard" + ], + { + "author": "VanillaCode314", + "description": "A simple wildcard node for ComfyUI. Can also be used a style prompt node.", + "nickname": "Simple Wildcard", + "title": "Simple Wildcard", + "title_aux": "Simple Wildcard" + } + ], + "https://github.com/veighnsche/comfyui_gr85": [ + [ + "GR85_ContainsWord", + "GR85_ElementsConcatenator", + "GR85_ImageDimensionResizer", + "GR85_ImageSizer", + "GR85_InsertCharacter", + "GR85_LlmEnhancer", + "GR85_NextSeed", + "GR85_RandomAtmLocOutfit", + "GR85_RandomRatio", + "GR85_RandomTitleCharacter", + "GR85_RandomWildcardTagPicker", + "GR85_ShowText", + "GR85_StrSafe", + "GR85_TagInjector" + ], + { + "title_aux": "comfyui_gr85" + } + ], + "https://github.com/victorchall/comfyui_webcamcapture": [ + [ + "WebcamCapture" + ], + { + "title_aux": "Comfyui Webcam capture node" + } + ], + "https://github.com/vienteck/ComfyUI-Chat-GPT-Integration": [ + [ + "ChatGptPrompt" + ], + { + "title_aux": "ComfyUI-Chat-GPT-Integration" + } + ], + "https://github.com/violet-chen/comfyui-psd2png": [ + [ + "Psd2Png" + ], + { + "title_aux": "comfyui-psd2png" + } + ], + "https://github.com/viperyl/ComfyUI-BiRefNet": [ + [ + "BiRefNet" + ], + { + "title_aux": "ComfyUI-BiRefNet" + } + ], + "https://github.com/viperyl/ComfyUI-RGT": [ + [ + "RGT_Upscale" + ], + { + "title_aux": "ComfyUI-RGT" + } + ], + "https://github.com/vivax3794/ComfyUI-Sub-Nodes": [ + [ + "VIV_Default", + "VIV_Subgraph", + "VIV_Subgraph_Inputs", + "VIV_Subgraph_Outputs" + ], + { + "title_aux": "ComfyUI-Sub-Nodes" + } + ], + "https://github.com/vivax3794/ComfyUI-Vivax-Nodes": [ + [ + "Any String", + "Chunk Up", + "Get Chunk", + "Inspect", + "Join Chunks", + "Model From URL" + ], + { + "title_aux": "ComfyUI-Vivax-Nodes" + } + ], + "https://github.com/vsevolod-oparin/comfyui-kandinsky22": [ + [ + "comfy-kandinsky22-decoder-loader", + "comfy-kandinsky22-hint-combiner", + "comfy-kandinsky22-image-encoder", + "comfy-kandinsky22-img-latents", + "comfy-kandinsky22-latents", + "comfy-kandinsky22-movq-decoder", + "comfy-kandinsky22-positive-text-encoder", + "comfy-kandinsky22-prior-averaging-2", + "comfy-kandinsky22-prior-averaging-3", + "comfy-kandinsky22-prior-averaging-4", + "comfy-kandinsky22-prior-loader", + "comfy-kandinsky22-text-encoder", + "comfy-kandinsky22-unet-decoder" + ], + { + "title_aux": "Kandinsky 2.2 ComfyUI Plugin" + } + ], + "https://github.com/vxinhao/color2rgb/raw/main/color2rgb.py": [ + [ + "color2RGB" + ], + { + "title_aux": "color2rgb" + } + ], + "https://github.com/wTechArtist/ComfyUI-CustomNodes": [ + [ + "Image Blending Mode Mask" + ], + { + "title_aux": "ComfyUI-CustomNodes" + } + ], + "https://github.com/wallish77/wlsh_nodes": [ + [ + "Alternating KSampler (WLSH)", + "Build Filename String (WLSH)", + "CLIP +/- w/Text Unified (WLSH)", + "CLIP Positive-Negative (WLSH)", + "CLIP Positive-Negative XL (WLSH)", + "CLIP Positive-Negative XL w/Text (WLSH)", + "CLIP Positive-Negative w/Text (WLSH)", + "Checkpoint Loader w/Name (WLSH)", + "Empty Latent by Pixels (WLSH)", + "Empty Latent by Ratio (WLSH)", + "Empty Latent by Size (WLSH)", + "Generate Border Mask (WLSH)", + "Grayscale Image (WLSH)", + "Image Load with Metadata (WLSH)", + "Image Save with Prompt (WLSH)", + "Image Save with Prompt File (WLSH)", + "Image Save with Prompt/Info (WLSH)", + "Image Save with Prompt/Info File (WLSH)", + "Image Scale By Factor (WLSH)", + "Image Scale by Shortside (WLSH)", + "KSamplerAdvanced (WLSH)", + "Multiply Integer (WLSH)", + "Outpaint to Image (WLSH)", + "Prompt Weight (WLSH)", + "Quick Resolution Multiply (WLSH)", + "Resolutions by Ratio (WLSH)", + "SDXL Quick Empty Latent (WLSH)", + "SDXL Quick Image Scale (WLSH)", + "SDXL Resolutions (WLSH)", + "SDXL Steps (WLSH)", + "Save Positive Prompt(WLSH)", + "Save Prompt (WLSH)", + "Save Prompt/Info (WLSH)", + "Seed and Int (WLSH)", + "Seed to Number (WLSH)", + "Simple Pattern Replace (WLSH)", + "Simple String Combine (WLSH)", + "Time String (WLSH)", + "Upscale by Factor with Model (WLSH)", + "VAE Encode for Inpaint w/Padding (WLSH)" + ], + { + "title_aux": "wlsh_nodes" + } + ], + "https://github.com/web3nomad/ComfyUI_Invisible_Watermark": [ + [ + "InvisibleWatermarkEncode" + ], + { + "title_aux": "ComfyUI Invisible Watermark" + } + ], + "https://github.com/whatbirdisthat/cyberdolphin": [ + [ + "\ud83d\udc2c Gradio ChatInterface", + "\ud83d\udc2c OpenAI Advanced", + "\ud83d\udc2c OpenAI Compatible", + "\ud83d\udc2c OpenAI DALL\u00b7E", + "\ud83d\udc2c OpenAI Simple" + ], + { + "title_aux": "cyberdolphin" + } + ], + "https://github.com/whmc76/ComfyUI-Openpose-Editor-Plus": [ + [ + "CDL.OpenPoseEditorPlus" + ], + { + "title_aux": "ComfyUI-Openpose-Editor-Plus" + } + ], + "https://github.com/wmatson/easy-comfy-nodes": [ + [ + "EZAssocDictNode", + "EZAssocImgNode", + "EZAssocStrNode", + "EZEmptyDictNode", + "EZHttpPostNode", + "EZLoadImgBatchFromUrlsNode", + "EZLoadImgFromUrlNode", + "EZRemoveImgBackground", + "EZS3Uploader" + ], + { + "title_aux": "easy-comfy-nodes" + } + ], + "https://github.com/wolfden/ComfyUi_PromptStylers": [ + [ + "SDXLPromptStylerAll", + "SDXLPromptStylerHorror", + "SDXLPromptStylerMisc", + "SDXLPromptStylerbyArtist", + "SDXLPromptStylerbyCamera", + "SDXLPromptStylerbyComposition", + "SDXLPromptStylerbyCyberpunkSurrealism", + "SDXLPromptStylerbyDepth", + "SDXLPromptStylerbyEnvironment", + "SDXLPromptStylerbyFantasySetting", + "SDXLPromptStylerbyFilter", + "SDXLPromptStylerbyFocus", + "SDXLPromptStylerbyImpressionism", + "SDXLPromptStylerbyLighting", + "SDXLPromptStylerbyMileHigh", + "SDXLPromptStylerbyMood", + "SDXLPromptStylerbyMythicalCreature", + "SDXLPromptStylerbyOriginal", + "SDXLPromptStylerbyQuantumRealism", + "SDXLPromptStylerbySteamPunkRealism", + "SDXLPromptStylerbySubject", + "SDXLPromptStylerbySurrealism", + "SDXLPromptStylerbyTheme", + "SDXLPromptStylerbyTimeofDay", + "SDXLPromptStylerbyWyvern", + "SDXLPromptbyCelticArt", + "SDXLPromptbyContemporaryNordicArt", + "SDXLPromptbyFashionArt", + "SDXLPromptbyGothicRevival", + "SDXLPromptbyIrishFolkArt", + "SDXLPromptbyRomanticNationalismArt", + "SDXLPromptbySportsArt", + "SDXLPromptbyStreetArt", + "SDXLPromptbyVikingArt", + "SDXLPromptbyWildlifeArt" + ], + { + "title_aux": "SDXL Prompt Styler (customized version by wolfden)" + } + ], + "https://github.com/wolfden/ComfyUi_String_Function_Tree": [ + [ + "StringFunction" + ], + { + "title_aux": "ComfyUi_String_Function_Tree" + } + ], + "https://github.com/wsippel/comfyui_ws/raw/main/sdxl_utility.py": [ + [ + "SDXLResolutionPresets" + ], + { + "title_aux": "SDXLResolutionPresets" + } + ], + "https://github.com/wujm424606/ComfyUi-Ollama-YN": [ + [ + "OllamaGenerate", + "OllamaGenerateAdvance", + "OllamaSpecialGenerateAdvance", + "OllamaVision" + ], + { + "title_aux": "ComfyUi-Ollama-YN" + } + ], + "https://github.com/wutipong/ComfyUI-TextUtils": [ + [ + "Text Utils - Join N-Elements of String List", + "Text Utils - Join String List", + "Text Utils - Join Strings", + "Text Utils - Split String to List" + ], + { + "title_aux": "ComfyUI-TextUtils" + } + ], + "https://github.com/wwwins/ComfyUI-Simple-Aspect-Ratio": [ + [ + "SimpleAspectRatio" + ], + { + "title_aux": "ComfyUI-Simple-Aspect-Ratio" + } + ], + "https://github.com/xXAdonesXx/NodeGPT": [ + [ + "AppendAgent", + "Assistant", + "Chat", + "ChatGPT", + "CombineInput", + "Conditioning", + "CostumeAgent_1", + "CostumeAgent_2", + "CostumeMaster_1", + "Critic", + "DisplayString", + "DisplayTextAsImage", + "EVAL", + "Engineer", + "Executor", + "GroupChat", + "Image_generation_Conditioning", + "LM_Studio", + "LoadAPIconfig", + "LoadTXT", + "MemGPT", + "Memory_Excel", + "Model_1", + "Ollama", + "Output2String", + "Planner", + "Scientist", + "TextCombine", + "TextGeneration", + "TextGenerator", + "TextInput", + "TextOutput", + "UserProxy", + "llama-cpp", + "llava", + "oobaboogaOpenAI" + ], + { + "title_aux": "NodeGPT" + } + ], + "https://github.com/xiaoxiaodesha/hd_node": [ + [ + "Combine HDMasks", + "Cover HDMasks", + "HD FaceIndex", + "HD GetMaskArea", + "HD Image Levels", + "HD SmoothEdge", + "HD UltimateSDUpscale" + ], + { + "title_aux": "hd-nodes-comfyui" + } + ], + "https://github.com/xliry/ComfyUI_SendDiscord": [ + [ + "SendDiscord" + ], + { + "title_aux": "ComfyUI_SendDiscord" + } + ], + "https://github.com/xuhongming251/ComfyUI-GPEN": [ + [ + "FaceEnhancement" + ], + { + "title_aux": "ComfyUI-GPEN" + } + ], + "https://github.com/xuhongming251/ComfyUI-MuseTalkUtils": [ + [ + "MuseTalkPostprocess", + "MuseTalkPreprocess", + "MuseTalkTrain", + "MuseTalkTrainPreprocess", + "MuseTalkUncropMask" + ], + { + "title_aux": "ComfyUI-MuseTalkUtils" + } + ], + "https://github.com/yffyhk/comfyui_auto_danbooru": [ + [ + "GetDanbooru", + "TagEncode" + ], + { + "title_aux": "comfyui_auto_danbooru" + } + ], + "https://github.com/yiwangsimple/ComfyUI_GroqChat": [ + [ + "GroqChatNode", + "PaliGemmaPixelProse" + ], + { + "title_aux": "comfy-groqchat" + } + ], + "https://github.com/yolain/ComfyUI-Easy-Use": [ + [ + "dynamicThresholdingFull", + "easy LLLiteLoader", + "easy XYInputs: CFG Scale", + "easy XYInputs: Checkpoint", + "easy XYInputs: ControlNet", + "easy XYInputs: Denoise", + "easy XYInputs: Lora", + "easy XYInputs: ModelMergeBlocks", + "easy XYInputs: NegativeCond", + "easy XYInputs: NegativeCondList", + "easy XYInputs: PositiveCond", + "easy XYInputs: PositiveCondList", + "easy XYInputs: PromptSR", + "easy XYInputs: Sampler/Scheduler", + "easy XYInputs: Seeds++ Batch", + "easy XYInputs: Steps", + "easy XYPlot", + "easy XYPlotAdvanced", + "easy a1111Loader", + "easy applyBrushNet", + "easy applyFooocusInpaint", + "easy applyInpaint", + "easy applyPowerPaint", + "easy boolean", + "easy cascadeKSampler", + "easy cascadeLoader", + "easy ckptNames", + "easy cleanGpuUsed", + "easy clearCacheAll", + "easy clearCacheKey", + "easy comfyLoader", + "easy compare", + "easy controlnetLoader", + "easy controlnetLoaderADV", + "easy controlnetNames", + "easy controlnetStack", + "easy convertAnything", + "easy detailerFix", + "easy dynamiCrafterLoader", + "easy float", + "easy fullCascadeKSampler", + "easy fullLoader", + "easy fullkSampler", + "easy globalSeed", + "easy hiresFix", + "easy humanSegmentation", + "easy hunyuanDiTLoader", + "easy icLightApply", + "easy if", + "easy imageBatchToImageList", + "easy imageChooser", + "easy imageColorMatch", + "easy imageConcat", + "easy imageCount", + "easy imageCropFromMask", + "easy imageDetailTransfer", + "easy imageInsetCrop", + "easy imageInterrogator", + "easy imageListToImageBatch", + "easy imagePixelPerfect", + "easy imageRatio", + "easy imageRemBg", + "easy imageSave", + "easy imageScaleDown", + "easy imageScaleDownBy", + "easy imageScaleDownToSize", + "easy imageSize", + "easy imageSizeByLongerSide", + "easy imageSizeBySide", + "easy imageSplitGrid", + "easy imageSplitList", + "easy imageSwitch", + "easy imageToBase64", + "easy imageToMask", + "easy imageUncropFromBBOX", + "easy imagesSplitImage", + "easy injectNoiseToLatent", + "easy instantIDApply", + "easy instantIDApplyADV", + "easy int", + "easy ipadapterApply", + "easy ipadapterApplyADV", + "easy ipadapterApplyEmbeds", + "easy ipadapterApplyEncoder", + "easy ipadapterApplyFromParams", + "easy ipadapterApplyRegional", + "easy ipadapterStyleComposition", + "easy isSDXL", + "easy joinImageBatch", + "easy kSampler", + "easy kSamplerDownscaleUnet", + "easy kSamplerInpainting", + "easy kSamplerLayerDiffusion", + "easy kSamplerSDTurbo", + "easy kSamplerTiled", + "easy latentCompositeMaskedWithCond", + "easy latentNoisy", + "easy loadImageBase64", + "easy loraStack", + "easy negative", + "easy pipeBatchIndex", + "easy pipeEdit", + "easy pipeIn", + "easy pipeOut", + "easy pipeToBasicPipe", + "easy pixArtLoader", + "easy portraitMaster", + "easy poseEditor", + "easy positive", + "easy preDetailerFix", + "easy preMaskDetailerFix", + "easy preSampling", + "easy preSamplingAdvanced", + "easy preSamplingCascade", + "easy preSamplingCustom", + "easy preSamplingDynamicCFG", + "easy preSamplingLayerDiffusion", + "easy preSamplingLayerDiffusionADDTL", + "easy preSamplingNoiseIn", + "easy preSamplingSdTurbo", + "easy prompt", + "easy promptConcat", + "easy promptLine", + "easy promptList", + "easy promptReplace", + "easy pulIDApply", + "easy pulIDApplyADV", + "easy rangeFloat", + "easy rangeInt", + "easy removeLocalImage", + "easy samLoaderPipe", + "easy seed", + "easy showAnything", + "easy showLoaderSettingsNames", + "easy showSpentTime", + "easy showTensorShape", + "easy sliderControl", + "easy stableDiffusion3API", + "easy string", + "easy styleAlignedBatchAlign", + "easy stylesSelector", + "easy sv3dLoader", + "easy svdLoader", + "easy textSwitch", + "easy ultralyticsDetectorPipe", + "easy unSampler", + "easy wildcards", + "easy xyAny", + "easy zero123Loader" + ], + { + "title_aux": "ComfyUI Easy Use" + } + ], + "https://github.com/yolanother/DTAIComfyImageSubmit": [ + [ + "DTSimpleSubmitImage", + "DTSubmitImage" + ], + { + "title_aux": "Comfy AI DoubTech.ai Image Sumission Node" + } + ], + "https://github.com/yolanother/DTAIComfyLoaders": [ + [ + "DTCLIPLoader", + "DTCLIPVisionLoader", + "DTCheckpointLoader", + "DTCheckpointLoaderSimple", + "DTControlNetLoader", + "DTDiffControlNetLoader", + "DTDiffusersLoader", + "DTGLIGENLoader", + "DTLoadImage", + "DTLoadImageMask", + "DTLoadLatent", + "DTLoraLoader", + "DTLorasLoader", + "DTStyleModelLoader", + "DTUpscaleModelLoader", + "DTVAELoader", + "DTunCLIPCheckpointLoader" + ], + { + "title_aux": "Comfy UI Online Loaders" + } + ], + "https://github.com/yolanother/DTAIComfyPromptAgent": [ + [ + "DTPromptAgent", + "DTPromptAgentString" + ], + { + "title_aux": "Comfy UI Prompt Agent" + } + ], + "https://github.com/yolanother/DTAIComfyQRCodes": [ + [ + "QRCode" + ], + { + "title_aux": "Comfy UI QR Codes" + } + ], + "https://github.com/yolanother/DTAIComfyVariables": [ + [ + "DTCLIPTextEncode", + "DTSingleLineStringVariable", + "DTSingleLineStringVariableNoClip", + "FloatVariable", + "IntVariable", + "StringFormat", + "StringFormatSingleLine", + "StringVariable" + ], + { + "title_aux": "Variables for Comfy UI" + } + ], + "https://github.com/yolanother/DTAIImageToTextNode": [ + [ + "DTAIImageToTextNode", + "DTAIImageUrlToTextNode" + ], + { + "title_aux": "Image to Text Node" + } + ], + "https://github.com/youyegit/tdxh_node_comfyui": [ + [ + "TdxhBoolNumber", + "TdxhClipVison", + "TdxhControlNetApply", + "TdxhControlNetProcessor", + "TdxhFloatInput", + "TdxhImageToSize", + "TdxhImageToSizeAdvanced", + "TdxhImg2ImgLatent", + "TdxhIntInput", + "TdxhLoraLoader", + "TdxhOnOrOff", + "TdxhReference", + "TdxhStringInput", + "TdxhStringInputTranslator" + ], + { + "title_aux": "tdxh_node_comfyui" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Depth-Anything-Tensorrt": [ + [ + "DepthAnythingTensorrt" + ], + { + "title_aux": "ComfyUI Depth Anything TensorRT" + } + ], + "https://github.com/yuvraj108c/ComfyUI-PiperTTS": [ + [ + "PiperTTS" + ], + { + "title_aux": "ComfyUI PiperTTS" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Pronodes": [ + [ + "LoadImageFromOutputDirectoryNode", + "LoadYoutubeVideoNode", + "PreviewVHSAudioNode", + "SaveAndOverwriteImageNode", + "VHSFilenamesToPathNode" + ], + { + "title_aux": "ComfyUI-Pronodes" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Upscaler-Tensorrt": [ + [ + "UpscalerTensorrt" + ], + { + "title_aux": "ComfyUI Upscaler TensorRT" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Vsgan": [ + [ + "DepthAnythingTrtNode", + "TTSCapcutNode", + "UpscaleVideoTrtNode" + ], + { + "title_aux": "ComfyUI-Vsgan" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Whisper": [ + [ + "Add Subtitles To Background", + "Add Subtitles To Frames", + "Apply Whisper", + "Resize Cropped Subtitles" + ], + { + "title_aux": "ComfyUI Whisper" + } + ], + "https://github.com/yuvraj108c/ComfyUI-YoloNasPose-Tensorrt": [ + [ + "YoloNasPoseTensorrt" + ], + { + "title_aux": "ComfyUI YoloNasPose Tensorrt" + } + ], + "https://github.com/za-wa-n-go/ComfyUI_Zwng_Nodes": [ + [ + "ZwngLoadImagePathOrURL", + "ZwngPreviewImageAndMask", + "ZwngSimpleGoogleTranslater", + "ZwngSimplePhotoshopConnector" + ], + { + "title_aux": "ComfyUI_Zwng_Nodes" + } + ], + "https://github.com/zcfrank1st/Comfyui-Toolbox": [ + [ + "PreviewJson", + "PreviewVideo", + "SaveJson", + "TestJsonPreview" + ], + { + "title_aux": "Comfyui-Toolbox" + } + ], + "https://github.com/zcfrank1st/Comfyui-Yolov8": [ + [ + "Yolov8Detection", + "Yolov8Segmentation" + ], + { + "title_aux": "ComfyUI Yolov8" + } + ], + "https://github.com/zcfrank1st/comfyui_visual_anagrams": [ + [ + "VisualAnagramsAnimate", + "VisualAnagramsSample" + ], + { + "title_aux": "comfyui_visual_anagram" + } + ], + "https://github.com/zer0TF/cute-comfy": [ + [ + "Cute.Placeholder" + ], + { + "title_aux": "Cute Comfy" + } + ], + "https://github.com/zeroxoxo/ComfyUI-Fast-Style-Transfer": [ + [ + "FastStyleTransfer", + "TrainFastStyleTransfer" + ], + { + "title_aux": "ComfyUI-Fast-Style-Transfer" + } + ], + "https://github.com/zfkun/ComfyUI_zfkun": [ + [ + "ZFLoadImagePath", + "ZFPreviewText", + "ZFPreviewTextMultiline", + "ZFShareScreen", + "ZFTextTranslation" + ], + { + "title_aux": "ComfyUI_zfkun" + } + ], + "https://github.com/zhangp365/ComfyUI-utils-nodes": [ + [ + "CheckpointLoaderSimpleWithSwitch", + "ColorCorrectOfUtils", + "ConcatTextOfUtils", + "ImageBatchOneOrMore", + "ImageCompositeMaskedWithSwitch", + "ImageConcanateOfUtils", + "IntAndIntAddOffsetLiteral", + "IntMultipleAddLiteral", + "LoadImageMaskWithSwitch", + "LoadImageMaskWithoutListDir", + "LoadImageWithSwitch", + "LoadImageWithoutListDir", + "MaskAutoSelector", + "MaskFastGrow", + "ModifyTextGender", + "SplitMask" + ], + { + "title_aux": "zhangp365/Some Utils for ComfyUI" + } + ], + "https://github.com/zhongpei/ComfyUI-InstructIR": [ + [ + "InstructIRProcess", + "LoadInstructIRModel" + ], + { + "title_aux": "ComfyUI for InstructIR" + } + ], + "https://github.com/zhongpei/Comfyui_image2prompt": [ + [ + "CLIP AdvancedTextEncode|fofo", + "CLIP PromptConditioning|fofo", + "Image2Text", + "Image2TextWithTags", + "ImageBatchToList|fofo", + "ImageRewardScore|fofo", + "LoadImage2TextModel", + "LoadImageRewardScoreModel|fofo", + "LoadT5Model|fofo", + "LoadText2PromptModel", + "ShowText|fofo", + "T5QuantizationConfig|fofo", + "T5Text2Prompt|fofo", + "Text2GPTPrompt", + "Text2Prompt", + "TextBox|fofo", + "Translate2Chinese|fofo" + ], + { + "title_aux": "Comfyui_image2prompt" + } + ], + "https://github.com/zhuanqianfish/ComfyUI-EasyNode": [ + [ + "EasyCaptureNode", + "EasyVideoOutputNode", + "SendImageWebSocket" + ], + { + "title_aux": "EasyCaptureNode for ComfyUI" + } + ], + "https://github.com/zhulu111/ComfyUI_Bxb": [ + [ + "sdBxb", + "sdBxb_textInput" + ], + { + "title_aux": "ComfyUI_Bxb" + } + ], + "https://github.com/zohac/ComfyUI_ZC_DrawShape": [ + [ + "ZcDrawShape" + ], + { + "author": "Zohac", + "description": "nodes for artists, designers and animators.", + "nickname": "Zc DrawShape", + "title": "Zc DrawShape", + "title_aux": "ComfyUI_ZC_DrawShape" + } + ], + "https://github.com/zombieyang/sd-ppp": [ + [ + "Get Image From Photoshop Layer", + "Image Times Opacity", + "Mask Times Opacity", + "Send Images To Photoshop" + ], + { + "title_aux": "SD-PPP" + } + ], + "https://raw.githubusercontent.com/throttlekitty/SDXLCustomAspectRatio/main/SDXLAspectRatio.py": [ + [ + "SDXLAspectRatio" + ], + { + "title_aux": "SDXLCustomAspectRatio" + } + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/git_helper.py b/custom_nodes/ComfyUI-Manager/git_helper.py new file mode 100644 index 000000000..38dd24f73 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/git_helper.py @@ -0,0 +1,426 @@ +import subprocess +import sys +import os +import traceback + +import git +import configparser +import re +import json +import yaml +from torchvision.datasets.utils import download_url +from tqdm.auto import tqdm +from git.remote import RemoteProgress + +config_path = os.path.join(os.path.dirname(__file__), "config.ini") +nodelist_path = os.path.join(os.path.dirname(__file__), "custom-node-list.json") +working_directory = os.getcwd() + +if os.path.basename(working_directory) != 'custom_nodes': + print(f"WARN: This script should be executed in custom_nodes dir") + print(f"DBG: INFO {working_directory}") + print(f"DBG: INFO {sys.argv}") + # exit(-1) + + +class GitProgress(RemoteProgress): + def __init__(self): + super().__init__() + self.pbar = tqdm(ascii=True) + + def update(self, op_code, cur_count, max_count=None, message=''): + self.pbar.total = max_count + self.pbar.n = cur_count + self.pbar.pos = 0 + self.pbar.refresh() + + +def gitclone(custom_nodes_path, url, target_hash=None): + repo_name = os.path.splitext(os.path.basename(url))[0] + repo_path = os.path.join(custom_nodes_path, repo_name) + + # Clone the repository from the remote URL + repo = git.Repo.clone_from(url, repo_path, recursive=True, progress=GitProgress()) + + if target_hash is not None: + print(f"CHECKOUT: {repo_name} [{target_hash}]") + repo.git.checkout(target_hash) + + repo.git.clear_cache() + repo.close() + + +def gitcheck(path, do_fetch=False): + try: + # Fetch the latest commits from the remote repository + repo = git.Repo(path) + + if repo.head.is_detached: + print("CUSTOM NODE CHECK: True") + return + + current_branch = repo.active_branch + branch_name = current_branch.name + + remote_name = current_branch.tracking_branch().remote_name + remote = repo.remote(name=remote_name) + + if do_fetch: + remote.fetch() + + # Get the current commit hash and the commit hash of the remote branch + commit_hash = repo.head.commit.hexsha + remote_commit_hash = repo.refs[f'{remote_name}/{branch_name}'].object.hexsha + + # Compare the commit hashes to determine if the local repository is behind the remote repository + if commit_hash != remote_commit_hash: + # Get the commit dates + commit_date = repo.head.commit.committed_datetime + remote_commit_date = repo.refs[f'{remote_name}/{branch_name}'].object.committed_datetime + + # Compare the commit dates to determine if the local repository is behind the remote repository + if commit_date < remote_commit_date: + print("CUSTOM NODE CHECK: True") + else: + print("CUSTOM NODE CHECK: False") + except Exception as e: + print(e) + print("CUSTOM NODE CHECK: Error") + + +def switch_to_default_branch(repo): + show_result = repo.git.remote("show", "origin") + matches = re.search(r"\s*HEAD branch:\s*(.*)", show_result) + if matches: + default_branch = matches.group(1) + repo.git.checkout(default_branch) + + +def gitpull(path): + # Check if the path is a git repository + if not os.path.exists(os.path.join(path, '.git')): + raise ValueError('Not a git repository') + + # Pull the latest changes from the remote repository + repo = git.Repo(path) + if repo.is_dirty(): + repo.git.stash() + + commit_hash = repo.head.commit.hexsha + try: + if repo.head.is_detached: + switch_to_default_branch(repo) + + current_branch = repo.active_branch + branch_name = current_branch.name + + remote_name = current_branch.tracking_branch().remote_name + remote = repo.remote(name=remote_name) + + remote.fetch() + remote_commit_hash = repo.refs[f'{remote_name}/{branch_name}'].object.hexsha + + if commit_hash == remote_commit_hash: + print("CUSTOM NODE PULL: None") # there is no update + repo.close() + return + + remote.pull() + + repo.git.submodule('update', '--init', '--recursive') + new_commit_hash = repo.head.commit.hexsha + + if commit_hash != new_commit_hash: + print("CUSTOM NODE PULL: Success") # update success + else: + print("CUSTOM NODE PULL: Fail") # update fail + except Exception as e: + print(e) + print("CUSTOM NODE PULL: Fail") # unknown git error + + repo.close() + + +def checkout_comfyui_hash(target_hash): + repo_path = os.path.abspath(os.path.join(working_directory, '..')) # ComfyUI dir + + repo = git.Repo(repo_path) + commit_hash = repo.head.commit.hexsha + + if commit_hash != target_hash: + try: + print(f"CHECKOUT: ComfyUI [{target_hash}]") + repo.git.checkout(target_hash) + except git.GitCommandError as e: + print(f"Error checking out the ComfyUI: {str(e)}") + + +def checkout_custom_node_hash(git_custom_node_infos): + repo_name_to_url = {} + + for url in git_custom_node_infos.keys(): + repo_name = url.split('/')[-1] + + if repo_name.endswith('.git'): + repo_name = repo_name[:-4] + + repo_name_to_url[repo_name] = url + + for path in os.listdir(working_directory): + if path.endswith("ComfyUI-Manager"): + continue + + fullpath = os.path.join(working_directory, path) + + if os.path.isdir(fullpath): + is_disabled = path.endswith(".disabled") + + try: + git_dir = os.path.join(fullpath, '.git') + if not os.path.exists(git_dir): + continue + + need_checkout = False + repo_name = os.path.basename(fullpath) + + if repo_name.endswith('.disabled'): + repo_name = repo_name[:-9] + + if repo_name not in repo_name_to_url: + if not is_disabled: + # should be disabled + print(f"DISABLE: {repo_name}") + new_path = fullpath + ".disabled" + os.rename(fullpath, new_path) + need_checkout = False + else: + item = git_custom_node_infos[repo_name_to_url[repo_name]] + if item['disabled'] and is_disabled: + pass + elif item['disabled'] and not is_disabled: + # disable + print(f"DISABLE: {repo_name}") + new_path = fullpath + ".disabled" + os.rename(fullpath, new_path) + + elif not item['disabled'] and is_disabled: + # enable + print(f"ENABLE: {repo_name}") + new_path = fullpath[:-9] + os.rename(fullpath, new_path) + fullpath = new_path + need_checkout = True + else: + need_checkout = True + + if need_checkout: + repo = git.Repo(fullpath) + commit_hash = repo.head.commit.hexsha + + if commit_hash != item['hash']: + print(f"CHECKOUT: {repo_name} [{item['hash']}]") + repo.git.checkout(item['hash']) + + except Exception: + print(f"Failed to restore snapshots for the custom node '{path}'") + + # clone missing + for k, v in git_custom_node_infos.items(): + if not v['disabled']: + repo_name = k.split('/')[-1] + if repo_name.endswith('.git'): + repo_name = repo_name[:-4] + + path = os.path.join(working_directory, repo_name) + if not os.path.exists(path): + print(f"CLONE: {path}") + gitclone(working_directory, k, v['hash']) + + +def invalidate_custom_node_file(file_custom_node_infos): + global nodelist_path + + enabled_set = set() + for item in file_custom_node_infos: + if not item['disabled']: + enabled_set.add(item['filename']) + + for path in os.listdir(working_directory): + fullpath = os.path.join(working_directory, path) + + if not os.path.isdir(fullpath) and fullpath.endswith('.py'): + if path not in enabled_set: + print(f"DISABLE: {path}") + new_path = fullpath+'.disabled' + os.rename(fullpath, new_path) + + elif not os.path.isdir(fullpath) and fullpath.endswith('.py.disabled'): + path = path[:-9] + if path in enabled_set: + print(f"ENABLE: {path}") + new_path = fullpath[:-9] + os.rename(fullpath, new_path) + + # download missing: just support for 'copy' style + py_to_url = {} + + with open(nodelist_path, 'r', encoding="UTF-8") as json_file: + info = json.load(json_file) + for item in info['custom_nodes']: + if item['install_type'] == 'copy': + for url in item['files']: + if url.endswith('.py'): + py = url.split('/')[-1] + py_to_url[py] = url + + for item in file_custom_node_infos: + filename = item['filename'] + if not item['disabled']: + target_path = os.path.join(working_directory, filename) + + if not os.path.exists(target_path) and filename in py_to_url: + url = py_to_url[filename] + print(f"DOWNLOAD: {filename}") + download_url(url, working_directory) + + +def apply_snapshot(target): + try: + path = os.path.join(os.path.dirname(__file__), 'snapshots', f"{target}") + if os.path.exists(path): + if not target.endswith('.json') and not target.endswith('.yaml'): + print(f"Snapshot file not found: `{path}`") + print("APPLY SNAPSHOT: False") + return None + + with open(path, 'r', encoding="UTF-8") as snapshot_file: + if target.endswith('.json'): + info = json.load(snapshot_file) + elif target.endswith('.yaml'): + info = yaml.load(snapshot_file, Loader=yaml.SafeLoader) + info = info['custom_nodes'] + else: + # impossible case + print("APPLY SNAPSHOT: False") + return None + + comfyui_hash = info['comfyui'] + git_custom_node_infos = info['git_custom_nodes'] + file_custom_node_infos = info['file_custom_nodes'] + + checkout_comfyui_hash(comfyui_hash) + checkout_custom_node_hash(git_custom_node_infos) + invalidate_custom_node_file(file_custom_node_infos) + + print("APPLY SNAPSHOT: True") + if 'pips' in info: + return info['pips'] + else: + return None + + print(f"Snapshot file not found: `{path}`") + print("APPLY SNAPSHOT: False") + + return None + except Exception as e: + print(e) + traceback.print_exc() + print("APPLY SNAPSHOT: False") + + return None + + +def restore_pip_snapshot(pips, options): + non_url = [] + local_url = [] + non_local_url = [] + for k, v in pips.items(): + if v == "": + non_url.append(k) + else: + if v.startswith('file:'): + local_url.append(v) + else: + non_local_url.append(v) + + failed = [] + if '--pip-non-url' in options: + # try all at once + res = 1 + try: + res = subprocess.check_call([sys.executable, '-m', 'pip', 'install'] + non_url) + except: + pass + + # fallback + if res != 0: + for x in non_url: + res = 1 + try: + res = subprocess.check_call([sys.executable, '-m', 'pip', 'install', x]) + except: + pass + + if res != 0: + failed.append(x) + + if '--pip-non-local-url' in options: + for x in non_local_url: + res = 1 + try: + res = subprocess.check_call([sys.executable, '-m', 'pip', 'install', x]) + except: + pass + + if res != 0: + failed.append(x) + + if '--pip-local-url' in options: + for x in local_url: + res = 1 + try: + res = subprocess.check_call([sys.executable, '-m', 'pip', 'install', x]) + except: + pass + + if res != 0: + failed.append(x) + + print(f"Installation failed for pip packages: {failed}") + + +def setup_environment(): + config = configparser.ConfigParser() + config.read(config_path) + if 'default' in config and 'git_exe' in config['default'] and config['default']['git_exe'] != '': + git.Git().update_environment(GIT_PYTHON_GIT_EXECUTABLE=config['default']['git_exe']) + + +setup_environment() + + +try: + if sys.argv[1] == "--clone": + gitclone(sys.argv[2], sys.argv[3]) + elif sys.argv[1] == "--check": + gitcheck(sys.argv[2], False) + elif sys.argv[1] == "--fetch": + gitcheck(sys.argv[2], True) + elif sys.argv[1] == "--pull": + gitpull(sys.argv[2]) + elif sys.argv[1] == "--apply-snapshot": + options = set() + for x in sys.argv: + if x in ['--pip-non-url', '--pip-local-url', '--pip-non-local-url']: + options.add(x) + + pips = apply_snapshot(sys.argv[2]) + + if pips and len(options) > 0: + restore_pip_snapshot(pips, options) + sys.exit(0) +except Exception as e: + print(e) + sys.exit(-1) + + diff --git a/custom_nodes/ComfyUI-Manager/github-stats.json b/custom_nodes/ComfyUI-Manager/github-stats.json new file mode 100644 index 000000000..22e023900 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/github-stats.json @@ -0,0 +1,5232 @@ +{ + "https://github.com/0xbitches/ComfyUI-LCM": { + "stars": 247, + "last_update": "2023-11-11 21:24:33", + "author_account_age_days": 547 + }, + "https://github.com/1038lab/ComfyUI-GPT2P": { + "stars": 3, + "last_update": "2024-06-10 16:56:29", + "author_account_age_days": 467 + }, + "https://github.com/1038lab/ComfyUI_LatentSizeSelector": { + "stars": 1, + "last_update": "2024-07-03 23:22:52", + "author_account_age_days": 467 + }, + "https://github.com/11cafe/comfyui-workspace-manager": { + "stars": 828, + "last_update": "2024-07-02 13:41:38", + "author_account_age_days": 220 + }, + "https://github.com/11dogzi/ComfUI-EGAdapterMadAssistant": { + "stars": 11, + "last_update": "2024-07-09 14:44:29", + "author_account_age_days": 140 + }, + "https://github.com/11dogzi/Comfyui-ergouzi-Nodes": { + "stars": 21, + "last_update": "2024-05-23 00:08:39", + "author_account_age_days": 140 + }, + "https://github.com/11dogzi/Comfyui-ergouzi-samplers": { + "stars": 21, + "last_update": "2024-06-28 05:28:05", + "author_account_age_days": 140 + }, + "https://github.com/1mckw/Comfyui-Gelbooru": { + "stars": 2, + "last_update": "2024-05-27 07:45:00", + "author_account_age_days": 705 + }, + "https://github.com/42lux/ComfyUI-safety-checker": { + "stars": 20, + "last_update": "2024-05-22 22:11:59", + "author_account_age_days": 3714 + }, + "https://github.com/438443467/ComfyUI-GPT4V-Image-Captioner": { + "stars": 20, + "last_update": "2024-06-13 05:51:56", + "author_account_age_days": 429 + }, + "https://github.com/54rt1n/ComfyUI-DareMerge": { + "stars": 47, + "last_update": "2024-07-09 16:29:23", + "author_account_age_days": 4066 + }, + "https://github.com/80sVectorz/ComfyUI-Static-Primitives": { + "stars": 10, + "last_update": "2024-05-23 11:20:57", + "author_account_age_days": 1486 + }, + "https://github.com/A4P7J1N7M05OT/ComfyUI-AutoColorGimp": { + "stars": 0, + "last_update": "2024-05-23 00:26:10", + "author_account_age_days": 488 + }, + "https://github.com/A4P7J1N7M05OT/ComfyUI-PixelOE": { + "stars": 7, + "last_update": "2024-06-02 14:57:59", + "author_account_age_days": 488 + }, + "https://github.com/AARG-FAN/Image-Raster-for-ComfyUI": { + "stars": 70, + "last_update": "2024-06-23 14:56:16", + "author_account_age_days": 514 + }, + "https://github.com/AI2lab/comfyUI-DeepSeek-2lab": { + "stars": 3, + "last_update": "2024-07-03 04:07:46", + "author_account_age_days": 207 + }, + "https://github.com/AI2lab/comfyUI-siliconflow-api-2lab": { + "stars": 3, + "last_update": "2024-06-29 18:08:21", + "author_account_age_days": 207 + }, + "https://github.com/AI2lab/comfyUI-tool-2lab": { + "stars": 9, + "last_update": "2024-07-08 07:12:32", + "author_account_age_days": 207 + }, + "https://github.com/AIFSH/ComfyUI-3d-photo-inpainting": { + "stars": 6, + "last_update": "2024-06-19 13:59:49", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-AuraSR": { + "stars": 13, + "last_update": "2024-06-27 14:00:16", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-DiffSynth-Studio": { + "stars": 32, + "last_update": "2024-07-02 13:01:42", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-FishSpeech": { + "stars": 8, + "last_update": "2024-05-23 01:18:49", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-GPT_SoVITS": { + "stars": 161, + "last_update": "2024-06-14 07:05:01", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-Hallo": { + "stars": 229, + "last_update": "2024-06-24 06:43:23", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-I2V-Adapter": { + "stars": 7, + "last_update": "2024-07-02 01:59:49", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-IP_LAP": { + "stars": 24, + "last_update": "2024-06-14 07:05:39", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-Live2DViewer": { + "stars": 2, + "last_update": "2024-06-14 07:04:49", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-MARS5-TTS": { + "stars": 18, + "last_update": "2024-07-02 02:00:28", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-MimicBrush": { + "stars": 69, + "last_update": "2024-06-17 22:26:53", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-MimicMotion": { + "stars": 235, + "last_update": "2024-07-02 13:59:07", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-MuseTalk_FSH": { + "stars": 9, + "last_update": "2024-06-14 07:05:19", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-RVC": { + "stars": 9, + "last_update": "2024-06-14 07:05:25", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-UVR5": { + "stars": 64, + "last_update": "2024-06-20 07:31:20", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-UniAnimate": { + "stars": 27, + "last_update": "2024-06-30 09:20:25", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-WhisperX": { + "stars": 21, + "last_update": "2024-06-14 07:05:31", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI-XTTS": { + "stars": 28, + "last_update": "2024-06-24 09:45:59", + "author_account_age_days": 246 + }, + "https://github.com/AIFSH/ComfyUI_V-Express": { + "stars": 77, + "last_update": "2024-06-23 09:54:57", + "author_account_age_days": 246 + }, + "https://github.com/AIGCTeam/ComfyUI_kkTranslator_nodes": { + "stars": 5, + "last_update": "2024-05-23 00:13:50", + "author_account_age_days": 225 + }, + "https://github.com/AIGODLIKE/AIGODLIKE-COMFYUI-TRANSLATION": { + "stars": 1043, + "last_update": "2024-07-01 03:49:28", + "author_account_age_days": 516 + }, + "https://github.com/AIGODLIKE/AIGODLIKE-ComfyUI-Studio": { + "stars": 208, + "last_update": "2024-06-05 00:52:46", + "author_account_age_days": 516 + }, + "https://github.com/AIGODLIKE/ComfyUI-CUP": { + "stars": 6, + "last_update": "2024-06-21 03:43:20", + "author_account_age_days": 516 + }, + "https://github.com/AIGODLIKE/ComfyUI-ToonCrafter": { + "stars": 263, + "last_update": "2024-06-18 08:04:40", + "author_account_age_days": 516 + }, + "https://github.com/AInseven/ComfyUI-fastblend": { + "stars": 136, + "last_update": "2024-06-14 07:13:21", + "author_account_age_days": 1698 + }, + "https://github.com/AIrjen/OneButtonPrompt": { + "stars": 754, + "last_update": "2024-07-09 17:44:12", + "author_account_age_days": 458 + }, + "https://github.com/ALatentPlace/ComfyUI_yanc": { + "stars": 23, + "last_update": "2024-06-30 10:04:17", + "author_account_age_days": 1475 + }, + "https://github.com/AbdullahAlfaraj/Comfy-Photoshop-SD": { + "stars": 184, + "last_update": "2024-06-14 07:04:37", + "author_account_age_days": 3683 + }, + "https://github.com/AbyssYuan0/ComfyUI_BadgerTools": { + "stars": 6, + "last_update": "2024-06-19 11:46:19", + "author_account_age_days": 504 + }, + "https://github.com/Acly/comfyui-inpaint-nodes": { + "stars": 470, + "last_update": "2024-07-02 10:02:46", + "author_account_age_days": 3820 + }, + "https://github.com/Acly/comfyui-tooling-nodes": { + "stars": 216, + "last_update": "2024-06-24 15:56:37", + "author_account_age_days": 3820 + }, + "https://github.com/AiMiDi/ComfyUI-Aimidi-nodes": { + "stars": 0, + "last_update": "2024-06-20 17:26:02", + "author_account_age_days": 1291 + }, + "https://github.com/AlekPet/ComfyUI_Custom_Nodes_AlekPet": { + "stars": 681, + "last_update": "2024-06-28 14:06:48", + "author_account_age_days": 2715 + }, + "https://github.com/Alysondao/Comfyui-Yolov8-JSON": { + "stars": 12, + "last_update": "2024-07-03 03:59:38", + "author_account_age_days": 1045 + }, + "https://github.com/Amorano/Jovimetrix": { + "stars": 172, + "last_update": "2024-07-07 17:11:00", + "author_account_age_days": 5227 + }, + "https://github.com/AonekoSS/ComfyUI-LoRA-Tuner": { + "stars": 5, + "last_update": "2024-07-05 13:48:56", + "author_account_age_days": 4107 + }, + "https://github.com/AonekoSS/ComfyUI-SimpleCounter": { + "stars": 1, + "last_update": "2024-07-05 13:46:19", + "author_account_age_days": 4107 + }, + "https://github.com/ArcherFMY/Diffusion360_ComfyUI": { + "stars": 18, + "last_update": "2024-05-28 03:14:17", + "author_account_age_days": 3404 + }, + "https://github.com/ArdeniusAI/CPlus_Ardenius": { + "stars": 0, + "last_update": "2024-06-14 07:13:26", + "author_account_age_days": 142 + }, + "https://github.com/ArtBot2023/CharacterFaceSwap": { + "stars": 57, + "last_update": "2024-05-22 20:53:09", + "author_account_age_days": 308 + }, + "https://github.com/ArtVentureX/comfyui-animatediff": { + "stars": 644, + "last_update": "2024-05-22 18:16:43", + "author_account_age_days": 420 + }, + "https://github.com/AshMartian/ComfyUI-DirGir": { + "stars": 11, + "last_update": "2024-05-29 22:28:55", + "author_account_age_days": 4601 + }, + "https://github.com/AuroBit/ComfyUI-AnimateAnyone-reproduction": { + "stars": 34, + "last_update": "2024-06-14 09:03:24", + "author_account_age_days": 405 + }, + "https://github.com/AuroBit/ComfyUI-OOTDiffusion": { + "stars": 356, + "last_update": "2024-06-14 08:11:00", + "author_account_age_days": 405 + }, + "https://github.com/AustinMroz/ComfyUI-DynamicOversampling": { + "stars": 0, + "last_update": "2024-06-14 07:06:51", + "author_account_age_days": 4089 + }, + "https://github.com/AustinMroz/ComfyUI-SpliceTools": { + "stars": 7, + "last_update": "2024-06-14 07:07:21", + "author_account_age_days": 4089 + }, + "https://github.com/AustinMroz/ComfyUI-WorkflowCheckpointing": { + "stars": 6, + "last_update": "2024-07-03 21:55:35", + "author_account_age_days": 4089 + }, + "https://github.com/Auttasak-L/ComfyUI-ImageCropper": { + "stars": 1, + "last_update": "2024-05-23 05:04:53", + "author_account_age_days": 2664 + }, + "https://github.com/BAIS1C/ComfyUI_RSS_Feed_Reader": { + "stars": 2, + "last_update": "2024-06-20 03:42:00", + "author_account_age_days": 505 + }, + "https://github.com/BXYMartin/ComfyUI-InstantIDUtils": { + "stars": 3, + "last_update": "2024-05-23 00:08:50", + "author_account_age_days": 2458 + }, + "https://github.com/BadCafeCode/masquerade-nodes-comfyui": { + "stars": 314, + "last_update": "2024-06-19 04:16:54", + "author_account_age_days": 445 + }, + "https://github.com/Beinsezii/bsz-cui-extras": { + "stars": 21, + "last_update": "2024-05-22 20:46:45", + "author_account_age_days": 2241 + }, + "https://github.com/BenNarum/SigmaWaveFormNode": { + "stars": 5, + "last_update": "2024-06-20 15:20:35", + "author_account_age_days": 3087 + }, + "https://github.com/BennyKok/comfyui-deploy": { + "stars": 713, + "last_update": "2024-07-08 05:06:56", + "author_account_age_days": 3011 + }, + "https://github.com/Big-Idea-Technology/ComfyUI-Book-Tools": { + "stars": 17, + "last_update": "2024-06-21 10:21:10", + "author_account_age_days": 887 + }, + "https://github.com/Big-Idea-Technology/ComfyUI_LLM_Node": { + "stars": 50, + "last_update": "2024-06-21 10:13:50", + "author_account_age_days": 887 + }, + "https://github.com/Billius-AI/ComfyUI-Path-Helper": { + "stars": 14, + "last_update": "2024-05-22 23:25:08", + "author_account_age_days": 150 + }, + "https://github.com/BlakeOne/ComfyUI-CustomScheduler": { + "stars": 11, + "last_update": "2024-05-23 00:23:56", + "author_account_age_days": 2548 + }, + "https://github.com/BlakeOne/ComfyUI-NodePresets": { + "stars": 11, + "last_update": "2024-05-23 00:24:07", + "author_account_age_days": 2548 + }, + "https://github.com/BlakeOne/ComfyUI-NodeReset": { + "stars": 1, + "last_update": "2024-05-23 00:24:18", + "author_account_age_days": 2548 + }, + "https://github.com/BlakeOne/ComfyUI-SchedulerMixer": { + "stars": 10, + "last_update": "2024-05-23 00:23:44", + "author_account_age_days": 2548 + }, + "https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb": { + "stars": 274, + "last_update": "2024-05-22 14:56:13", + "author_account_age_days": 493 + }, + "https://github.com/BlenderNeko/ComfyUI_Cutoff": { + "stars": 344, + "last_update": "2024-05-22 15:01:45", + "author_account_age_days": 493 + }, + "https://github.com/BlenderNeko/ComfyUI_Noise": { + "stars": 214, + "last_update": "2024-06-10 16:38:48", + "author_account_age_days": 493 + }, + "https://github.com/BlenderNeko/ComfyUI_SeeCoder": { + "stars": 36, + "last_update": "2024-05-22 14:57:04", + "author_account_age_days": 493 + }, + "https://github.com/BlenderNeko/ComfyUI_TiledKSampler": { + "stars": 297, + "last_update": "2024-05-22 14:56:49", + "author_account_age_days": 493 + }, + "https://github.com/CC-BryanOttho/ComfyUI_API_Manager": { + "stars": 13, + "last_update": "2024-06-14 07:13:34", + "author_account_age_days": 500 + }, + "https://github.com/CYBERLOOM-INC/ComfyUI-nodes-hnmr": { + "stars": 6, + "last_update": "2024-05-22 17:55:41", + "author_account_age_days": 265 + }, + "https://github.com/CavinHuang/comfyui-nodes-docs": { + "stars": 76, + "last_update": "2024-07-04 11:29:55", + "author_account_age_days": 2741 + }, + "https://github.com/Chan-0312/ComfyUI-EasyDeforum": { + "stars": 9, + "last_update": "2024-05-22 23:22:14", + "author_account_age_days": 1881 + }, + "https://github.com/Chan-0312/ComfyUI-IPAnimate": { + "stars": 66, + "last_update": "2024-05-22 23:22:03", + "author_account_age_days": 1881 + }, + "https://github.com/Chan-0312/ComfyUI-Prompt-Preview": { + "stars": 19, + "last_update": "2024-06-14 09:01:37", + "author_account_age_days": 1881 + }, + "https://github.com/Chaoses-Ib/ComfyUI_Ib_CustomNodes": { + "stars": 13, + "last_update": "2024-04-05 11:14:24", + "author_account_age_days": 1894 + }, + "https://github.com/Clybius/ComfyUI-Extra-Samplers": { + "stars": 58, + "last_update": "2024-06-14 09:03:17", + "author_account_age_days": 1749 + }, + "https://github.com/Clybius/ComfyUI-Latent-Modifiers": { + "stars": 64, + "last_update": "2024-06-14 09:02:44", + "author_account_age_days": 1749 + }, + "https://github.com/CosmicLaca/ComfyUI_Primere_Nodes": { + "stars": 85, + "last_update": "2024-06-29 07:14:23", + "author_account_age_days": 3670 + }, + "https://github.com/Danand/ComfyUI-ComfyCouple": { + "stars": 21, + "last_update": "2024-07-03 22:22:08", + "author_account_age_days": 4304 + }, + "https://github.com/DarKDinDoN/comfyui-checkpoint-automatic-config": { + "stars": 3, + "last_update": "2024-05-26 08:00:23", + "author_account_age_days": 4455 + }, + "https://github.com/DataCTE/prompt_injection": { + "stars": 66, + "last_update": "2024-06-21 12:56:43", + "author_account_age_days": 793 + }, + "https://github.com/DeJoker/pipeline-parallel-comfy": { + "stars": 1, + "last_update": "2024-07-09 03:00:49", + "author_account_age_days": 3006 + }, + "https://github.com/Derfuu/Derfuu_ComfyUI_ModdedNodes": { + "stars": 308, + "last_update": "2024-06-22 02:12:19", + "author_account_age_days": 1790 + }, + "https://github.com/DigitalIO/ComfyUI-stable-wildcards": { + "stars": 19, + "last_update": "2024-05-24 21:15:08", + "author_account_age_days": 4054 + }, + "https://github.com/DimaChaichan/LAizypainter-Exporter-ComfyUI": { + "stars": 7, + "last_update": "2024-05-22 23:14:06", + "author_account_age_days": 3088 + }, + "https://github.com/DonBaronFactory/ComfyUI-Cre8it-Nodes": { + "stars": 0, + "last_update": "2024-05-22 23:24:30", + "author_account_age_days": 3503 + }, + "https://github.com/DrJKL/ComfyUI-Anchors": { + "stars": 5, + "last_update": "2024-06-20 18:23:00", + "author_account_age_days": 5010 + }, + "https://github.com/DrMWeigand/ComfyUI_ColorImageDetection": { + "stars": 2, + "last_update": "2024-05-23 00:25:14", + "author_account_age_days": 1047 + }, + "https://github.com/Electrofried/ComfyUI-OpenAINode": { + "stars": 19, + "last_update": "2024-06-14 09:01:22", + "author_account_age_days": 2635 + }, + "https://github.com/EllangoK/ComfyUI-post-processing-nodes": { + "stars": 147, + "last_update": "2024-05-22 17:54:09", + "author_account_age_days": 2793 + }, + "https://github.com/ExponentialML/ComfyUI_ModelScopeT2V": { + "stars": 25, + "last_update": "2024-05-23 00:12:17", + "author_account_age_days": 1639 + }, + "https://github.com/ExponentialML/ComfyUI_Native_DynamiCrafter": { + "stars": 103, + "last_update": "2024-06-08 02:33:02", + "author_account_age_days": 1639 + }, + "https://github.com/ExponentialML/ComfyUI_VisualStylePrompting": { + "stars": 255, + "last_update": "2024-05-23 00:12:41", + "author_account_age_days": 1639 + }, + "https://github.com/Extraltodeus/ComfyUI-AutomaticCFG": { + "stars": 285, + "last_update": "2024-07-07 23:20:40", + "author_account_age_days": 3165 + }, + "https://github.com/Extraltodeus/LoadLoraWithTags": { + "stars": 42, + "last_update": "2024-06-22 21:05:44", + "author_account_age_days": 3165 + }, + "https://github.com/Extraltodeus/Stable-Diffusion-temperature-settings": { + "stars": 33, + "last_update": "2024-07-07 13:37:55", + "author_account_age_days": 3165 + }, + "https://github.com/Extraltodeus/Uncond-Zero-for-ComfyUI": { + "stars": 38, + "last_update": "2024-07-08 20:33:15", + "author_account_age_days": 3165 + }, + "https://github.com/Extraltodeus/Vector_Sculptor_ComfyUI": { + "stars": 87, + "last_update": "2024-06-22 21:06:08", + "author_account_age_days": 3165 + }, + "https://github.com/Extraltodeus/noise_latent_perlinpinpin": { + "stars": 23, + "last_update": "2024-06-22 21:05:57", + "author_account_age_days": 3165 + }, + "https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI": { + "stars": 0, + "last_update": "2024-07-09 23:23:27", + "author_account_age_days": 3165 + }, + "https://github.com/Extraltodeus/sigmas_tools_and_the_golden_scheduler": { + "stars": 46, + "last_update": "2024-06-22 21:05:34", + "author_account_age_days": 3165 + }, + "https://github.com/Fannovel16/ComfyUI-Frame-Interpolation": { + "stars": 357, + "last_update": "2024-06-20 16:25:59", + "author_account_age_days": 3147 + }, + "https://github.com/Fannovel16/ComfyUI-Loopchain": { + "stars": 30, + "last_update": "2023-12-15 14:25:35", + "author_account_age_days": 3147 + }, + "https://github.com/Fannovel16/ComfyUI-MagickWand": { + "stars": 73, + "last_update": "2024-06-20 16:23:15", + "author_account_age_days": 3147 + }, + "https://github.com/Fannovel16/ComfyUI-MotionDiff": { + "stars": 150, + "last_update": "2024-06-20 16:29:32", + "author_account_age_days": 3147 + }, + "https://github.com/Fannovel16/ComfyUI-Video-Matting": { + "stars": 151, + "last_update": "2024-06-20 16:14:38", + "author_account_age_days": 3147 + }, + "https://github.com/Fannovel16/comfyui_controlnet_aux": { + "stars": 1661, + "last_update": "2024-07-08 17:03:55", + "author_account_age_days": 3147 + }, + "https://github.com/Fantaxico/ComfyUI-GCP-Storage": { + "stars": 0, + "last_update": "2024-06-14 09:05:52", + "author_account_age_days": 551 + }, + "https://github.com/Feidorian/feidorian-ComfyNodes": { + "stars": 5, + "last_update": "2024-06-20 11:31:37", + "author_account_age_days": 2770 + }, + "https://github.com/Fictiverse/ComfyUI_Fictiverse": { + "stars": 7, + "last_update": "2024-06-05 19:03:21", + "author_account_age_days": 687 + }, + "https://github.com/Fihade/IC-Light-ComfyUI-Node": { + "stars": 6, + "last_update": "2024-07-02 03:47:17", + "author_account_age_days": 2762 + }, + "https://github.com/FizzleDorf/ComfyUI-AIT": { + "stars": 44, + "last_update": "2024-06-22 03:13:05", + "author_account_age_days": 1995 + }, + "https://github.com/FizzleDorf/ComfyUI_FizzNodes": { + "stars": 326, + "last_update": "2024-06-27 03:29:51", + "author_account_age_days": 1995 + }, + "https://github.com/FlyingFireCo/tiled_ksampler": { + "stars": 56, + "last_update": "2024-05-22 23:15:17", + "author_account_age_days": 648 + }, + "https://github.com/ForeignGods/ComfyUI-Mana-Nodes": { + "stars": 182, + "last_update": "2024-05-29 18:29:05", + "author_account_age_days": 1259 + }, + "https://github.com/Franck-Demongin/NX_PromptStyler": { + "stars": 5, + "last_update": "2024-05-22 23:25:21", + "author_account_age_days": 1786 + }, + "https://github.com/FredBill1/comfyui-fb-utils": { + "stars": 0, + "last_update": "2024-05-23 01:41:02", + "author_account_age_days": 2332 + }, + "https://github.com/Fucci-Mateo/ComfyUI-Airtable": { + "stars": 0, + "last_update": "2024-06-25 13:35:18", + "author_account_age_days": 894 + }, + "https://github.com/FuouM/ComfyUI-FirstOrderMM": { + "stars": 2, + "last_update": "2024-07-01 10:46:26", + "author_account_age_days": 1696 + }, + "https://github.com/G-370/ComfyUI-SD3-Powerlab": { + "stars": 17, + "last_update": "2024-06-22 19:17:18", + "author_account_age_days": 1534 + }, + "https://github.com/GMapeSplat/ComfyUI_ezXY": { + "stars": 23, + "last_update": "2024-05-29 17:43:08", + "author_account_age_days": 1313 + }, + "https://github.com/GTSuya-Studio/ComfyUI-Gtsuya-Nodes": { + "stars": 7, + "last_update": "2024-05-22 21:31:52", + "author_account_age_days": 2572 + }, + "https://github.com/GavChap/ComfyUI-SD3LatentSelectRes": { + "stars": 9, + "last_update": "2024-06-19 11:01:41", + "author_account_age_days": 4583 + }, + "https://github.com/GentlemanHu/ComfyUI-SunoAI": { + "stars": 10, + "last_update": "2024-06-14 06:02:29", + "author_account_age_days": 2398 + }, + "https://github.com/Goktug/comfyui-saveimage-plus": { + "stars": 2, + "last_update": "2024-06-20 07:23:48", + "author_account_age_days": 4947 + }, + "https://github.com/Gourieff/comfyui-reactor-node": { + "stars": 1122, + "last_update": "2024-07-03 09:36:19", + "author_account_age_days": 1135 + }, + "https://github.com/GraftingRayman/ComfyUI_GraftingRayman": { + "stars": 23, + "last_update": "2024-07-09 08:28:38", + "author_account_age_days": 178 + }, + "https://github.com/Grant-CP/ComfyUI-LivePortraitKJ-MPS": { + "stars": 6, + "last_update": "2024-07-09 04:52:14", + "author_account_age_days": 1189 + }, + "https://github.com/GreenLandisaLie/AuraSR-ComfyUI": { + "stars": 68, + "last_update": "2024-07-04 00:07:10", + "author_account_age_days": 1213 + }, + "https://github.com/Guillaume-Fgt/ComfyUI_StableCascadeLatentRatio": { + "stars": 3, + "last_update": "2024-06-14 08:59:42", + "author_account_age_days": 1495 + }, + "https://github.com/HAL41/ComfyUI-aichemy-nodes": { + "stars": 4, + "last_update": "2024-05-22 23:10:19", + "author_account_age_days": 2861 + }, + "https://github.com/HECer/ComfyUI-FilePathCreator": { + "stars": 2, + "last_update": "2024-07-09 22:02:15", + "author_account_age_days": 2995 + }, + "https://github.com/Hangover3832/ComfyUI-Hangover-Moondream": { + "stars": 37, + "last_update": "2024-06-14 08:08:20", + "author_account_age_days": 625 + }, + "https://github.com/Hangover3832/ComfyUI-Hangover-Nodes": { + "stars": 33, + "last_update": "2024-06-14 08:08:28", + "author_account_age_days": 625 + }, + "https://github.com/Hangover3832/ComfyUI-Hangover-Recognize_Anything": { + "stars": 16, + "last_update": "2024-06-14 08:10:52", + "author_account_age_days": 625 + }, + "https://github.com/Haoming02/comfyui-clear-screen": { + "stars": 1, + "last_update": "2024-07-09 08:49:03", + "author_account_age_days": 1346 + }, + "https://github.com/Haoming02/comfyui-diffusion-cg": { + "stars": 51, + "last_update": "2024-06-14 07:10:28", + "author_account_age_days": 1346 + }, + "https://github.com/Haoming02/comfyui-floodgate": { + "stars": 25, + "last_update": "2024-07-09 09:02:07", + "author_account_age_days": 1346 + }, + "https://github.com/Haoming02/comfyui-menu-anchor": { + "stars": 3, + "last_update": "2024-07-09 10:03:10", + "author_account_age_days": 1346 + }, + "https://github.com/Haoming02/comfyui-node-beautify": { + "stars": 3, + "last_update": "2024-07-09 09:25:46", + "author_account_age_days": 1346 + }, + "https://github.com/Haoming02/comfyui-prompt-format": { + "stars": 30, + "last_update": "2024-06-14 07:12:02", + "author_account_age_days": 1346 + }, + "https://github.com/Haoming02/comfyui-tab-handler": { + "stars": 4, + "last_update": "2024-07-09 08:41:44", + "author_account_age_days": 1346 + }, + "https://github.com/HaydenReeve/ComfyUI-Better-Strings": { + "stars": 0, + "last_update": "2024-05-22 23:20:05", + "author_account_age_days": 2257 + }, + "https://github.com/HebelHuber/comfyui-enhanced-save-node": { + "stars": 1, + "last_update": "2024-06-14 08:59:28", + "author_account_age_days": 2339 + }, + "https://github.com/Hiero207/ComfyUI-Hiero-Nodes": { + "stars": 6, + "last_update": "2024-06-24 03:38:50", + "author_account_age_days": 1714 + }, + "https://github.com/Hopping-Mad-Games/ComfyUI_LiteLLM": { + "stars": 3, + "last_update": "2024-06-29 19:44:47", + "author_account_age_days": 204 + }, + "https://github.com/IDGallagher/ComfyUI-IG-Nodes": { + "stars": 1, + "last_update": "2024-06-04 00:24:47", + "author_account_age_days": 5496 + }, + "https://github.com/ITurchenko/ComfyUI-SizeFromArray": { + "stars": 0, + "last_update": "2024-05-24 14:09:58", + "author_account_age_days": 3724 + }, + "https://github.com/Intersection98/ComfyUI_MX_post_processing-nodes": { + "stars": 9, + "last_update": "2024-05-23 01:12:46", + "author_account_age_days": 2645 + }, + "https://github.com/Inzaniak/comfyui-ranbooru": { + "stars": 8, + "last_update": "2024-05-22 23:12:23", + "author_account_age_days": 3925 + }, + "https://github.com/IsItDanOrAi/ComfyUI-Stereopsis": { + "stars": 3, + "last_update": "2024-06-21 20:39:06", + "author_account_age_days": 127 + }, + "https://github.com/JPS-GER/ComfyUI_JPS-Nodes": { + "stars": 39, + "last_update": "2024-05-22 20:39:14", + "author_account_age_days": 331 + }, + "https://github.com/Jannchie/ComfyUI-J": { + "stars": 64, + "last_update": "2024-06-20 12:08:09", + "author_account_age_days": 2568 + }, + "https://github.com/JaredTherriault/ComfyUI-JNodes": { + "stars": 25, + "last_update": "2024-06-27 23:37:38", + "author_account_age_days": 3587 + }, + "https://github.com/JayLyu/ComfyUI_BaiKong_Node": { + "stars": 0, + "last_update": "2024-07-03 15:07:04", + "author_account_age_days": 3283 + }, + "https://github.com/JcandZero/ComfyUI_GLM4Node": { + "stars": 25, + "last_update": "2024-05-22 23:12:46", + "author_account_age_days": 705 + }, + "https://github.com/Jcd1230/rembg-comfyui-node": { + "stars": 123, + "last_update": "2024-05-22 17:58:34", + "author_account_age_days": 4901 + }, + "https://github.com/JerryOrbachJr/ComfyUI-RandomSize": { + "stars": 3, + "last_update": "2024-05-22 23:18:51", + "author_account_age_days": 171 + }, + "https://github.com/JettHu/ComfyUI-TCD": { + "stars": 93, + "last_update": "2024-06-03 11:40:18", + "author_account_age_days": 2373 + }, + "https://github.com/JettHu/ComfyUI_TGate": { + "stars": 49, + "last_update": "2024-05-26 08:29:23", + "author_account_age_days": 2373 + }, + "https://github.com/Jordach/comfy-plasma": { + "stars": 53, + "last_update": "2024-05-22 18:08:28", + "author_account_age_days": 4528 + }, + "https://github.com/Kaharos94/ComfyUI-Saveaswebp": { + "stars": 33, + "last_update": "2024-06-21 23:01:48", + "author_account_age_days": 1210 + }, + "https://github.com/Kangkang625/ComfyUI-paint-by-example": { + "stars": 14, + "last_update": "2024-05-22 22:20:27", + "author_account_age_days": 929 + }, + "https://github.com/KewkLW/ComfyUI-kewky_tools": { + "stars": 3, + "last_update": "2024-07-09 16:59:34", + "author_account_age_days": 1702 + }, + "https://github.com/Koishi-Star/Euler-Smea-Dyn-Sampler": { + "stars": 138, + "last_update": "2024-06-16 15:50:10", + "author_account_age_days": 1501 + }, + "https://github.com/KoreTeknology/ComfyUI-Universal-Styler": { + "stars": 14, + "last_update": "2024-06-14 10:28:10", + "author_account_age_days": 3205 + }, + "https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet": { + "stars": 443, + "last_update": "2024-07-09 01:09:21", + "author_account_age_days": 3732 + }, + "https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved": { + "stars": 2323, + "last_update": "2024-07-09 22:56:21", + "author_account_age_days": 3732 + }, + "https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite": { + "stars": 417, + "last_update": "2024-07-09 22:08:17", + "author_account_age_days": 3732 + }, + "https://github.com/KytraScript/ComfyUI_KytraWebhookHTTP": { + "stars": 3, + "last_update": "2024-05-23 00:21:43", + "author_account_age_days": 1795 + }, + "https://github.com/LEv145/images-grid-comfy-plugin": { + "stars": 130, + "last_update": "2024-05-30 17:54:32", + "author_account_age_days": 2223 + }, + "https://github.com/LZpenguin/ComfyUI-Text": { + "stars": 23, + "last_update": "2024-06-20 13:38:16", + "author_account_age_days": 1994 + }, + "https://github.com/LarryJane491/Image-Captioning-in-ComfyUI": { + "stars": 32, + "last_update": "2024-06-06 20:45:43", + "author_account_age_days": 179 + }, + "https://github.com/LarryJane491/Lora-Training-in-Comfy": { + "stars": 282, + "last_update": "2024-06-09 05:24:00", + "author_account_age_days": 179 + }, + "https://github.com/Layer-norm/comfyui-lama-remover": { + "stars": 59, + "last_update": "2024-05-25 00:12:04", + "author_account_age_days": 347 + }, + "https://github.com/Lerc/canvas_tab": { + "stars": 144, + "last_update": "2024-05-22 20:48:45", + "author_account_age_days": 5383 + }, + "https://github.com/Limitex/ComfyUI-Calculation": { + "stars": 0, + "last_update": "2024-05-22 22:18:40", + "author_account_age_days": 1290 + }, + "https://github.com/Limitex/ComfyUI-Diffusers": { + "stars": 118, + "last_update": "2024-05-22 22:18:57", + "author_account_age_days": 1290 + }, + "https://github.com/Loewen-Hob/rembg-comfyui-node-better": { + "stars": 43, + "last_update": "2024-05-23 00:32:53", + "author_account_age_days": 486 + }, + "https://github.com/LonicaMewinsky/ComfyUI-MakeFrame": { + "stars": 23, + "last_update": "2024-05-22 21:29:02", + "author_account_age_days": 991 + }, + "https://github.com/LonicaMewinsky/ComfyUI-RawSaver": { + "stars": 2, + "last_update": "2024-05-22 21:31:28", + "author_account_age_days": 991 + }, + "https://github.com/Ludobico/ComfyUI-ScenarioPrompt": { + "stars": 14, + "last_update": "2024-06-21 06:43:02", + "author_account_age_days": 1048 + }, + "https://github.com/LyazS/comfyui-anime-seg": { + "stars": 4, + "last_update": "2024-05-22 23:21:49", + "author_account_age_days": 2872 + }, + "https://github.com/M1kep/ComfyLiterals": { + "stars": 13, + "last_update": "2024-05-22 20:31:38", + "author_account_age_days": 4273 + }, + "https://github.com/M1kep/ComfyUI-KepOpenAI": { + "stars": 26, + "last_update": "2024-05-22 20:33:54", + "author_account_age_days": 4273 + }, + "https://github.com/M1kep/ComfyUI-OtherVAEs": { + "stars": 2, + "last_update": "2024-05-22 20:33:41", + "author_account_age_days": 4273 + }, + "https://github.com/M1kep/Comfy_KepKitchenSink": { + "stars": 0, + "last_update": "2024-05-22 20:33:29", + "author_account_age_days": 4273 + }, + "https://github.com/M1kep/Comfy_KepListStuff": { + "stars": 28, + "last_update": "2024-06-22 00:51:28", + "author_account_age_days": 4273 + }, + "https://github.com/M1kep/Comfy_KepMatteAnything": { + "stars": 10, + "last_update": "2024-05-22 20:33:16", + "author_account_age_days": 4273 + }, + "https://github.com/M1kep/KepPromptLang": { + "stars": 5, + "last_update": "2024-05-22 20:32:56", + "author_account_age_days": 4273 + }, + "https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes": { + "stars": 28, + "last_update": "2024-06-04 23:56:25", + "author_account_age_days": 1620 + }, + "https://github.com/Makeezi/ComfyUI-promptLAB": { + "stars": 0, + "last_update": "2024-05-23 01:24:51", + "author_account_age_days": 1797 + }, + "https://github.com/Mamaaaamooooo/batchImg-rembg-ComfyUI-nodes": { + "stars": 14, + "last_update": "2024-06-14 10:24:17", + "author_account_age_days": 397 + }, + "https://github.com/ManglerFTW/ComfyI2I": { + "stars": 146, + "last_update": "2024-06-14 11:01:01", + "author_account_age_days": 671 + }, + "https://github.com/MaraScott/ComfyUI_MaraScott_Nodes": { + "stars": 68, + "last_update": "2024-07-09 13:08:03", + "author_account_age_days": 4985 + }, + "https://github.com/MarcusNyne/m9-prompts-comfyui": { + "stars": 1, + "last_update": "2024-06-14 15:25:15", + "author_account_age_days": 1438 + }, + "https://github.com/MariusKM/ComfyUI-BadmanNodes": { + "stars": 1, + "last_update": "2024-06-21 15:20:22", + "author_account_age_days": 2246 + }, + "https://github.com/MarkoCa1/ComfyUI-Text": { + "stars": 2, + "last_update": "2024-05-23 00:15:39", + "author_account_age_days": 1648 + }, + "https://github.com/MarkoCa1/ComfyUI_Segment_Mask": { + "stars": 16, + "last_update": "2024-05-23 00:15:51", + "author_account_age_days": 1648 + }, + "https://github.com/Mason-McGough/ComfyUI-Mosaica": { + "stars": 4, + "last_update": "2024-05-29 12:57:49", + "author_account_age_days": 3221 + }, + "https://github.com/MilitantHitchhiker/MilitantHitchhiker-SwitchbladePack": { + "stars": 3, + "last_update": "2024-06-24 22:04:33", + "author_account_age_days": 75 + }, + "https://github.com/Millyarde/Pomfy": { + "stars": 7, + "last_update": "2024-05-22 22:22:48", + "author_account_age_days": 922 + }, + "https://github.com/MinusZoneAI/ComfyUI-Prompt-MZ": { + "stars": 75, + "last_update": "2024-07-07 14:51:07", + "author_account_age_days": 81 + }, + "https://github.com/MinusZoneAI/ComfyUI-StylizePhoto-MZ": { + "stars": 17, + "last_update": "2024-05-23 01:13:32", + "author_account_age_days": 81 + }, + "https://github.com/MinusZoneAI/ComfyUI-TrainTools-MZ": { + "stars": 17, + "last_update": "2024-07-09 12:42:11", + "author_account_age_days": 81 + }, + "https://github.com/Miosp/ComfyUI-FBCNN": { + "stars": 5, + "last_update": "2024-05-24 12:13:08", + "author_account_age_days": 2531 + }, + "https://github.com/MitoshiroPJ/comfyui_slothful_attention": { + "stars": 6, + "last_update": "2024-05-22 22:09:15", + "author_account_age_days": 3983 + }, + "https://github.com/MokkaBoss1/ComfyUI_Mokkaboss1": { + "stars": 16, + "last_update": "2024-07-08 18:34:18", + "author_account_age_days": 395 + }, + "https://github.com/MrForExample/ComfyUI-3D-Pack": { + "stars": 1749, + "last_update": "2024-07-09 23:18:25", + "author_account_age_days": 1576 + }, + "https://github.com/MrForExample/ComfyUI-AnimateAnyone-Evolved": { + "stars": 444, + "last_update": "2024-06-14 12:02:47", + "author_account_age_days": 1576 + }, + "https://github.com/MrSamSeen/ComfyUI_SSStereoscope": { + "stars": 5, + "last_update": "2024-07-08 20:40:49", + "author_account_age_days": 3606 + }, + "https://github.com/Munkyfoot/ComfyUI-TextOverlay": { + "stars": 5, + "last_update": "2024-06-28 05:57:03", + "author_account_age_days": 3060 + }, + "https://github.com/Nestorchik/NStor-ComfyUI-Translation": { + "stars": 1, + "last_update": "2024-06-14 10:25:32", + "author_account_age_days": 1340 + }, + "https://github.com/NeuralSamurAI/Comfyui-Superprompt-Unofficial": { + "stars": 57, + "last_update": "2024-05-23 00:22:08", + "author_account_age_days": 109 + }, + "https://github.com/Nevysha/ComfyUI-nevysha-top-menu": { + "stars": 5, + "last_update": "2024-05-23 00:17:31", + "author_account_age_days": 542 + }, + "https://github.com/NicholasMcCarthy/ComfyUI_TravelSuite": { + "stars": 13, + "last_update": "2024-05-22 20:34:46", + "author_account_age_days": 5165 + }, + "https://github.com/NimaNzrii/comfyui-photoshop": { + "stars": 276, + "last_update": "2024-07-09 08:17:57", + "author_account_age_days": 260 + }, + "https://github.com/NimaNzrii/comfyui-popup_preview": { + "stars": 35, + "last_update": "2024-05-22 22:12:04", + "author_account_age_days": 260 + }, + "https://github.com/Niutonian/ComfyUi-NoodleWebcam": { + "stars": 28, + "last_update": "2024-05-22 21:30:40", + "author_account_age_days": 1057 + }, + "https://github.com/Nlar/ComfyUI_CartoonSegmentation": { + "stars": 10, + "last_update": "2024-05-22 23:15:37", + "author_account_age_days": 3846 + }, + "https://github.com/NotHarroweD/Harronode": { + "stars": 5, + "last_update": "2024-05-22 22:18:29", + "author_account_age_days": 1999 + }, + "https://github.com/Nourepide/ComfyUI-Allor": { + "stars": 180, + "last_update": "2024-05-22 18:11:17", + "author_account_age_days": 2861 + }, + "https://github.com/Nuked88/ComfyUI-N-Nodes": { + "stars": 177, + "last_update": "2024-05-21 19:52:44", + "author_account_age_days": 4495 + }, + "https://github.com/Nuked88/ComfyUI-N-Sidebar": { + "stars": 412, + "last_update": "2024-07-05 18:21:44", + "author_account_age_days": 4495 + }, + "https://github.com/Off-Live/ComfyUI-off-suite": { + "stars": 0, + "last_update": "2024-06-14 12:02:25", + "author_account_age_days": 1187 + }, + "https://github.com/OpenArt-AI/ComfyUI-Assistant": { + "stars": 14, + "last_update": "2024-05-22 22:16:57", + "author_account_age_days": 790 + }, + "https://github.com/PCMonsterx/ComfyUI-CSV-Loader": { + "stars": 11, + "last_update": "2024-05-22 21:27:10", + "author_account_age_days": 1680 + }, + "https://github.com/ParisNeo/lollms_nodes_suite": { + "stars": 10, + "last_update": "2024-06-23 21:04:43", + "author_account_age_days": 4785 + }, + "https://github.com/ParmanBabra/ComfyUI-Malefish-Custom-Scripts": { + "stars": 0, + "last_update": "2024-05-22 21:26:35", + "author_account_age_days": 3658 + }, + "https://github.com/Pfaeff/pfaeff-comfyui": { + "stars": 19, + "last_update": "2024-05-22 18:21:10", + "author_account_age_days": 3223 + }, + "https://github.com/PnthrLeo/comfyUI-image-search": { + "stars": 0, + "last_update": "2024-06-14 07:06:45", + "author_account_age_days": 2567 + }, + "https://github.com/Pos13/comfyui-cyclist": { + "stars": 31, + "last_update": "2024-06-19 09:21:53", + "author_account_age_days": 1533 + }, + "https://github.com/QaisMalkawi/ComfyUI-QaisHelper": { + "stars": 2, + "last_update": "2024-05-23 20:29:30", + "author_account_age_days": 1266 + }, + "https://github.com/RedRayz/ComfyUI-Danbooru-To-WD": { + "stars": 2, + "last_update": "2024-06-24 18:20:48", + "author_account_age_days": 1380 + }, + "https://github.com/RenderRift/ComfyUI-RenderRiftNodes": { + "stars": 6, + "last_update": "2024-05-22 22:16:41", + "author_account_age_days": 202 + }, + "https://github.com/RomanKuschanow/ComfyUI-Advanced-Latent-Control": { + "stars": 16, + "last_update": "2024-06-21 07:29:14", + "author_account_age_days": 1397 + }, + "https://github.com/Ron-Digital/ComfyUI-SceneGenerator": { + "stars": 2, + "last_update": "2024-06-28 19:36:30", + "author_account_age_days": 944 + }, + "https://github.com/Ryuukeisyou/comfyui_face_parsing": { + "stars": 52, + "last_update": "2024-07-03 12:48:31", + "author_account_age_days": 2428 + }, + "https://github.com/Ryuukeisyou/comfyui_io_helpers": { + "stars": 1, + "last_update": "2024-05-22 22:22:59", + "author_account_age_days": 2428 + }, + "https://github.com/SEkINVR/ComfyUI-Save-Multi-Format": { + "stars": 1, + "last_update": "2024-07-08 03:39:48", + "author_account_age_days": 672 + }, + "https://github.com/SEkINVR/ComfyUI-SaveAs": { + "stars": 1, + "last_update": "2024-07-08 03:39:48", + "author_account_age_days": 672 + }, + "https://github.com/SLAPaper/ComfyUI-Image-Selector": { + "stars": 61, + "last_update": "2024-05-24 17:03:46", + "author_account_age_days": 3713 + }, + "https://github.com/SLAPaper/ComfyUI-dpmpp_2m_alt-Sampler": { + "stars": 8, + "last_update": "2024-06-18 19:22:50", + "author_account_age_days": 3713 + }, + "https://github.com/SOELexicon/ComfyUI-LexMSDBNodes": { + "stars": 4, + "last_update": "2024-06-28 19:20:36", + "author_account_age_days": 4099 + }, + "https://github.com/SOELexicon/ComfyUI-LexTools": { + "stars": 25, + "last_update": "2024-06-28 19:25:13", + "author_account_age_days": 4099 + }, + "https://github.com/SamKhoze/ComfyUI-DeepFuze": { + "stars": 223, + "last_update": "2024-07-09 18:11:33", + "author_account_age_days": 1458 + }, + "https://github.com/SayanoAI/Comfy-RVC": { + "stars": 2, + "last_update": "2024-06-25 02:50:53", + "author_account_age_days": 2619 + }, + "https://github.com/Scholar01/ComfyUI-Keyframe": { + "stars": 10, + "last_update": "2024-06-14 09:01:30", + "author_account_age_days": 3211 + }, + "https://github.com/Scorpinaus/ComfyUI-DiffusersLoader": { + "stars": 5, + "last_update": "2024-06-23 01:30:57", + "author_account_age_days": 1125 + }, + "https://github.com/ScreamingHawk/comfyui-ollama-prompt-encode": { + "stars": 5, + "last_update": "2024-06-26 00:07:10", + "author_account_age_days": 4521 + }, + "https://github.com/SeaArtLab/ComfyUI-Long-CLIP": { + "stars": 63, + "last_update": "2024-06-14 08:08:26", + "author_account_age_days": 92 + }, + "https://github.com/SeargeDP/SeargeSDXL": { + "stars": 750, + "last_update": "2024-05-22 00:28:26", + "author_account_age_days": 4187 + }, + "https://github.com/Seedsa/Fooocus_Nodes": { + "stars": 43, + "last_update": "2024-07-03 07:51:13", + "author_account_age_days": 2623 + }, + "https://github.com/Shadetail/ComfyUI_Eagleshadow": { + "stars": 1, + "last_update": "2024-06-15 13:04:49", + "author_account_age_days": 3413 + }, + "https://github.com/SherryXieYuchen/ComfyUI-Image-Inpainting": { + "stars": 3, + "last_update": "2024-07-03 03:39:49", + "author_account_age_days": 130 + }, + "https://github.com/Shibiko-AI/ShibikoAI-ComfyUI-Tools": { + "stars": 8, + "last_update": "2024-07-04 02:22:10", + "author_account_age_days": 417 + }, + "https://github.com/ShmuelRonen/ComfyUI-SVDResizer": { + "stars": 2, + "last_update": "2024-06-14 11:50:52", + "author_account_age_days": 1220 + }, + "https://github.com/ShmuelRonen/ComfyUI_Gemini_Flash": { + "stars": 9, + "last_update": "2024-06-15 17:12:05", + "author_account_age_days": 1220 + }, + "https://github.com/ShmuelRonen/ComfyUI_wav2lip": { + "stars": 55, + "last_update": "2024-07-03 11:25:27", + "author_account_age_days": 1220 + }, + "https://github.com/Shraknard/ComfyUI-Remover": { + "stars": 4, + "last_update": "2024-05-22 23:15:06", + "author_account_age_days": 2332 + }, + "https://github.com/Siberpone/lazy-pony-prompter": { + "stars": 25, + "last_update": "2024-07-08 15:39:40", + "author_account_age_days": 468 + }, + "https://github.com/Smirnov75/ComfyUI-mxToolkit": { + "stars": 60, + "last_update": "2024-06-21 19:22:42", + "author_account_age_days": 1527 + }, + "https://github.com/Smuzzies/comfyui_meme_maker": { + "stars": 0, + "last_update": "2024-07-05 22:01:41", + "author_account_age_days": 707 + }, + "https://github.com/SoftMeng/ComfyUI_ImageToText": { + "stars": 6, + "last_update": "2024-06-14 08:08:36", + "author_account_age_days": 3539 + }, + "https://github.com/SoftMeng/ComfyUI_Mexx_Poster": { + "stars": 16, + "last_update": "2024-06-14 07:06:27", + "author_account_age_days": 3539 + }, + "https://github.com/SoftMeng/ComfyUI_Mexx_Styler": { + "stars": 18, + "last_update": "2024-06-14 07:09:03", + "author_account_age_days": 3539 + }, + "https://github.com/Sorcerio/MBM-Music-Visualizer": { + "stars": 15, + "last_update": "2024-05-23 01:09:18", + "author_account_age_days": 4262 + }, + "https://github.com/SozeInc/ComfyUI-Mobile": { + "stars": 0, + "last_update": "2024-06-14 07:09:00", + "author_account_age_days": 95 + }, + "https://github.com/SpaceKendo/ComfyUI-svd_txt2vid": { + "stars": 6, + "last_update": "2024-05-22 22:11:52", + "author_account_age_days": 223 + }, + "https://github.com/Stability-AI/ComfyUI-SAI_API": { + "stars": 41, + "last_update": "2024-06-06 14:18:15", + "author_account_age_days": 858 + }, + "https://github.com/Stability-AI/stability-ComfyUI-nodes": { + "stars": 183, + "last_update": "2024-05-22 15:30:47", + "author_account_age_days": 858 + }, + "https://github.com/StartHua/ComfyUI_OOTDiffusion_CXH": { + "stars": 95, + "last_update": "2024-06-14 08:12:12", + "author_account_age_days": 2850 + }, + "https://github.com/StartHua/ComfyUI_PCDMs": { + "stars": 3, + "last_update": "2024-05-22 23:21:14", + "author_account_age_days": 2850 + }, + "https://github.com/StartHua/ComfyUI_Seg_VITON": { + "stars": 174, + "last_update": "2024-05-22 23:20:17", + "author_account_age_days": 2850 + }, + "https://github.com/StartHua/Comfyui_joytag": { + "stars": 19, + "last_update": "2024-05-22 23:20:28", + "author_account_age_days": 2850 + }, + "https://github.com/StartHua/Comfyui_segformer_b2_clothes": { + "stars": 42, + "last_update": "2024-05-22 23:20:39", + "author_account_age_days": 2850 + }, + "https://github.com/SuperBeastsAI/ComfyUI-SuperBeasts": { + "stars": 111, + "last_update": "2024-06-01 20:27:53", + "author_account_age_days": 104 + }, + "https://github.com/SuperMasterBlasterLaser/ComfyUI_YOLO_Classifiers": { + "stars": 1, + "last_update": "2024-06-20 15:06:51", + "author_account_age_days": 3593 + }, + "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes": { + "stars": 502, + "last_update": "2024-07-09 14:21:47", + "author_account_age_days": 2165 + }, + "https://github.com/Sxela/ComfyWarp": { + "stars": 21, + "last_update": "2024-05-22 20:47:11", + "author_account_age_days": 3387 + }, + "https://github.com/TGu-97/ComfyUI-TGu-utils": { + "stars": 1, + "last_update": "2024-05-22 21:07:45", + "author_account_age_days": 545 + }, + "https://github.com/THtianhao/ComfyUI-FaceChain": { + "stars": 88, + "last_update": "2024-06-25 02:59:28", + "author_account_age_days": 3706 + }, + "https://github.com/THtianhao/ComfyUI-Portrait-Maker": { + "stars": 170, + "last_update": "2024-05-22 21:18:05", + "author_account_age_days": 3706 + }, + "https://github.com/TJ16th/comfyUI_TJ_NormalLighting": { + "stars": 129, + "last_update": "2024-05-23 00:25:37", + "author_account_age_days": 2550 + }, + "https://github.com/TMElyralab/Comfyui-MusePose": { + "stars": 296, + "last_update": "2024-06-22 07:09:49", + "author_account_age_days": 112 + }, + "https://github.com/TRI3D-LC/ComfyUI-MiroBoard": { + "stars": 4, + "last_update": "2024-07-02 16:21:56", + "author_account_age_days": 454 + }, + "https://github.com/TRI3D-LC/tri3d-comfyui-nodes": { + "stars": 19, + "last_update": "2024-07-05 08:16:25", + "author_account_age_days": 454 + }, + "https://github.com/TW-CUI/TW-CUI-Util": { + "stars": 1, + "last_update": "2024-06-17 03:03:57", + "author_account_age_days": 46 + }, + "https://github.com/TaiTair/comfyui-simswap": { + "stars": 9, + "last_update": "2024-05-28 21:58:53", + "author_account_age_days": 3582 + }, + "https://github.com/Taremin/comfyui-prompt-extranetworks": { + "stars": 2, + "last_update": "2024-05-22 23:08:34", + "author_account_age_days": 2230 + }, + "https://github.com/Taremin/comfyui-string-tools": { + "stars": 1, + "last_update": "2024-05-22 23:08:45", + "author_account_age_days": 2230 + }, + "https://github.com/Taremin/webui-monaco-prompt": { + "stars": 24, + "last_update": "2024-05-23 13:58:57", + "author_account_age_days": 2230 + }, + "https://github.com/TeaCrab/ComfyUI-TeaNodes": { + "stars": 4, + "last_update": "2024-05-22 20:44:05", + "author_account_age_days": 3233 + }, + "https://github.com/TemryL/ComfyS3": { + "stars": 18, + "last_update": "2024-07-09 02:43:13", + "author_account_age_days": 884 + }, + "https://github.com/TemryL/ComfyUI-IDM-VTON": { + "stars": 231, + "last_update": "2024-07-06 10:12:20", + "author_account_age_days": 884 + }, + "https://github.com/TencentQQGYLab/ComfyUI-ELLA": { + "stars": 298, + "last_update": "2024-05-07 03:07:38", + "author_account_age_days": 113 + }, + "https://github.com/TheBarret/ZSuite": { + "stars": 6, + "last_update": "2024-06-25 10:19:11", + "author_account_age_days": 2728 + }, + "https://github.com/TheBill2001/comfyui-upscale-by-model": { + "stars": 2, + "last_update": "2024-06-18 17:57:06", + "author_account_age_days": 1457 + }, + "https://github.com/TheMistoAI/ComfyUI-Anyline": { + "stars": 292, + "last_update": "2024-07-09 11:01:15", + "author_account_age_days": 180 + }, + "https://github.com/ThereforeGames/ComfyUI-Unprompted": { + "stars": 8, + "last_update": "2024-06-23 21:38:03", + "author_account_age_days": 950 + }, + "https://github.com/TinyTerra/ComfyUI_tinyterraNodes": { + "stars": 334, + "last_update": "2024-07-01 23:43:02", + "author_account_age_days": 636 + }, + "https://github.com/TripleHeadedMonkey/ComfyUI_MileHighStyler": { + "stars": 19, + "last_update": "2024-05-22 22:13:06", + "author_account_age_days": 876 + }, + "https://github.com/Tropfchen/ComfyUI-Embedding_Picker": { + "stars": 28, + "last_update": "2024-05-24 20:02:20", + "author_account_age_days": 3869 + }, + "https://github.com/Tropfchen/ComfyUI-yaResolutionSelector": { + "stars": 8, + "last_update": "2024-05-24 19:48:43", + "author_account_age_days": 3869 + }, + "https://github.com/Trung0246/ComfyUI-0246": { + "stars": 93, + "last_update": "2024-05-24 03:45:59", + "author_account_age_days": 3395 + }, + "https://github.com/Ttl/ComfyUi_NNLatentUpscale": { + "stars": 173, + "last_update": "2024-05-22 20:50:03", + "author_account_age_days": 4937 + }, + "https://github.com/TylerZoro/SD3-Scaling": { + "stars": 1, + "last_update": "2024-06-15 16:59:22", + "author_account_age_days": 1301 + }, + "https://github.com/Umikaze-job/select_folder_path_easy": { + "stars": 4, + "last_update": "2024-05-22 21:30:13", + "author_account_age_days": 234 + }, + "https://github.com/VAST-AI-Research/ComfyUI-Tripo": { + "stars": 72, + "last_update": "2024-05-23 01:11:56", + "author_account_age_days": 257 + }, + "https://github.com/WASasquatch/ASTERR": { + "stars": 14, + "last_update": "2024-06-17 00:49:59", + "author_account_age_days": 4641 + }, + "https://github.com/WASasquatch/ComfyUI_Preset_Merger": { + "stars": 24, + "last_update": "2024-06-17 00:52:28", + "author_account_age_days": 4641 + }, + "https://github.com/WASasquatch/FreeU_Advanced": { + "stars": 102, + "last_update": "2024-06-17 04:40:22", + "author_account_age_days": 4641 + }, + "https://github.com/WASasquatch/PPF_Noise_ComfyUI": { + "stars": 20, + "last_update": "2024-06-14 10:27:23", + "author_account_age_days": 4641 + }, + "https://github.com/WASasquatch/PowerNoiseSuite": { + "stars": 57, + "last_update": "2024-06-17 01:40:44", + "author_account_age_days": 4641 + }, + "https://github.com/WASasquatch/WAS_Extras": { + "stars": 27, + "last_update": "2024-06-17 04:08:37", + "author_account_age_days": 4641 + }, + "https://github.com/WASasquatch/was-node-suite-comfyui": { + "stars": 968, + "last_update": "2024-07-09 19:34:38", + "author_account_age_days": 4641 + }, + "https://github.com/WebDev9000/WebDev9000-Nodes": { + "stars": 1, + "last_update": "2024-06-14 10:28:22", + "author_account_age_days": 3767 + }, + "https://github.com/Wicloz/ComfyUI-Simply-Nodes": { + "stars": 1, + "last_update": "2024-07-06 22:35:50", + "author_account_age_days": 3659 + }, + "https://github.com/XmYx/deforum-comfy-nodes": { + "stars": 125, + "last_update": "2024-07-08 19:39:48", + "author_account_age_days": 2621 + }, + "https://github.com/Xyem/Xycuno-Oobabooga": { + "stars": 3, + "last_update": "2024-05-23 00:14:14", + "author_account_age_days": 4340 + }, + "https://github.com/YMC-GitHub/ymc-node-suite-comfyui": { + "stars": 16, + "last_update": "2024-05-22 21:15:51", + "author_account_age_days": 2710 + }, + "https://github.com/YOUR-WORST-TACO/ComfyUI-TacoNodes": { + "stars": 14, + "last_update": "2024-05-22 20:48:23", + "author_account_age_days": 3771 + }, + "https://github.com/Yanick112/ComfyUI-ToSVG": { + "stars": 15, + "last_update": "2024-06-14 14:00:22", + "author_account_age_days": 829 + }, + "https://github.com/YinBailiang/MergeBlockWeighted_fo_ComfyUI": { + "stars": 14, + "last_update": "2024-07-01 09:03:34", + "author_account_age_days": 801 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR": { + "stars": 319, + "last_update": "2024-05-22 14:14:46", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Animated-optical-illusions": { + "stars": 18, + "last_update": "2024-06-14 07:06:15", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-ArtGallery": { + "stars": 366, + "last_update": "2024-06-12 04:40:50", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BRIA_AI-RMBG": { + "stars": 575, + "last_update": "2024-05-22 14:14:18", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BiRefNet-ZHO": { + "stars": 159, + "last_update": "2024-06-27 03:38:19", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-DepthFM": { + "stars": 68, + "last_update": "2024-05-22 14:14:03", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Gemini": { + "stars": 605, + "last_update": "2024-05-22 14:15:11", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-InstantID": { + "stars": 1225, + "last_update": "2024-05-22 13:57:55", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Phi-3-mini": { + "stars": 181, + "last_update": "2024-06-30 08:41:40", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PhotoMaker-ZHO": { + "stars": 755, + "last_update": "2024-05-22 14:13:49", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PixArt-alpha-Diffusers": { + "stars": 44, + "last_update": "2024-05-22 13:40:58", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Q-Align": { + "stars": 3, + "last_update": "2024-05-22 14:15:52", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-2": { + "stars": 61, + "last_update": "2024-06-14 12:02:55", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-VL-API": { + "stars": 182, + "last_update": "2024-05-22 14:14:57", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SVD-ZHO": { + "stars": 95, + "last_update": "2024-05-22 13:40:44", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SegMoE": { + "stars": 74, + "last_update": "2024-05-22 13:41:14", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Text_Image-Composite": { + "stars": 84, + "last_update": "2024-05-31 12:03:55", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM": { + "stars": 488, + "last_update": "2024-05-22 13:01:07", + "author_account_age_days": 355 + }, + "https://github.com/ZHO-ZHO-ZHO/comfyui-portrait-master-zh-cn": { + "stars": 1495, + "last_update": "2024-06-14 09:00:04", + "author_account_age_days": 355 + }, + "https://github.com/ZZXYWQ/ComfyUI-ZZXYWQ": { + "stars": 3, + "last_update": "2024-07-09 12:37:59", + "author_account_age_days": 1288 + }, + "https://github.com/ZaneA/ComfyUI-ImageReward": { + "stars": 22, + "last_update": "2024-07-01 21:25:12", + "author_account_age_days": 5555 + }, + "https://github.com/ZeDarkAdam/ComfyUI-Embeddings-Tools": { + "stars": 2, + "last_update": "2024-06-23 19:19:40", + "author_account_age_days": 1209 + }, + "https://github.com/Zuellni/ComfyUI-Custom-Nodes": { + "stars": 44, + "last_update": "2023-09-19 12:11:26", + "author_account_age_days": 538 + }, + "https://github.com/Zuellni/ComfyUI-ExLlama": { + "stars": 101, + "last_update": "2024-06-26 14:01:12", + "author_account_age_days": 538 + }, + "https://github.com/Zuellni/ComfyUI-ExLlama-Nodes": { + "stars": 101, + "last_update": "2024-06-26 14:01:12", + "author_account_age_days": 538 + }, + "https://github.com/Zuellni/ComfyUI-PickScore-Nodes": { + "stars": 25, + "last_update": "2024-06-15 08:23:16", + "author_account_age_days": 538 + }, + "https://github.com/a1lazydog/ComfyUI-AudioScheduler": { + "stars": 92, + "last_update": "2024-06-14 11:02:32", + "author_account_age_days": 4817 + }, + "https://github.com/aburahamu/ComfyUI-IsNiceParts": { + "stars": 2, + "last_update": "2024-06-14 12:01:40", + "author_account_age_days": 88 + }, + "https://github.com/aburahamu/ComfyUI-RequestsPoster": { + "stars": 2, + "last_update": "2024-06-14 13:59:24", + "author_account_age_days": 88 + }, + "https://github.com/abyz22/image_control": { + "stars": 14, + "last_update": "2024-05-22 23:10:07", + "author_account_age_days": 178 + }, + "https://github.com/adbrasi/ComfyUI-TrashNodes-DownloadHuggingface": { + "stars": 4, + "last_update": "2024-05-22 23:24:45", + "author_account_age_days": 719 + }, + "https://github.com/adieyal/comfyui-dynamicprompts": { + "stars": 190, + "last_update": "2024-07-09 14:21:09", + "author_account_age_days": 5032 + }, + "https://github.com/adigayung/ComfyUI-Translator": { + "stars": 0, + "last_update": "2024-07-09 11:47:13", + "author_account_age_days": 228 + }, + "https://github.com/adriflex/ComfyUI_Blender_Texdiff": { + "stars": 1, + "last_update": "2024-05-22 23:14:18", + "author_account_age_days": 2237 + }, + "https://github.com/aegis72/aegisflow_utility_nodes": { + "stars": 24, + "last_update": "2024-05-22 22:10:29", + "author_account_age_days": 599 + }, + "https://github.com/aegis72/comfyui-styles-all": { + "stars": 34, + "last_update": "2024-05-22 22:10:41", + "author_account_age_days": 599 + }, + "https://github.com/ai-liam/comfyui-liam": { + "stars": 2, + "last_update": "2024-06-22 03:27:52", + "author_account_age_days": 1536 + }, + "https://github.com/ai-liam/comfyui_liam_util": { + "stars": 2, + "last_update": "2024-05-22 22:21:23", + "author_account_age_days": 1536 + }, + "https://github.com/aianimation55/ComfyUI-FatLabels": { + "stars": 4, + "last_update": "2024-05-22 21:26:01", + "author_account_age_days": 289 + }, + "https://github.com/al-swaiti/ComfyUI-CascadeResolutions": { + "stars": 2, + "last_update": "2024-06-29 17:12:23", + "author_account_age_days": 945 + }, + "https://github.com/alessandrozonta/ComfyUI-CenterNode": { + "stars": 3, + "last_update": "2024-05-23 01:17:52", + "author_account_age_days": 1212 + }, + "https://github.com/alessandrozonta/ComfyUI-Layers": { + "stars": 28, + "last_update": "2024-06-14 09:04:36", + "author_account_age_days": 1212 + }, + "https://github.com/alessandrozonta/ComfyUI-OpenPose": { + "stars": 2, + "last_update": "2024-06-14 13:59:36", + "author_account_age_days": 1212 + }, + "https://github.com/alexopus/ComfyUI-Image-Saver": { + "stars": 31, + "last_update": "2024-06-29 19:31:28", + "author_account_age_days": 2695 + }, + "https://github.com/ali1234/comfyui-job-iterator": { + "stars": 64, + "last_update": "2024-05-22 20:54:21", + "author_account_age_days": 4875 + }, + "https://github.com/alisson-anjos/ComfyUI-Ollama-Describer": { + "stars": 38, + "last_update": "2024-06-29 16:19:33", + "author_account_age_days": 616 + }, + "https://github.com/alpertunga-bile/prompt-generator-comfyui": { + "stars": 66, + "last_update": "2024-07-01 09:08:11", + "author_account_age_days": 1288 + }, + "https://github.com/alsritter/asymmetric-tiling-comfyui": { + "stars": 14, + "last_update": "2024-05-22 20:43:07", + "author_account_age_days": 2009 + }, + "https://github.com/alt-key-project/comfyui-dream-project": { + "stars": 73, + "last_update": "2024-07-01 05:34:14", + "author_account_age_days": 675 + }, + "https://github.com/alt-key-project/comfyui-dream-video-batches": { + "stars": 53, + "last_update": "2024-07-01 05:37:03", + "author_account_age_days": 675 + }, + "https://github.com/an90ray/ComfyUI_RErouter_CustomNodes": { + "stars": 0, + "last_update": "2024-05-22 22:21:00", + "author_account_age_days": 204 + }, + "https://github.com/andersxa/comfyui-PromptAttention": { + "stars": 22, + "last_update": "2024-06-20 11:09:25", + "author_account_age_days": 2968 + }, + "https://github.com/angeloshredder/StableCascadeResizer": { + "stars": 2, + "last_update": "2024-05-23 00:12:55", + "author_account_age_days": 1844 + }, + "https://github.com/ansonkao/comfyui-geometry": { + "stars": 7, + "last_update": "2024-06-14 09:03:19", + "author_account_age_days": 361 + }, + "https://github.com/antrobot1234/antrobots-comfyUI-nodepack": { + "stars": 9, + "last_update": "2024-05-28 14:44:16", + "author_account_age_days": 2878 + }, + "https://github.com/aria1th/ComfyUI-LogicUtils": { + "stars": 21, + "last_update": "2024-05-23 01:27:16", + "author_account_age_days": 2360 + }, + "https://github.com/asagi4/ComfyUI-Adaptive-Guidance": { + "stars": 5, + "last_update": "2024-07-03 13:54:53", + "author_account_age_days": 456 + }, + "https://github.com/asagi4/ComfyUI-CADS": { + "stars": 33, + "last_update": "2024-05-23 18:14:56", + "author_account_age_days": 456 + }, + "https://github.com/asagi4/comfyui-prompt-control": { + "stars": 166, + "last_update": "2024-06-20 13:48:26", + "author_account_age_days": 456 + }, + "https://github.com/asagi4/comfyui-utility-nodes": { + "stars": 7, + "last_update": "2024-05-25 11:40:49", + "author_account_age_days": 456 + }, + "https://github.com/aszc-dev/ComfyUI-CoreMLSuite": { + "stars": 93, + "last_update": "2024-07-04 06:44:42", + "author_account_age_days": 2742 + }, + "https://github.com/atmaranto/ComfyUI-SaveAsScript": { + "stars": 52, + "last_update": "2024-06-14 09:01:17", + "author_account_age_days": 2364 + }, + "https://github.com/audioscavenger/ComfyUI-Thumbnails": { + "stars": 10, + "last_update": "2024-06-07 07:19:30", + "author_account_age_days": 4136 + }, + "https://github.com/audioscavenger/save-image-extended-comfyui": { + "stars": 21, + "last_update": "2024-06-27 18:28:01", + "author_account_age_days": 4136 + }, + "https://github.com/avatechai/avatar-graph-comfyui": { + "stars": 219, + "last_update": "2024-05-22 21:14:14", + "author_account_age_days": 869 + }, + "https://github.com/aws-samples/comfyui-llm-node-for-amazon-bedrock": { + "stars": 5, + "last_update": "2024-06-12 15:04:39", + "author_account_age_days": 3574 + }, + "https://github.com/azure-dragon-ai/ComfyUI-ClipScore-Nodes": { + "stars": 2, + "last_update": "2024-05-22 23:16:28", + "author_account_age_days": 316 + }, + "https://github.com/badayvedat/ComfyUI-fal-Connector": { + "stars": 12, + "last_update": "2024-07-01 07:54:24", + "author_account_age_days": 1786 + }, + "https://github.com/badjeff/comfyui_lora_tag_loader": { + "stars": 43, + "last_update": "2024-05-22 20:40:03", + "author_account_age_days": 5378 + }, + "https://github.com/baicai99/ComfyUI-FrameSkipping": { + "stars": 6, + "last_update": "2024-06-18 10:25:55", + "author_account_age_days": 846 + }, + "https://github.com/banodoco/steerable-motion": { + "stars": 752, + "last_update": "2024-06-15 23:01:54", + "author_account_age_days": 417 + }, + "https://github.com/bash-j/mikey_nodes": { + "stars": 83, + "last_update": "2024-06-15 10:31:20", + "author_account_age_days": 4202 + }, + "https://github.com/bedovyy/ComfyUI_NAIDGenerator": { + "stars": 18, + "last_update": "2024-06-14 09:04:39", + "author_account_age_days": 378 + }, + "https://github.com/bilal-arikan/ComfyUI_TextAssets": { + "stars": 2, + "last_update": "2024-05-22 23:23:50", + "author_account_age_days": 3523 + }, + "https://github.com/bitaffinity/ComfyUI_HF_Inference": { + "stars": 0, + "last_update": "2024-06-14 10:23:29", + "author_account_age_days": 72 + }, + "https://github.com/blepping/ComfyUI-bleh": { + "stars": 31, + "last_update": "2024-05-22 23:17:49", + "author_account_age_days": 169 + }, + "https://github.com/blepping/ComfyUI-sonar": { + "stars": 31, + "last_update": "2024-05-22 23:18:26", + "author_account_age_days": 169 + }, + "https://github.com/blepping/comfyui_jankhidiffusion": { + "stars": 93, + "last_update": "2024-05-22 23:18:40", + "author_account_age_days": 169 + }, + "https://github.com/blueraincoatli/comfyUI_SillyNodes": { + "stars": 3, + "last_update": "2024-06-09 13:30:57", + "author_account_age_days": 328 + }, + "https://github.com/bluevisor/ComfyUI_PS_Blend_Node": { + "stars": 1, + "last_update": "2024-07-08 12:38:26", + "author_account_age_days": 4582 + }, + "https://github.com/bmad4ever/ComfyUI-Bmad-DirtyUndoRedo": { + "stars": 50, + "last_update": "2024-05-22 18:11:51", + "author_account_age_days": 3552 + }, + "https://github.com/bmad4ever/comfyui_ab_samplercustom": { + "stars": 5, + "last_update": "2024-06-21 00:02:39", + "author_account_age_days": 3552 + }, + "https://github.com/bmad4ever/comfyui_bmad_nodes": { + "stars": 48, + "last_update": "2024-06-13 10:42:09", + "author_account_age_days": 3552 + }, + "https://github.com/bmad4ever/comfyui_lists_cartesian_product": { + "stars": 3, + "last_update": "2024-05-22 20:18:07", + "author_account_age_days": 3552 + }, + "https://github.com/bmad4ever/comfyui_quilting": { + "stars": 3, + "last_update": "2024-07-09 17:19:48", + "author_account_age_days": 3552 + }, + "https://github.com/bmad4ever/comfyui_wfc_like": { + "stars": 5, + "last_update": "2024-06-02 23:06:37", + "author_account_age_days": 3552 + }, + "https://github.com/bobmagicii/comfykit-custom-nodes": { + "stars": 1, + "last_update": "2024-06-04 20:04:00", + "author_account_age_days": 4760 + }, + "https://github.com/bradsec/ComfyUI_ResolutionSelector": { + "stars": 8, + "last_update": "2024-07-07 12:15:49", + "author_account_age_days": 3671 + }, + "https://github.com/bradsec/ComfyUI_StringTools": { + "stars": 0, + "last_update": "2024-07-08 10:20:27", + "author_account_age_days": 3671 + }, + "https://github.com/braintacles/braintacles-comfyui-nodes": { + "stars": 1, + "last_update": "2024-05-23 06:06:16", + "author_account_age_days": 446 + }, + "https://github.com/brianfitzgerald/style_aligned_comfy": { + "stars": 259, + "last_update": "2024-05-30 14:23:40", + "author_account_age_days": 4255 + }, + "https://github.com/bronkula/comfyui-fitsize": { + "stars": 35, + "last_update": "2024-05-22 21:32:34", + "author_account_age_days": 5170 + }, + "https://github.com/bruefire/ComfyUI-SeqImageLoader": { + "stars": 28, + "last_update": "2024-06-08 15:48:49", + "author_account_age_days": 2381 + }, + "https://github.com/budihartono/comfyui_otonx_nodes": { + "stars": 1, + "last_update": "2024-05-25 04:10:08", + "author_account_age_days": 4701 + }, + "https://github.com/bvhari/ComfyUI_ImageProcessing": { + "stars": 18, + "last_update": "2024-05-22 18:08:40", + "author_account_age_days": 1190 + }, + "https://github.com/bvhari/ComfyUI_LatentToRGB": { + "stars": 11, + "last_update": "2024-06-23 11:37:10", + "author_account_age_days": 1190 + }, + "https://github.com/bvhari/ComfyUI_PerpWeight": { + "stars": 12, + "last_update": "2024-05-22 18:09:06", + "author_account_age_days": 1190 + }, + "https://github.com/bvhari/ComfyUI_SUNoise": { + "stars": 6, + "last_update": "2024-07-06 13:37:18", + "author_account_age_days": 1190 + }, + "https://github.com/cdb-boop/ComfyUI-Bringing-Old-Photos-Back-to-Life": { + "stars": 250, + "last_update": "2024-06-21 15:05:26", + "author_account_age_days": 1220 + }, + "https://github.com/cdb-boop/comfyui-image-round": { + "stars": 0, + "last_update": "2024-05-23 00:09:02", + "author_account_age_days": 1220 + }, + "https://github.com/celsojr2013/comfyui_jamworks_client": { + "stars": 0, + "last_update": "2024-06-23 12:35:44", + "author_account_age_days": 3414 + }, + "https://github.com/celsojr2013/comfyui_simpletools": { + "stars": 2, + "last_update": "2024-06-22 11:35:40", + "author_account_age_days": 3414 + }, + "https://github.com/cerspense/ComfyUI_cspnodes": { + "stars": 24, + "last_update": "2024-06-27 22:39:06", + "author_account_age_days": 2697 + }, + "https://github.com/ceruleandeep/ComfyUI-LLaVA-Captioner": { + "stars": 78, + "last_update": "2024-05-22 22:17:55", + "author_account_age_days": 1169 + }, + "https://github.com/chakib-belgaid/ComfyUI-autosize": { + "stars": 0, + "last_update": "2024-06-14 07:13:20", + "author_account_age_days": 3851 + }, + "https://github.com/chakib-belgaid/Comfyui_Prompt_styler": { + "stars": 0, + "last_update": "2024-07-01 12:40:52", + "author_account_age_days": 3851 + }, + "https://github.com/chandlergis/ComfyUI-IMG_Query": { + "stars": 1, + "last_update": "2024-05-23 01:25:57", + "author_account_age_days": 371 + }, + "https://github.com/chandlergis/ComfyUI_EmojiOverlay": { + "stars": 0, + "last_update": "2024-06-14 09:05:03", + "author_account_age_days": 371 + }, + "https://github.com/chaojie/ComfyUI-AniPortrait": { + "stars": 230, + "last_update": "2024-05-22 22:26:03", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-CameraCtrl-Wrapper": { + "stars": 16, + "last_update": "2024-06-14 09:07:23", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Champ": { + "stars": 19, + "last_update": "2024-05-22 22:26:47", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-DragAnything": { + "stars": 66, + "last_update": "2024-06-14 10:23:53", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-DragNUWA": { + "stars": 364, + "last_update": "2024-06-14 10:25:01", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-DynamiCrafter": { + "stars": 112, + "last_update": "2024-06-14 10:23:59", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-EasyAnimate": { + "stars": 39, + "last_update": "2024-05-22 22:24:00", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Gemma": { + "stars": 5, + "last_update": "2024-05-22 22:27:47", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-I2VGEN-XL": { + "stars": 27, + "last_update": "2024-06-14 09:06:10", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Img2Img-Turbo": { + "stars": 36, + "last_update": "2024-05-22 22:26:30", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-LaVIT": { + "stars": 10, + "last_update": "2024-06-14 10:27:44", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-LightGlue": { + "stars": 48, + "last_update": "2024-01-20 16:53:51", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Moore-AnimateAnyone": { + "stars": 201, + "last_update": "2024-06-10 20:16:06", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Motion-Vector-Extractor": { + "stars": 1, + "last_update": "2024-06-14 10:26:15", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-MotionCtrl": { + "stars": 128, + "last_update": "2024-06-14 10:26:02", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-MotionCtrl-SVD": { + "stars": 79, + "last_update": "2024-06-14 10:26:30", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-MuseTalk": { + "stars": 151, + "last_update": "2024-05-22 22:25:07", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-MuseV": { + "stars": 125, + "last_update": "2024-05-22 22:25:31", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Open-Sora": { + "stars": 88, + "last_update": "2024-05-22 22:26:59", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Open-Sora-Plan": { + "stars": 49, + "last_update": "2024-05-29 16:15:10", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Panda3d": { + "stars": 13, + "last_update": "2024-06-14 10:28:47", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Pymunk": { + "stars": 16, + "last_update": "2024-06-14 12:02:32", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-RAFT": { + "stars": 25, + "last_update": "2024-06-14 11:02:00", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-SimDA": { + "stars": 13, + "last_update": "2024-06-14 12:02:39", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Trajectory": { + "stars": 5, + "last_update": "2024-05-22 22:27:12", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-Video-Editing-X-Attention": { + "stars": 17, + "last_update": "2024-06-14 10:28:16", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI-dust3r": { + "stars": 15, + "last_update": "2024-05-22 22:27:33", + "author_account_age_days": 4849 + }, + "https://github.com/chaojie/ComfyUI_StreamingT2V": { + "stars": 26, + "last_update": "2024-06-14 10:26:21", + "author_account_age_days": 4849 + }, + "https://github.com/chaosaiart/Chaosaiart-Nodes": { + "stars": 47, + "last_update": "2024-05-27 10:55:18", + "author_account_age_days": 349 + }, + "https://github.com/chenpx976/ComfyUI-RunRunRun": { + "stars": 0, + "last_update": "2024-05-23 01:19:37", + "author_account_age_days": 3430 + }, + "https://github.com/chesnokovivan/ComfyUI-Novakid": { + "stars": 0, + "last_update": "2024-06-10 20:15:56", + "author_account_age_days": 1545 + }, + "https://github.com/chflame163/ComfyUI_FaceSimilarity": { + "stars": 13, + "last_update": "2024-05-23 12:48:18", + "author_account_age_days": 459 + }, + "https://github.com/chflame163/ComfyUI_LayerStyle": { + "stars": 693, + "last_update": "2024-06-29 06:38:45", + "author_account_age_days": 459 + }, + "https://github.com/chflame163/ComfyUI_MSSpeech_TTS": { + "stars": 23, + "last_update": "2024-05-25 02:39:56", + "author_account_age_days": 459 + }, + "https://github.com/chflame163/ComfyUI_WordCloud": { + "stars": 71, + "last_update": "2024-05-25 02:41:06", + "author_account_age_days": 459 + }, + "https://github.com/chibiace/ComfyUI-Chibi-Nodes": { + "stars": 30, + "last_update": "2024-05-22 21:16:12", + "author_account_age_days": 2864 + }, + "https://github.com/choey/Comfy-Topaz": { + "stars": 26, + "last_update": "2024-06-20 13:52:32", + "author_account_age_days": 5538 + }, + "https://github.com/chris-the-wiz/EmbeddingsCurveEditor_ComfyUI": { + "stars": 7, + "last_update": "2024-06-29 19:13:44", + "author_account_age_days": 1812 + }, + "https://github.com/chrisfreilich/virtuoso-nodes": { + "stars": 50, + "last_update": "2024-06-30 18:26:54", + "author_account_age_days": 747 + }, + "https://github.com/chrisgoringe/cg-image-picker": { + "stars": 191, + "last_update": "2024-06-12 18:50:30", + "author_account_age_days": 4080 + }, + "https://github.com/chrisgoringe/cg-noise": { + "stars": 25, + "last_update": "2024-06-14 08:10:52", + "author_account_age_days": 4080 + }, + "https://github.com/chrisgoringe/cg-prompt-info": { + "stars": 27, + "last_update": "2024-05-22 21:07:33", + "author_account_age_days": 4080 + }, + "https://github.com/chrisgoringe/cg-use-everywhere": { + "stars": 360, + "last_update": "2024-07-01 05:43:31", + "author_account_age_days": 4080 + }, + "https://github.com/chrish-slingshot/CrasHUtils": { + "stars": 11, + "last_update": "2024-06-20 12:53:00", + "author_account_age_days": 616 + }, + "https://github.com/christian-byrne/audio-separation-nodes-comfyui": { + "stars": 34, + "last_update": "2024-07-09 05:00:46", + "author_account_age_days": 1364 + }, + "https://github.com/christian-byrne/comfyui-default-values-manager": { + "stars": 4, + "last_update": "2024-07-08 13:59:42", + "author_account_age_days": 1364 + }, + "https://github.com/christian-byrne/comfyui-search-navigation": { + "stars": 5, + "last_update": "2024-06-26 04:41:12", + "author_account_age_days": 1364 + }, + "https://github.com/christian-byrne/img2colors-comfyui-node": { + "stars": 5, + "last_update": "2024-06-24 07:26:35", + "author_account_age_days": 1364 + }, + "https://github.com/christian-byrne/img2txt-comfyui-nodes": { + "stars": 30, + "last_update": "2024-06-23 22:15:59", + "author_account_age_days": 1364 + }, + "https://github.com/christian-byrne/size-match-compositing-nodes": { + "stars": 3, + "last_update": "2024-06-23 21:00:23", + "author_account_age_days": 1364 + }, + "https://github.com/city96/ComfyUI_ColorMod": { + "stars": 43, + "last_update": "2024-05-22 18:06:19", + "author_account_age_days": 513 + }, + "https://github.com/city96/ComfyUI_DiT": { + "stars": 3, + "last_update": "2024-05-22 18:06:05", + "author_account_age_days": 513 + }, + "https://github.com/city96/ComfyUI_ExtraModels": { + "stars": 315, + "last_update": "2024-07-06 18:26:29", + "author_account_age_days": 513 + }, + "https://github.com/city96/ComfyUI_NetDist": { + "stars": 238, + "last_update": "2024-05-22 18:05:10", + "author_account_age_days": 513 + }, + "https://github.com/city96/SD-Advanced-Noise": { + "stars": 19, + "last_update": "2024-05-22 18:05:35", + "author_account_age_days": 513 + }, + "https://github.com/city96/SD-Latent-Interposer": { + "stars": 186, + "last_update": "2024-06-17 05:27:08", + "author_account_age_days": 513 + }, + "https://github.com/city96/SD-Latent-Upscaler": { + "stars": 115, + "last_update": "2024-05-22 18:05:50", + "author_account_age_days": 513 + }, + "https://github.com/civitai/comfy-nodes": { + "stars": 87, + "last_update": "2024-06-23 03:35:42", + "author_account_age_days": 614 + }, + "https://github.com/claussteinmassl/ComfyUI-CS-CustomNodes": { + "stars": 1, + "last_update": "2024-06-14 09:03:10", + "author_account_age_days": 2716 + }, + "https://github.com/comfyanonymous/ComfyUI": { + "stars": 41626, + "last_update": "2024-07-09 21:12:57", + "author_account_age_days": 564 + }, + "https://github.com/comfyanonymous/ComfyUI_TensorRT": { + "stars": 345, + "last_update": "2024-06-19 21:31:56", + "author_account_age_days": 564 + }, + "https://github.com/comfyanonymous/ComfyUI_experiments": { + "stars": 139, + "last_update": "2024-05-22 15:29:49", + "author_account_age_days": 564 + }, + "https://github.com/concarne000/ConCarneNode": { + "stars": 4, + "last_update": "2024-05-22 22:10:18", + "author_account_age_days": 1916 + }, + "https://github.com/conquestace/ComfyUI-ImageUploader": { + "stars": 2, + "last_update": "2024-05-23 01:25:49", + "author_account_age_days": 4624 + }, + "https://github.com/coolzilj/ComfyUI-LJNodes": { + "stars": 59, + "last_update": "2024-06-15 01:57:32", + "author_account_age_days": 4678 + }, + "https://github.com/coolzilj/ComfyUI-Photopea": { + "stars": 60, + "last_update": "2024-06-14 08:10:57", + "author_account_age_days": 4678 + }, + "https://github.com/coreyryanhanson/ComfyQR": { + "stars": 51, + "last_update": "2024-07-05 04:13:09", + "author_account_age_days": 3071 + }, + "https://github.com/coreyryanhanson/ComfyQR-scanning-nodes": { + "stars": 9, + "last_update": "2024-07-05 03:55:48", + "author_account_age_days": 3071 + }, + "https://github.com/cozymantis/cozy-utils-comfyui-nodes": { + "stars": 3, + "last_update": "2024-07-07 15:38:05", + "author_account_age_days": 124 + }, + "https://github.com/cozymantis/human-parser-comfyui-node": { + "stars": 54, + "last_update": "2024-07-07 15:31:17", + "author_account_age_days": 124 + }, + "https://github.com/cozymantis/pose-generator-comfyui-node": { + "stars": 30, + "last_update": "2024-07-07 15:22:45", + "author_account_age_days": 124 + }, + "https://github.com/crystian/ComfyUI-Crystools": { + "stars": 511, + "last_update": "2024-07-01 03:24:20", + "author_account_age_days": 4132 + }, + "https://github.com/crystian/ComfyUI-Crystools-save": { + "stars": 31, + "last_update": "2024-07-01 01:19:58", + "author_account_age_days": 4132 + }, + "https://github.com/cubiq/ComfyUI_FaceAnalysis": { + "stars": 231, + "last_update": "2024-06-14 08:08:35", + "author_account_age_days": 5026 + }, + "https://github.com/cubiq/ComfyUI_IPAdapter_plus": { + "stars": 3218, + "last_update": "2024-06-28 11:03:36", + "author_account_age_days": 5026 + }, + "https://github.com/cubiq/ComfyUI_InstantID": { + "stars": 967, + "last_update": "2024-07-04 03:04:24", + "author_account_age_days": 5026 + }, + "https://github.com/cubiq/ComfyUI_SimpleMath": { + "stars": 17, + "last_update": "2024-06-14 09:02:50", + "author_account_age_days": 5026 + }, + "https://github.com/cubiq/ComfyUI_essentials": { + "stars": 355, + "last_update": "2024-07-08 17:19:58", + "author_account_age_days": 5026 + }, + "https://github.com/cubiq/PuLID_ComfyUI": { + "stars": 435, + "last_update": "2024-06-25 06:37:25", + "author_account_age_days": 5026 + }, + "https://github.com/cuongloveit/comfy_http_request": { + "stars": 0, + "last_update": "2024-06-14 11:00:11", + "author_account_age_days": 3267 + }, + "https://github.com/curiousjp/ComfyUI-MaskBatchPermutations": { + "stars": 4, + "last_update": "2024-05-28 13:09:32", + "author_account_age_days": 1945 + }, + "https://github.com/czcz1024/Comfyui-FaceCompare": { + "stars": 0, + "last_update": "2024-06-14 07:13:32", + "author_account_age_days": 4249 + }, + "https://github.com/da2el-ai/ComfyUI-d2-size-selector": { + "stars": 2, + "last_update": "2024-05-23 01:16:17", + "author_account_age_days": 405 + }, + "https://github.com/da2el-ai/ComfyUI-d2-steps": { + "stars": 5, + "last_update": "2024-05-23 01:16:06", + "author_account_age_days": 405 + }, + "https://github.com/dagthomas/comfyui_dagthomas": { + "stars": 83, + "last_update": "2024-07-07 16:56:46", + "author_account_age_days": 4087 + }, + "https://github.com/daniabib/ComfyUI_ProPainter_Nodes": { + "stars": 168, + "last_update": "2024-07-08 21:59:15", + "author_account_age_days": 2420 + }, + "https://github.com/daniel-lewis-ab/ComfyUI-Llama": { + "stars": 26, + "last_update": "2024-06-29 19:55:42", + "author_account_age_days": 3367 + }, + "https://github.com/daniel-lewis-ab/ComfyUI-TTS": { + "stars": 13, + "last_update": "2024-06-14 08:09:49", + "author_account_age_days": 3367 + }, + "https://github.com/darkpixel/darkprompts": { + "stars": 6, + "last_update": "2024-05-23 19:48:02", + "author_account_age_days": 5339 + }, + "https://github.com/dave-palt/comfyui_DSP_imagehelpers": { + "stars": 0, + "last_update": "2024-05-22 23:12:11", + "author_account_age_days": 173 + }, + "https://github.com/daxcay/ComfyUI-DRMN": { + "stars": 19, + "last_update": "2024-07-08 08:25:29", + "author_account_age_days": 110 + }, + "https://github.com/daxcay/ComfyUI-DataSet": { + "stars": 19, + "last_update": "2024-07-08 08:25:29", + "author_account_age_days": 110 + }, + "https://github.com/daxcay/ComfyUI-JDCN": { + "stars": 66, + "last_update": "2024-07-08 14:02:49", + "author_account_age_days": 110 + }, + "https://github.com/daxcay/ComfyUI-NODEJS": { + "stars": 5, + "last_update": "2024-06-13 14:30:45", + "author_account_age_days": 110 + }, + "https://github.com/daxthin/DZ-FaceDetailer": { + "stars": 102, + "last_update": "2024-06-17 10:00:30", + "author_account_age_days": 1246 + }, + "https://github.com/dchatel/comfyui_facetools": { + "stars": 46, + "last_update": "2024-06-26 10:26:43", + "author_account_age_days": 4551 + }, + "https://github.com/denfrost/Den_ComfyUI_Workflow": { + "stars": 4, + "last_update": "2024-06-20 14:57:57", + "author_account_age_days": 3512 + }, + "https://github.com/deroberon/StableZero123-comfyui": { + "stars": 136, + "last_update": "2024-05-22 22:09:53", + "author_account_age_days": 5311 + }, + "https://github.com/deroberon/demofusion-comfyui": { + "stars": 83, + "last_update": "2024-05-22 22:09:42", + "author_account_age_days": 5311 + }, + "https://github.com/dfl/comfyui-clip-with-break": { + "stars": 10, + "last_update": "2024-05-22 23:23:15", + "author_account_age_days": 5990 + }, + "https://github.com/dfl/comfyui-tcd-scheduler": { + "stars": 80, + "last_update": "2024-05-22 23:23:28", + "author_account_age_days": 5990 + }, + "https://github.com/diStyApps/ComfyUI_FrameMaker": { + "stars": 10, + "last_update": "2024-05-23 00:11:33", + "author_account_age_days": 4220 + }, + "https://github.com/dicksondickson/ComfyUI-Dickson-Nodes": { + "stars": 4, + "last_update": "2024-06-29 21:27:03", + "author_account_age_days": 4006 + }, + "https://github.com/digitaljohn/comfyui-propost": { + "stars": 109, + "last_update": "2024-07-02 15:28:37", + "author_account_age_days": 4533 + }, + "https://github.com/dimtoneff/ComfyUI-PixelArt-Detector": { + "stars": 170, + "last_update": "2024-07-06 10:15:30", + "author_account_age_days": 3430 + }, + "https://github.com/diontimmer/ComfyUI-Vextra-Nodes": { + "stars": 61, + "last_update": "2024-06-20 16:48:44", + "author_account_age_days": 4786 + }, + "https://github.com/discopixel-studio/comfyui-discopixel": { + "stars": 7, + "last_update": "2024-06-14 09:03:19", + "author_account_age_days": 361 + }, + "https://github.com/discus0434/comfyui-aesthetic-predictor-v2-5": { + "stars": 5, + "last_update": "2024-06-14 08:12:05", + "author_account_age_days": 1485 + }, + "https://github.com/discus0434/comfyui-caching-embeddings": { + "stars": 1, + "last_update": "2024-06-14 08:59:36", + "author_account_age_days": 1485 + }, + "https://github.com/djbielejeski/a-person-mask-generator": { + "stars": 240, + "last_update": "2024-06-15 04:06:44", + "author_account_age_days": 4299 + }, + "https://github.com/dmMaze/sketch2manga": { + "stars": 27, + "last_update": "2024-06-30 03:27:55", + "author_account_age_days": 1865 + }, + "https://github.com/dmarx/ComfyUI-AudioReactive": { + "stars": 10, + "last_update": "2024-05-22 22:12:53", + "author_account_age_days": 4520 + }, + "https://github.com/dmarx/ComfyUI-Keyframed": { + "stars": 81, + "last_update": "2024-07-01 01:41:23", + "author_account_age_days": 4520 + }, + "https://github.com/drago87/ComfyUI_Dragos_Nodes": { + "stars": 3, + "last_update": "2024-05-22 21:32:15", + "author_account_age_days": 3785 + }, + "https://github.com/drustan-hawk/primitive-types": { + "stars": 5, + "last_update": "2024-06-30 06:10:23", + "author_account_age_days": 304 + }, + "https://github.com/e7mac/ComfyUI-ShadertoyGL": { + "stars": 2, + "last_update": "2024-06-20 14:52:42", + "author_account_age_days": 4819 + }, + "https://github.com/ealkanat/comfyui_easy_padding": { + "stars": 13, + "last_update": "2024-05-22 21:58:52", + "author_account_age_days": 2478 + }, + "https://github.com/edenartlab/eden_comfy_pipelines": { + "stars": 40, + "last_update": "2024-07-08 09:44:46", + "author_account_age_days": 288 + }, + "https://github.com/evanspearman/ComfyMath": { + "stars": 55, + "last_update": "2023-08-27 03:29:04", + "author_account_age_days": 4254 + }, + "https://github.com/exdysa/comfyui-selector": { + "stars": 3, + "last_update": "2024-07-04 01:38:33", + "author_account_age_days": 1011 + }, + "https://github.com/fablestudio/ComfyUI-Showrunner-Utils": { + "stars": 0, + "last_update": "2024-06-24 14:27:05", + "author_account_age_days": 2064 + }, + "https://github.com/failfa-st/failfast-comfyui-extensions": { + "stars": 134, + "last_update": "2024-06-17 10:01:12", + "author_account_age_days": 289 + }, + "https://github.com/fexli/fexli-util-node-comfyui": { + "stars": 3, + "last_update": "2024-05-22 21:27:36", + "author_account_age_days": 1574 + }, + "https://github.com/fexploit/ComfyUI-AutoLabel": { + "stars": 6, + "last_update": "2024-06-14 08:09:41", + "author_account_age_days": 5059 + }, + "https://github.com/fexploit/ComfyUI-AutoTrimBG": { + "stars": 2, + "last_update": "2024-05-24 20:38:15", + "author_account_age_days": 5059 + }, + "https://github.com/fexploit/ComfyUI-Classifier": { + "stars": 1, + "last_update": "2024-06-14 16:58:31", + "author_account_age_days": 5059 + }, + "https://github.com/filipemeneses/comfy_pixelization": { + "stars": 31, + "last_update": "2024-05-22 20:59:16", + "author_account_age_days": 3492 + }, + "https://github.com/filliptm/ComfyUI_Fill-Nodes": { + "stars": 120, + "last_update": "2024-07-09 05:50:58", + "author_account_age_days": 1752 + }, + "https://github.com/florestefano1975/ComfyUI-HiDiffusion": { + "stars": 135, + "last_update": "2024-05-22 00:33:06", + "author_account_age_days": 209 + }, + "https://github.com/florestefano1975/ComfyUI-StabilityAI-Suite": { + "stars": 2, + "last_update": "2024-06-14 09:05:46", + "author_account_age_days": 209 + }, + "https://github.com/florestefano1975/comfyui-portrait-master": { + "stars": 774, + "last_update": "2024-06-19 16:30:07", + "author_account_age_days": 209 + }, + "https://github.com/florestefano1975/comfyui-prompt-composer": { + "stars": 214, + "last_update": "2024-05-22 00:34:06", + "author_account_age_days": 209 + }, + "https://github.com/flowtyone/ComfyUI-Flowty-CRM": { + "stars": 128, + "last_update": "2024-06-14 10:23:09", + "author_account_age_days": 289 + }, + "https://github.com/flowtyone/ComfyUI-Flowty-LDSR": { + "stars": 168, + "last_update": "2024-06-14 09:04:51", + "author_account_age_days": 289 + }, + "https://github.com/flowtyone/ComfyUI-Flowty-TripoSR": { + "stars": 369, + "last_update": "2024-06-16 00:53:22", + "author_account_age_days": 289 + }, + "https://github.com/flyingshutter/As_ComfyUI_CustomNodes": { + "stars": 8, + "last_update": "2024-05-22 18:07:19", + "author_account_age_days": 3510 + }, + "https://github.com/fmatray/ComfyUI_BattlemapGrid": { + "stars": 0, + "last_update": "2024-06-05 22:35:06", + "author_account_age_days": 3637 + }, + "https://github.com/fofr/ComfyUI-HyperSDXL1StepUnetScheduler": { + "stars": 12, + "last_update": "2024-06-20 11:51:50", + "author_account_age_days": 5123 + }, + "https://github.com/fofr/ComfyUI-Prompter-fofrAI": { + "stars": 35, + "last_update": "2024-06-29 22:10:29", + "author_account_age_days": 5123 + }, + "https://github.com/fofr/comfyui-replicate": { + "stars": 34, + "last_update": "2024-07-02 17:58:30", + "author_account_age_days": 1624 + }, + "https://github.com/forever22777/comfyui-self-guidance": { + "stars": 6, + "last_update": "2024-06-14 07:12:02", + "author_account_age_days": 340 + }, + "https://github.com/foxtrot-roger/comfyui-rf-nodes": { + "stars": 1, + "last_update": "2024-05-22 23:09:13", + "author_account_age_days": 2336 + }, + "https://github.com/frankchieng/ComfyUI_Aniportrait": { + "stars": 48, + "last_update": "2024-06-26 03:06:51", + "author_account_age_days": 456 + }, + "https://github.com/frankchieng/ComfyUI_MagicClothing": { + "stars": 426, + "last_update": "2024-06-24 07:48:07", + "author_account_age_days": 456 + }, + "https://github.com/frankchieng/ComfyUI_llm_easyanimiate": { + "stars": 10, + "last_update": "2024-06-26 03:13:32", + "author_account_age_days": 456 + }, + "https://github.com/fsdymy1024/ComfyUI_fsdymy": { + "stars": 6, + "last_update": "2024-07-01 17:58:52", + "author_account_age_days": 2221 + }, + "https://github.com/gemell1/ComfyUI_GMIC": { + "stars": 6, + "last_update": "2024-05-22 21:28:51", + "author_account_age_days": 1972 + }, + "https://github.com/get-salt-AI/SaltAI": { + "stars": 61, + "last_update": "2024-06-26 00:32:47", + "author_account_age_days": 131 + }, + "https://github.com/get-salt-AI/SaltAI_AudioViz": { + "stars": 13, + "last_update": "2024-06-29 16:16:46", + "author_account_age_days": 131 + }, + "https://github.com/get-salt-AI/SaltAI_Language_Toolkit": { + "stars": 19, + "last_update": "2024-06-25 23:49:29", + "author_account_age_days": 131 + }, + "https://github.com/get-salt-AI/SaltAI_LlamaIndex": { + "stars": 19, + "last_update": "2024-06-25 23:49:29", + "author_account_age_days": 131 + }, + "https://github.com/ginlov/segment_to_mask_comfyui": { + "stars": 1, + "last_update": "2024-06-14 10:23:23", + "author_account_age_days": 2027 + }, + "https://github.com/giriss/comfy-image-saver": { + "stars": 151, + "last_update": "2024-05-22 20:40:55", + "author_account_age_days": 4253 + }, + "https://github.com/githubYiheng/ComfyUI_Change_IMAGE_BOREDER": { + "stars": 0, + "last_update": "2024-05-23 01:20:09", + "author_account_age_days": 3918 + }, + "https://github.com/githubYiheng/ComfyUI_GetFileNameFromURL": { + "stars": 0, + "last_update": "2024-05-23 01:19:47", + "author_account_age_days": 3918 + }, + "https://github.com/githubYiheng/comfyui_kmeans_filter": { + "stars": 0, + "last_update": "2024-06-14 09:01:24", + "author_account_age_days": 3918 + }, + "https://github.com/githubYiheng/comfyui_meanshift_filter": { + "stars": 0, + "last_update": "2024-06-14 10:59:43", + "author_account_age_days": 3918 + }, + "https://github.com/githubYiheng/comfyui_private_postprocessor": { + "stars": 0, + "last_update": "2024-06-14 08:09:39", + "author_account_age_days": 3918 + }, + "https://github.com/glibsonoran/Plush-for-ComfyUI": { + "stars": 111, + "last_update": "2024-07-07 15:47:16", + "author_account_age_days": 2513 + }, + "https://github.com/glifxyz/ComfyUI-GlifNodes": { + "stars": 18, + "last_update": "2024-07-05 12:12:47", + "author_account_age_days": 589 + }, + "https://github.com/glowcone/comfyui-base64-to-image": { + "stars": 8, + "last_update": "2024-07-08 22:53:25", + "author_account_age_days": 3761 + }, + "https://github.com/godspede/ComfyUI_Substring": { + "stars": 0, + "last_update": "2024-07-01 01:05:38", + "author_account_age_days": 3128 + }, + "https://github.com/gokayfem/ComfyUI-Depth-Visualization": { + "stars": 49, + "last_update": "2024-05-21 00:37:05", + "author_account_age_days": 1073 + }, + "https://github.com/gokayfem/ComfyUI-Dream-Interpreter": { + "stars": 66, + "last_update": "2024-05-21 00:36:50", + "author_account_age_days": 1073 + }, + "https://github.com/gokayfem/ComfyUI-Texture-Simple": { + "stars": 30, + "last_update": "2024-05-21 00:19:53", + "author_account_age_days": 1073 + }, + "https://github.com/gokayfem/ComfyUI_VLM_nodes": { + "stars": 298, + "last_update": "2024-07-04 01:40:04", + "author_account_age_days": 1073 + }, + "https://github.com/gonzalu/ComfyUI_YFG_Comical": { + "stars": 20, + "last_update": "2024-07-02 02:05:08", + "author_account_age_days": 2476 + }, + "https://github.com/griptape-ai/ComfyUI-Griptape": { + "stars": 50, + "last_update": "2024-07-09 23:19:26", + "author_account_age_days": 536 + }, + "https://github.com/guill/abracadabra-comfyui": { + "stars": 1, + "last_update": "2024-06-14 08:12:07", + "author_account_age_days": 4208 + }, + "https://github.com/guoyk93/yk-node-suite-comfyui": { + "stars": 10, + "last_update": "2024-06-17 10:00:36", + "author_account_age_days": 1504 + }, + "https://github.com/hackkhai/ComfyUI-Image-Matting": { + "stars": 15, + "last_update": "2024-06-20 11:25:12", + "author_account_age_days": 1866 + }, + "https://github.com/haohaocreates/ComfyUI-HH-Image-Selector": { + "stars": 0, + "last_update": "2024-07-08 22:02:55", + "author_account_age_days": 121 + }, + "https://github.com/hay86/ComfyUI_AceNodes": { + "stars": 9, + "last_update": "2024-07-02 08:17:41", + "author_account_age_days": 4682 + }, + "https://github.com/hay86/ComfyUI_DDColor": { + "stars": 2, + "last_update": "2024-06-14 08:12:13", + "author_account_age_days": 4682 + }, + "https://github.com/hay86/ComfyUI_Dreamtalk": { + "stars": 8, + "last_update": "2024-07-02 08:15:01", + "author_account_age_days": 4682 + }, + "https://github.com/hay86/ComfyUI_Hallo": { + "stars": 19, + "last_update": "2024-07-02 08:19:11", + "author_account_age_days": 4682 + }, + "https://github.com/hay86/ComfyUI_MiniCPM-V": { + "stars": 10, + "last_update": "2024-07-02 08:09:38", + "author_account_age_days": 4682 + }, + "https://github.com/hay86/ComfyUI_OpenVoice": { + "stars": 7, + "last_update": "2024-07-02 08:16:20", + "author_account_age_days": 4682 + }, + "https://github.com/hayden-fr/ComfyUI-Image-Browsing": { + "stars": 2, + "last_update": "2024-05-22 20:54:07", + "author_account_age_days": 1952 + }, + "https://github.com/hayden-fr/ComfyUI-Model-Manager": { + "stars": 26, + "last_update": "2024-05-22 20:53:55", + "author_account_age_days": 1952 + }, + "https://github.com/hben35096/ComfyUI-ToolBox": { + "stars": 0, + "last_update": "2024-06-26 18:27:22", + "author_account_age_days": 363 + }, + "https://github.com/heshengtao/comfyui_LLM_party": { + "stars": 177, + "last_update": "2024-07-09 17:00:35", + "author_account_age_days": 2910 + }, + "https://github.com/hhhzzyang/Comfyui_Lama": { + "stars": 39, + "last_update": "2024-05-22 21:13:19", + "author_account_age_days": 522 + }, + "https://github.com/hiforce/comfyui-hiforce-plugin": { + "stars": 3, + "last_update": "2024-06-14 08:13:24", + "author_account_age_days": 1817 + }, + "https://github.com/hinablue/ComfyUI_3dPoseEditor": { + "stars": 127, + "last_update": "2024-06-21 17:38:40", + "author_account_age_days": 5127 + }, + "https://github.com/holchan/ComfyUI-ModelDownloader": { + "stars": 2, + "last_update": "2024-06-14 08:59:42", + "author_account_age_days": 1607 + }, + "https://github.com/huagetai/ComfyUI-Gaffer": { + "stars": 36, + "last_update": "2024-06-19 00:58:38", + "author_account_age_days": 4647 + }, + "https://github.com/huagetai/ComfyUI_LightGradient": { + "stars": 8, + "last_update": "2024-05-23 01:21:27", + "author_account_age_days": 4647 + }, + "https://github.com/huchenlei/ComfyUI-IC-Light-Native": { + "stars": 415, + "last_update": "2024-06-21 21:49:44", + "author_account_age_days": 2891 + }, + "https://github.com/huchenlei/ComfyUI-layerdiffuse": { + "stars": 1293, + "last_update": "2024-07-05 12:52:34", + "author_account_age_days": 2891 + }, + "https://github.com/huchenlei/ComfyUI-openpose-editor": { + "stars": 27, + "last_update": "2024-06-26 21:15:34", + "author_account_age_days": 2891 + }, + "https://github.com/huchenlei/ComfyUI_DanTagGen": { + "stars": 50, + "last_update": "2024-06-21 21:46:47", + "author_account_age_days": 2891 + }, + "https://github.com/huchenlei/ComfyUI_densediffusion": { + "stars": 86, + "last_update": "2024-06-11 00:39:28", + "author_account_age_days": 2891 + }, + "https://github.com/huchenlei/ComfyUI_omost": { + "stars": 347, + "last_update": "2024-06-26 21:16:52", + "author_account_age_days": 2891 + }, + "https://github.com/hughescr/ComfyUI-OpenPose-Keypoint-Extractor": { + "stars": 6, + "last_update": "2024-06-14 09:04:25", + "author_account_age_days": 5656 + }, + "https://github.com/humgate/simplecomfy": { + "stars": 0, + "last_update": "2024-06-14 08:58:21", + "author_account_age_days": 1382 + }, + "https://github.com/hustille/ComfyUI_Fooocus_KSampler": { + "stars": 60, + "last_update": "2024-05-22 20:39:48", + "author_account_age_days": 455 + }, + "https://github.com/hustille/ComfyUI_hus_utils": { + "stars": 6, + "last_update": "2024-05-22 20:39:34", + "author_account_age_days": 455 + }, + "https://github.com/hwhaocool/ComfyUI-Select-Any": { + "stars": 3, + "last_update": "2024-07-03 14:16:01", + "author_account_age_days": 2903 + }, + "https://github.com/hylarucoder/ComfyUI-Eagle-PNGInfo": { + "stars": 8, + "last_update": "2024-06-28 04:43:18", + "author_account_age_days": 3928 + }, + "https://github.com/hyunamy/comfy-ui-on-complete-email-me": { + "stars": 1, + "last_update": "2024-07-01 18:44:18", + "author_account_age_days": 3126 + }, + "https://github.com/iFREEGROUP/comfyui-undistort": { + "stars": 2, + "last_update": "2024-06-14 08:59:52", + "author_account_age_days": 1572 + }, + "https://github.com/icesun963/ComfyUI_HFDownLoad": { + "stars": 0, + "last_update": "2024-06-14 08:59:58", + "author_account_age_days": 4121 + }, + "https://github.com/idrirap/ComfyUI-Lora-Auto-Trigger-Words": { + "stars": 101, + "last_update": "2024-06-20 15:56:56", + "author_account_age_days": 3065 + }, + "https://github.com/iemesowum/ComfyUI_IsaacNodes": { + "stars": 0, + "last_update": "2024-06-14 09:00:05", + "author_account_age_days": 5307 + }, + "https://github.com/if-ai/ComfyUI-IF_AI_HFDownloaderNode": { + "stars": 10, + "last_update": "2024-07-07 09:55:48", + "author_account_age_days": 2877 + }, + "https://github.com/if-ai/ComfyUI-IF_AI_WishperSpeechNode": { + "stars": 28, + "last_update": "2024-05-22 22:02:55", + "author_account_age_days": 2877 + }, + "https://github.com/if-ai/ComfyUI-IF_AI_tools": { + "stars": 384, + "last_update": "2024-06-26 13:16:20", + "author_account_age_days": 2877 + }, + "https://github.com/imb101/ComfyUI-FaceSwap": { + "stars": 28, + "last_update": "2024-05-22 18:22:29", + "author_account_age_days": 904 + }, + "https://github.com/iwanders/ComfyUI_nodes": { + "stars": 0, + "last_update": "2024-07-07 16:30:05", + "author_account_age_days": 4441 + }, + "https://github.com/jags111/ComfyUI_Jags_Audiotools": { + "stars": 38, + "last_update": "2024-05-19 18:54:12", + "author_account_age_days": 3886 + }, + "https://github.com/jags111/ComfyUI_Jags_VectorMagic": { + "stars": 52, + "last_update": "2024-05-19 18:49:42", + "author_account_age_days": 3886 + }, + "https://github.com/jags111/efficiency-nodes-comfyui": { + "stars": 735, + "last_update": "2024-06-23 09:42:43", + "author_account_age_days": 3886 + }, + "https://github.com/jakechai/ComfyUI-JakeUpgrade": { + "stars": 6, + "last_update": "2024-07-07 09:22:17", + "author_account_age_days": 1587 + }, + "https://github.com/jamal-alkharrat/ComfyUI_rotate_image": { + "stars": 0, + "last_update": "2024-05-22 23:19:02", + "author_account_age_days": 992 + }, + "https://github.com/jamesWalker55/comfyui-p2ldgan": { + "stars": 12, + "last_update": "2024-05-22 18:19:04", + "author_account_age_days": 2542 + }, + "https://github.com/jamesWalker55/comfyui-various": { + "stars": 33, + "last_update": "2024-05-22 18:19:17", + "author_account_age_days": 2542 + }, + "https://github.com/jax-explorer/fast_video_comfyui": { + "stars": 0, + "last_update": "2024-05-23 01:17:35", + "author_account_age_days": 592 + }, + "https://github.com/jeffy5/comfyui-faceless-node": { + "stars": 20, + "last_update": "2024-06-14 04:11:28", + "author_account_age_days": 2946 + }, + "https://github.com/jesenzhang/ComfyUI_StreamDiffusion": { + "stars": 107, + "last_update": "2024-05-23 02:40:36", + "author_account_age_days": 3667 + }, + "https://github.com/jiaxiangc/ComfyUI-ResAdapter": { + "stars": 271, + "last_update": "2024-05-23 00:22:23", + "author_account_age_days": 1301 + }, + "https://github.com/jitcoder/lora-info": { + "stars": 46, + "last_update": "2024-06-20 13:04:19", + "author_account_age_days": 4056 + }, + "https://github.com/jjkramhoeft/ComfyUI-Jjk-Nodes": { + "stars": 4, + "last_update": "2024-05-22 20:44:56", + "author_account_age_days": 3664 + }, + "https://github.com/jkrauss82/ultools-comfyui": { + "stars": 5, + "last_update": "2024-06-23 15:33:07", + "author_account_age_days": 4227 + }, + "https://github.com/jmkl/ComfyUI-ricing": { + "stars": 9, + "last_update": "2024-05-22 20:54:35", + "author_account_age_days": 4612 + }, + "https://github.com/jojkaart/ComfyUI-sampler-lcm-alternative": { + "stars": 113, + "last_update": "2024-07-08 19:16:55", + "author_account_age_days": 4813 + }, + "https://github.com/jordoh/ComfyUI-Deepface": { + "stars": 12, + "last_update": "2024-07-08 14:25:46", + "author_account_age_days": 5009 + }, + "https://github.com/jroc22/ComfyUI-CSV-prompt-builder": { + "stars": 2, + "last_update": "2024-07-03 01:20:35", + "author_account_age_days": 705 + }, + "https://github.com/jtrue/ComfyUI-JaRue": { + "stars": 6, + "last_update": "2024-06-14 09:01:12", + "author_account_age_days": 3945 + }, + "https://github.com/jtydhr88/ComfyUI-LayerDivider": { + "stars": 50, + "last_update": "2024-07-06 01:43:45", + "author_account_age_days": 4768 + }, + "https://github.com/jtydhr88/ComfyUI-Unique3D": { + "stars": 123, + "last_update": "2024-07-04 04:27:01", + "author_account_age_days": 4768 + }, + "https://github.com/jtydhr88/ComfyUI-Workflow-Encrypt": { + "stars": 16, + "last_update": "2024-06-28 03:16:19", + "author_account_age_days": 4768 + }, + "https://github.com/juehackr/comfyui_fk_server": { + "stars": 52, + "last_update": "2024-07-08 02:48:37", + "author_account_age_days": 1127 + }, + "https://github.com/justUmen/Bjornulf_custom_nodes": { + "stars": 0, + "last_update": "2024-07-06 10:05:31", + "author_account_age_days": 2804 + }, + "https://github.com/ka-puna/comfyui-yanc": { + "stars": 6, + "last_update": "2024-05-22 21:29:37", + "author_account_age_days": 2222 + }, + "https://github.com/kaanyalova/ComfyUI_ExtendedImageFormats": { + "stars": 2, + "last_update": "2024-06-03 13:20:01", + "author_account_age_days": 1282 + }, + "https://github.com/kadirnar/ComfyUI-Transformers": { + "stars": 19, + "last_update": "2024-06-22 22:44:39", + "author_account_age_days": 2345 + }, + "https://github.com/kadirnar/ComfyUI-YOLO": { + "stars": 18, + "last_update": "2024-07-08 18:33:07", + "author_account_age_days": 2345 + }, + "https://github.com/kale4eat/ComfyUI-path-util": { + "stars": 0, + "last_update": "2024-05-25 05:44:11", + "author_account_age_days": 1627 + }, + "https://github.com/kale4eat/ComfyUI-speech-dataset-toolkit": { + "stars": 7, + "last_update": "2024-05-23 00:25:02", + "author_account_age_days": 1627 + }, + "https://github.com/kale4eat/ComfyUI-string-util": { + "stars": 1, + "last_update": "2024-05-23 00:24:40", + "author_account_age_days": 1627 + }, + "https://github.com/kale4eat/ComfyUI-text-file-util": { + "stars": 0, + "last_update": "2024-05-23 00:24:51", + "author_account_age_days": 1627 + }, + "https://github.com/katalist-ai/comfyUI-nsfw-detection": { + "stars": 1, + "last_update": "2024-05-23 01:23:32", + "author_account_age_days": 769 + }, + "https://github.com/kealiu/ComfyUI-S3-Tools": { + "stars": 2, + "last_update": "2024-07-04 10:13:07", + "author_account_age_days": 4143 + }, + "https://github.com/kealiu/ComfyUI-Zero123-Porting": { + "stars": 14, + "last_update": "2024-07-04 10:11:13", + "author_account_age_days": 4143 + }, + "https://github.com/kealiu/ComfyUI-ZeroShot-MTrans": { + "stars": 133, + "last_update": "2024-07-04 10:12:32", + "author_account_age_days": 4143 + }, + "https://github.com/kenjiqq/qq-nodes-comfyui": { + "stars": 23, + "last_update": "2024-05-22 21:34:53", + "author_account_age_days": 4905 + }, + "https://github.com/kft334/Knodes": { + "stars": 3, + "last_update": "2024-06-14 08:12:06", + "author_account_age_days": 974 + }, + "https://github.com/kijai/ComfyUI-ADMotionDirector": { + "stars": 132, + "last_update": "2024-06-19 09:13:35", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-APISR-KJ": { + "stars": 56, + "last_update": "2024-05-21 16:30:21", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-BrushNet-Wrapper": { + "stars": 113, + "last_update": "2024-06-20 12:15:16", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-CCSR": { + "stars": 157, + "last_update": "2024-06-28 11:13:33", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-DDColor": { + "stars": 81, + "last_update": "2024-05-21 16:04:26", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-DepthAnythingV2": { + "stars": 121, + "last_update": "2024-06-28 20:46:46", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-DiffusionLight": { + "stars": 51, + "last_update": "2024-05-21 16:16:52", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-DynamiCrafterWrapper": { + "stars": 510, + "last_update": "2024-07-09 13:16:42", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-ELLA-wrapper": { + "stars": 104, + "last_update": "2024-05-21 16:47:28", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-Florence2": { + "stars": 328, + "last_update": "2024-07-09 15:18:00", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-Geowizard": { + "stars": 83, + "last_update": "2024-05-28 14:08:34", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-IC-Light": { + "stars": 483, + "last_update": "2024-06-19 09:18:06", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-KJNodes": { + "stars": 363, + "last_update": "2024-07-07 16:28:35", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-KwaiKolorsWrapper": { + "stars": 238, + "last_update": "2024-07-07 22:56:24", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-LaVi-Bridge-Wrapper": { + "stars": 19, + "last_update": "2024-05-21 16:41:18", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-LivePortraitKJ": { + "stars": 514, + "last_update": "2024-07-09 22:17:30", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-LuminaWrapper": { + "stars": 162, + "last_update": "2024-06-28 16:33:51", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-Marigold": { + "stars": 399, + "last_update": "2024-06-19 09:10:03", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-MimicMotionWrapper": { + "stars": 126, + "last_update": "2024-07-08 11:18:03", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-OpenDiTWrapper": { + "stars": 33, + "last_update": "2024-07-03 14:59:13", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-SUPIR": { + "stars": 1240, + "last_update": "2024-07-06 23:45:09", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-SVD": { + "stars": 152, + "last_update": "2024-05-22 21:09:54", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-depth-fm": { + "stars": 54, + "last_update": "2024-05-22 21:10:15", + "author_account_age_days": 2198 + }, + "https://github.com/kijai/ComfyUI-moondream": { + "stars": 81, + "last_update": "2024-05-22 21:10:33", + "author_account_age_days": 2198 + }, + "https://github.com/kinfolk0117/ComfyUI_GradientDeepShrink": { + "stars": 23, + "last_update": "2024-05-22 21:25:13", + "author_account_age_days": 484 + }, + "https://github.com/kinfolk0117/ComfyUI_Pilgram": { + "stars": 7, + "last_update": "2024-05-22 21:25:24", + "author_account_age_days": 484 + }, + "https://github.com/kinfolk0117/ComfyUI_SimpleTiles": { + "stars": 35, + "last_update": "2024-05-22 21:25:01", + "author_account_age_days": 484 + }, + "https://github.com/klinter007/klinter_nodes": { + "stars": 6, + "last_update": "2024-06-25 05:15:24", + "author_account_age_days": 441 + }, + "https://github.com/knuknX/ComfyUI-Image-Tools": { + "stars": 3, + "last_update": "2024-06-14 09:05:58", + "author_account_age_days": 215 + }, + "https://github.com/kohya-ss/ControlNet-LLLite-ComfyUI": { + "stars": 150, + "last_update": "2024-05-22 20:44:44", + "author_account_age_days": 1824 + }, + "https://github.com/komojini/ComfyUI_SDXL_DreamBooth_LoRA_CustomNodes": { + "stars": 3, + "last_update": "2024-05-22 21:34:27", + "author_account_age_days": 598 + }, + "https://github.com/komojini/komojini-comfyui-nodes": { + "stars": 65, + "last_update": "2024-05-22 21:34:39", + "author_account_age_days": 598 + }, + "https://github.com/kunieone/ComfyUI_alkaid": { + "stars": 0, + "last_update": "2024-05-23 01:10:21", + "author_account_age_days": 2535 + }, + "https://github.com/kwaroran/abg-comfyui": { + "stars": 22, + "last_update": "2024-05-22 18:19:51", + "author_account_age_days": 623 + }, + "https://github.com/l20richo/ComfyUI-Azure-Blob-Storage": { + "stars": 2, + "last_update": "2024-06-22 16:53:47", + "author_account_age_days": 1182 + }, + "https://github.com/laksjdjf/Batch-Condition-ComfyUI": { + "stars": 1, + "last_update": "2024-05-22 20:42:42", + "author_account_age_days": 2846 + }, + "https://github.com/laksjdjf/LCMSampler-ComfyUI": { + "stars": 15, + "last_update": "2024-05-22 20:42:17", + "author_account_age_days": 2846 + }, + "https://github.com/laksjdjf/LoRTnoC-ComfyUI": { + "stars": 13, + "last_update": "2024-05-22 20:42:29", + "author_account_age_days": 2846 + }, + "https://github.com/laksjdjf/cd-tuner_negpip-ComfyUI": { + "stars": 20, + "last_update": "2024-05-22 20:42:04", + "author_account_age_days": 2846 + }, + "https://github.com/laksjdjf/cgem156-ComfyUI": { + "stars": 32, + "last_update": "2024-06-08 01:09:03", + "author_account_age_days": 2846 + }, + "https://github.com/laksjdjf/pfg-ComfyUI": { + "stars": 10, + "last_update": "2024-05-22 20:41:41", + "author_account_age_days": 2846 + }, + "https://github.com/larsupb/LoRA-Merger-ComfyUI": { + "stars": 13, + "last_update": "2024-07-02 05:55:23", + "author_account_age_days": 3091 + }, + "https://github.com/latenightlabs/ComfyUI-LNL": { + "stars": 19, + "last_update": "2024-06-28 17:27:55", + "author_account_age_days": 166 + }, + "https://github.com/leiweiqiang/ComfyUI-TRA": { + "stars": 5, + "last_update": "2024-07-09 23:36:24", + "author_account_age_days": 2626 + }, + "https://github.com/leoleelxh/ComfyUI-LLMs": { + "stars": 7, + "last_update": "2024-06-14 10:24:23", + "author_account_age_days": 4090 + }, + "https://github.com/licyk/ComfyUI-Restart-Sampler": { + "stars": 2, + "last_update": "2024-06-29 03:36:00", + "author_account_age_days": 1283 + }, + "https://github.com/lilly1987/ComfyUI_node_Lilly": { + "stars": 50, + "last_update": "2024-05-22 17:53:19", + "author_account_age_days": 2925 + }, + "https://github.com/linshier/comfyui-remote-tools": { + "stars": 1, + "last_update": "2024-05-28 07:44:23", + "author_account_age_days": 3807 + }, + "https://github.com/liusida/ComfyUI-AutoCropFaces": { + "stars": 26, + "last_update": "2024-07-05 03:24:00", + "author_account_age_days": 3223 + }, + "https://github.com/liusida/ComfyUI-B-LoRA": { + "stars": 20, + "last_update": "2024-06-18 03:17:46", + "author_account_age_days": 3223 + }, + "https://github.com/liusida/ComfyUI-Debug": { + "stars": 6, + "last_update": "2024-06-14 10:25:26", + "author_account_age_days": 3223 + }, + "https://github.com/liusida/ComfyUI-Login": { + "stars": 45, + "last_update": "2024-06-27 13:31:34", + "author_account_age_days": 3223 + }, + "https://github.com/liusida/ComfyUI-SD3-nodes": { + "stars": 4, + "last_update": "2024-06-14 13:01:41", + "author_account_age_days": 3223 + }, + "https://github.com/ljleb/comfy-mecha": { + "stars": 29, + "last_update": "2024-07-07 03:15:02", + "author_account_age_days": 2479 + }, + "https://github.com/lks-ai/ComfyUI-StableAudioSampler": { + "stars": 185, + "last_update": "2024-06-17 18:54:17", + "author_account_age_days": 115 + }, + "https://github.com/lks-ai/anynode": { + "stars": 435, + "last_update": "2024-07-07 03:45:48", + "author_account_age_days": 115 + }, + "https://github.com/lldacing/comfyui-easyapi-nodes": { + "stars": 31, + "last_update": "2024-05-24 02:51:26", + "author_account_age_days": 2108 + }, + "https://github.com/logtd/ComfyUI-FLATTEN": { + "stars": 91, + "last_update": "2024-06-14 18:00:19", + "author_account_age_days": 137 + }, + "https://github.com/logtd/ComfyUI-InstanceDiffusion": { + "stars": 145, + "last_update": "2024-05-22 00:02:08", + "author_account_age_days": 137 + }, + "https://github.com/logtd/ComfyUI-InversedNoise": { + "stars": 6, + "last_update": "2024-05-22 00:10:18", + "author_account_age_days": 137 + }, + "https://github.com/logtd/ComfyUI-RAVE_ATTN": { + "stars": 10, + "last_update": "2024-05-22 00:20:03", + "author_account_age_days": 137 + }, + "https://github.com/logtd/ComfyUI-RefSampling": { + "stars": 4, + "last_update": "2024-05-22 00:04:40", + "author_account_age_days": 137 + }, + "https://github.com/logtd/ComfyUI-TrackingNodes": { + "stars": 15, + "last_update": "2024-05-22 00:03:27", + "author_account_age_days": 137 + }, + "https://github.com/longgui0318/comfyui-common-util": { + "stars": 0, + "last_update": "2024-07-08 08:57:06", + "author_account_age_days": 4180 + }, + "https://github.com/longgui0318/comfyui-llm-assistant": { + "stars": 5, + "last_update": "2024-06-27 03:50:46", + "author_account_age_days": 4180 + }, + "https://github.com/longgui0318/comfyui-magic-clothing": { + "stars": 24, + "last_update": "2024-06-27 03:48:38", + "author_account_age_days": 4180 + }, + "https://github.com/longgui0318/comfyui-mask-util": { + "stars": 6, + "last_update": "2024-06-30 03:43:58", + "author_account_age_days": 4180 + }, + "https://github.com/longgui0318/comfyui-oms-diffusion": { + "stars": 24, + "last_update": "2024-06-27 03:48:38", + "author_account_age_days": 4180 + }, + "https://github.com/lordgasmic/comfyui_save_image_with_options": { + "stars": 0, + "last_update": "2024-06-20 16:39:23", + "author_account_age_days": 4782 + }, + "https://github.com/lordgasmic/comfyui_wildcards": { + "stars": 5, + "last_update": "2024-06-20 16:52:14", + "author_account_age_days": 4782 + }, + "https://github.com/lquesada/ComfyUI-Inpaint-CropAndStitch": { + "stars": 165, + "last_update": "2024-06-21 10:54:35", + "author_account_age_days": 4066 + }, + "https://github.com/lquesada/ComfyUI-Prompt-Combinator": { + "stars": 21, + "last_update": "2024-06-30 15:37:31", + "author_account_age_days": 4066 + }, + "https://github.com/ltdrdata/ComfyUI-Impact-Pack": { + "stars": 1451, + "last_update": "2024-07-06 09:25:25", + "author_account_age_days": 477 + }, + "https://github.com/ltdrdata/ComfyUI-Inspire-Pack": { + "stars": 300, + "last_update": "2024-07-09 11:07:42", + "author_account_age_days": 477 + }, + "https://github.com/ltdrdata/ComfyUI-Manager": { + "stars": 4667, + "last_update": "2024-07-09 19:59:22", + "author_account_age_days": 477 + }, + "https://github.com/luandev/ComfyUI-CrewAI": { + "stars": 13, + "last_update": "2024-06-27 17:53:19", + "author_account_age_days": 3823 + }, + "https://github.com/m-sokes/ComfyUI-Sokes-Nodes": { + "stars": 1, + "last_update": "2024-05-22 20:36:07", + "author_account_age_days": 331 + }, + "https://github.com/madtunebk/ComfyUI-ControlnetAux": { + "stars": 10, + "last_update": "2024-06-28 16:16:51", + "author_account_age_days": 476 + }, + "https://github.com/mape/ComfyUI-mape-Helpers": { + "stars": 135, + "last_update": "2024-06-27 16:30:32", + "author_account_age_days": 5770 + }, + "https://github.com/maracman/ComfyUI-SubjectStyle-CSV": { + "stars": 3, + "last_update": "2024-06-24 13:53:39", + "author_account_age_days": 1182 + }, + "https://github.com/marduk191/comfyui-marnodes": { + "stars": 0, + "last_update": "2024-06-30 21:20:15", + "author_account_age_days": 4430 + }, + "https://github.com/marhensa/sdxl-recommended-res-calc": { + "stars": 56, + "last_update": "2024-07-07 09:20:15", + "author_account_age_days": 4790 + }, + "https://github.com/martijnat/comfyui-previewlatent": { + "stars": 29, + "last_update": "2024-05-22 21:28:39", + "author_account_age_days": 2847 + }, + "https://github.com/massao000/ComfyUI_aspect_ratios": { + "stars": 7, + "last_update": "2024-05-22 22:23:10", + "author_account_age_days": 1422 + }, + "https://github.com/matan1905/ComfyUI-Serving-Toolkit": { + "stars": 39, + "last_update": "2024-06-04 19:15:36", + "author_account_age_days": 2755 + }, + "https://github.com/mav-rik/facerestore_cf": { + "stars": 158, + "last_update": "2024-05-22 20:53:23", + "author_account_age_days": 2936 + }, + "https://github.com/mbrostami/ComfyUI-HF": { + "stars": 16, + "last_update": "2024-05-27 21:45:33", + "author_account_age_days": 4337 + }, + "https://github.com/mbrostami/ComfyUI-TITrain": { + "stars": 7, + "last_update": "2024-05-27 21:50:06", + "author_account_age_days": 4337 + }, + "https://github.com/mcmonkeyprojects/sd-dynamic-thresholding": { + "stars": 1070, + "last_update": "2024-05-24 16:09:17", + "author_account_age_days": 2117 + }, + "https://github.com/meap158/ComfyUI-Background-Replacement": { + "stars": 42, + "last_update": "2024-05-22 20:43:52", + "author_account_age_days": 3218 + }, + "https://github.com/meap158/ComfyUI-GPU-temperature-protection": { + "stars": 3, + "last_update": "2024-05-22 20:43:21", + "author_account_age_days": 3218 + }, + "https://github.com/meap158/ComfyUI-Prompt-Expansion": { + "stars": 62, + "last_update": "2024-05-22 20:43:37", + "author_account_age_days": 3218 + }, + "https://github.com/melMass/comfy_mtb": { + "stars": 358, + "last_update": "2024-07-07 18:40:33", + "author_account_age_days": 3761 + }, + "https://github.com/mephisto83/petty-paint-comfyui-node": { + "stars": 2, + "last_update": "2024-07-05 19:04:04", + "author_account_age_days": 3688 + }, + "https://github.com/meshmesh-io/ComfyUI-MeshMesh": { + "stars": 0, + "last_update": "2024-05-23 00:10:09", + "author_account_age_days": 244 + }, + "https://github.com/meshmesh-io/mm-comfyui-loopback": { + "stars": 1, + "last_update": "2024-05-23 00:09:57", + "author_account_age_days": 244 + }, + "https://github.com/meshmesh-io/mm-comfyui-megamask": { + "stars": 0, + "last_update": "2024-05-23 00:09:47", + "author_account_age_days": 244 + }, + "https://github.com/metncelik/comfyui_met_suit": { + "stars": 0, + "last_update": "2024-07-07 13:40:26", + "author_account_age_days": 638 + }, + "https://github.com/metncelik/comfyui_met_suite": { + "stars": 0, + "last_update": "2024-07-07 13:40:26", + "author_account_age_days": 638 + }, + "https://github.com/mihaiiancu/ComfyUI_Inpaint": { + "stars": 9, + "last_update": "2024-05-22 18:19:38", + "author_account_age_days": 2677 + }, + "https://github.com/mikkel/ComfyUI-text-overlay": { + "stars": 29, + "last_update": "2024-05-22 21:13:59", + "author_account_age_days": 5932 + }, + "https://github.com/mikkel/comfyui-mask-boundingbox": { + "stars": 25, + "last_update": "2024-05-22 21:26:23", + "author_account_age_days": 5932 + }, + "https://github.com/mingqizhang/ComfyUI_InSPyResNet_zmq": { + "stars": 0, + "last_update": "2024-06-28 15:59:20", + "author_account_age_days": 2609 + }, + "https://github.com/mirabarukaso/ComfyUI_Mira": { + "stars": 24, + "last_update": "2024-06-14 11:01:10", + "author_account_age_days": 1236 + }, + "https://github.com/modusCell/ComfyUI-dimension-node-modusCell": { + "stars": 1, + "last_update": "2024-05-22 22:08:50", + "author_account_age_days": 4619 + }, + "https://github.com/moyi7712/ComfyUI_Seamless_Patten": { + "stars": 10, + "last_update": "2024-06-22 02:18:14", + "author_account_age_days": 2316 + }, + "https://github.com/mozman/ComfyUI_mozman_nodes": { + "stars": 0, + "last_update": "2024-05-22 22:13:32", + "author_account_age_days": 4095 + }, + "https://github.com/mpiquero7164/ComfyUI-SaveImgPrompt": { + "stars": 16, + "last_update": "2023-08-14 11:27:09", + "author_account_age_days": 2624 + }, + "https://github.com/mullakhmetov/comfyui_dynamic_util_nodes": { + "stars": 0, + "last_update": "2024-07-09 10:26:31", + "author_account_age_days": 3953 + }, + "https://github.com/muzi12888/ComfyUI-PoseKeypoint-Mask": { + "stars": 6, + "last_update": "2024-06-14 13:26:02", + "author_account_age_days": 2961 + }, + "https://github.com/my-opencode/ComfyUI_IndustrialMagick": { + "stars": 1, + "last_update": "2024-07-08 12:25:30", + "author_account_age_days": 1395 + }, + "https://github.com/my-opencode/ComfyUI_KSamplerTimer": { + "stars": 1, + "last_update": "2024-07-08 12:22:33", + "author_account_age_days": 1395 + }, + "https://github.com/nagolinc/ComfyUI_FastVAEDecorder_SDXL": { + "stars": 2, + "last_update": "2024-05-22 20:44:17", + "author_account_age_days": 3689 + }, + "https://github.com/nagolinc/comfyui_openai_node": { + "stars": 0, + "last_update": "2024-06-15 15:59:07", + "author_account_age_days": 3689 + }, + "https://github.com/nat-chan/ComfyUI-graphToPrompt": { + "stars": 0, + "last_update": "2024-05-23 01:16:40", + "author_account_age_days": 3008 + }, + "https://github.com/nat-chan/comfyui-paint": { + "stars": 2, + "last_update": "2024-06-14 11:01:38", + "author_account_age_days": 3008 + }, + "https://github.com/nat-chan/comfyui-transceiver": { + "stars": 3, + "last_update": "2024-05-23 01:16:28", + "author_account_age_days": 3008 + }, + "https://github.com/nathannlu/ComfyUI-Cloud": { + "stars": 156, + "last_update": "2024-06-30 06:18:52", + "author_account_age_days": 2741 + }, + "https://github.com/nathannlu/ComfyUI-Pets": { + "stars": 37, + "last_update": "2024-06-14 11:00:42", + "author_account_age_days": 2741 + }, + "https://github.com/natto-maki/ComfyUI-NegiTools": { + "stars": 26, + "last_update": "2024-05-22 21:31:17", + "author_account_age_days": 293 + }, + "https://github.com/nickve28/ComfyUI-Nich-Utils": { + "stars": 8, + "last_update": "2024-06-22 05:29:37", + "author_account_age_days": 4044 + }, + "https://github.com/ningxiaoxiao/comfyui-NDI": { + "stars": 36, + "last_update": "2024-07-02 09:03:11", + "author_account_age_days": 3003 + }, + "https://github.com/nirbhay-faaya/ImgProcessing_ComfyUI": { + "stars": 0, + "last_update": "2024-06-14 12:01:14", + "author_account_age_days": 351 + }, + "https://github.com/nirex0/ComfyUI_pytorch_openpose": { + "stars": 2, + "last_update": "2024-06-14 12:01:07", + "author_account_age_days": 3518 + }, + "https://github.com/nkchocoai/ComfyUI-Dart": { + "stars": 18, + "last_update": "2024-06-23 04:56:49", + "author_account_age_days": 175 + }, + "https://github.com/nkchocoai/ComfyUI-PromptUtilities": { + "stars": 6, + "last_update": "2024-06-23 04:58:30", + "author_account_age_days": 175 + }, + "https://github.com/nkchocoai/ComfyUI-SaveImageWithMetaData": { + "stars": 9, + "last_update": "2024-06-23 04:57:38", + "author_account_age_days": 175 + }, + "https://github.com/nkchocoai/ComfyUI-SizeFromPresets": { + "stars": 4, + "last_update": "2024-06-23 04:40:00", + "author_account_age_days": 175 + }, + "https://github.com/nkchocoai/ComfyUI-TextOnSegs": { + "stars": 7, + "last_update": "2024-06-23 04:52:29", + "author_account_age_days": 175 + }, + "https://github.com/noembryo/ComfyUI-noEmbryo": { + "stars": 13, + "last_update": "2024-06-04 11:27:45", + "author_account_age_days": 2758 + }, + "https://github.com/nosiu/comfyui-instantId-faceswap": { + "stars": 176, + "last_update": "2024-05-22 23:21:38", + "author_account_age_days": 3920 + }, + "https://github.com/noxinias/ComfyUI_NoxinNodes": { + "stars": 7, + "last_update": "2024-05-22 21:24:24", + "author_account_age_days": 2576 + }, + "https://github.com/ntc-ai/ComfyUI-DARE-LoRA-Merge": { + "stars": 24, + "last_update": "2024-05-22 22:22:14", + "author_account_age_days": 1733 + }, + "https://github.com/nuanarchy/ComfyUI-NuA-BIRD": { + "stars": 4, + "last_update": "2024-06-18 05:35:49", + "author_account_age_days": 1107 + }, + "https://github.com/nuanarchy/ComfyUI-NuA-FlashFace": { + "stars": 14, + "last_update": "2024-06-17 15:29:15", + "author_account_age_days": 1107 + }, + "https://github.com/nullquant/ComfyUI-BrushNet": { + "stars": 404, + "last_update": "2024-06-19 16:24:00", + "author_account_age_days": 1192 + }, + "https://github.com/olduvai-jp/ComfyUI-HfLoader": { + "stars": 3, + "last_update": "2024-05-23 00:14:52", + "author_account_age_days": 891 + }, + "https://github.com/omar92/ComfyUI-QualityOfLifeSuit_Omar92": { + "stars": 111, + "last_update": "2024-06-03 11:02:37", + "author_account_age_days": 4522 + }, + "https://github.com/opvelll/ComfyUI_TextListProduct": { + "stars": 0, + "last_update": "2024-06-22 02:11:26", + "author_account_age_days": 1570 + }, + "https://github.com/osi1880vr/prompt_quill_comfyui": { + "stars": 10, + "last_update": "2024-06-13 17:24:12", + "author_account_age_days": 1092 + }, + "https://github.com/ostris/ostris_nodes_comfyui": { + "stars": 19, + "last_update": "2024-05-22 21:23:24", + "author_account_age_days": 2418 + }, + "https://github.com/ownimage/ComfyUI-ownimage": { + "stars": 0, + "last_update": "2024-05-22 22:22:37", + "author_account_age_days": 2798 + }, + "https://github.com/oyvindg/ComfyUI-TrollSuite": { + "stars": 0, + "last_update": "2024-05-22 21:32:03", + "author_account_age_days": 2345 + }, + "https://github.com/oztrkoguz/ComfyUI_StoryCreator": { + "stars": 19, + "last_update": "2024-05-23 12:18:45", + "author_account_age_days": 857 + }, + "https://github.com/palant/extended-saveimage-comfyui": { + "stars": 11, + "last_update": "2024-03-27 14:08:21", + "author_account_age_days": 5068 + }, + "https://github.com/palant/image-resize-comfyui": { + "stars": 62, + "last_update": "2024-01-18 20:59:55", + "author_account_age_days": 5068 + }, + "https://github.com/palant/integrated-nodes-comfyui": { + "stars": 32, + "last_update": "2023-12-27 22:52:00", + "author_account_age_days": 5068 + }, + "https://github.com/pamparamm/ComfyUI-vectorscope-cc": { + "stars": 2, + "last_update": "2024-07-08 16:05:59", + "author_account_age_days": 2146 + }, + "https://github.com/pamparamm/sd-perturbed-attention": { + "stars": 183, + "last_update": "2024-06-29 05:44:18", + "author_account_age_days": 2146 + }, + "https://github.com/pants007/comfy-pants": { + "stars": 2, + "last_update": "2024-05-22 18:16:04", + "author_account_age_days": 2332 + }, + "https://github.com/paulo-coronado/comfy_clip_blip_node": { + "stars": 25, + "last_update": "2024-05-22 17:39:09", + "author_account_age_days": 2702 + }, + "https://github.com/philz1337x/ComfyUI-ClarityAI": { + "stars": 47, + "last_update": "2024-05-23 01:19:05", + "author_account_age_days": 679 + }, + "https://github.com/phineas-pta/comfyui-auto-nodes-layout": { + "stars": 26, + "last_update": "2024-06-19 21:38:47", + "author_account_age_days": 2304 + }, + "https://github.com/picturesonpictures/comfy_PoP": { + "stars": 15, + "last_update": "2024-07-05 07:32:50", + "author_account_age_days": 602 + }, + "https://github.com/pkpkTech/ComfyUI-SaveAVIF": { + "stars": 0, + "last_update": "2024-05-22 22:19:21", + "author_account_age_days": 1518 + }, + "https://github.com/pkpkTech/ComfyUI-SaveQueues": { + "stars": 1, + "last_update": "2024-05-22 22:19:54", + "author_account_age_days": 1518 + }, + "https://github.com/pkpkTech/ComfyUI-TemporaryLoader": { + "stars": 1, + "last_update": "2024-05-22 22:19:44", + "author_account_age_days": 1518 + }, + "https://github.com/pkpkTech/ComfyUI-ngrok": { + "stars": 3, + "last_update": "2024-05-22 22:19:32", + "author_account_age_days": 1518 + }, + "https://github.com/portu-sim/comfyui_bmab": { + "stars": 39, + "last_update": "2024-06-09 14:22:04", + "author_account_age_days": 337 + }, + "https://github.com/prodogape/ComfyUI-EasyOCR": { + "stars": 8, + "last_update": "2024-07-03 05:54:03", + "author_account_age_days": 1045 + }, + "https://github.com/prodogape/ComfyUI-Minio": { + "stars": 2, + "last_update": "2024-05-23 00:13:38", + "author_account_age_days": 1045 + }, + "https://github.com/prodogape/ComfyUI-OmDet": { + "stars": 2, + "last_update": "2024-06-14 13:01:34", + "author_account_age_days": 1045 + }, + "https://github.com/prodogape/Comfyui-Yolov8-JSON": { + "stars": 12, + "last_update": "2024-07-03 03:59:38", + "author_account_age_days": 1045 + }, + "https://github.com/prozacgod/comfyui-pzc-multiworkspace": { + "stars": 7, + "last_update": "2024-05-22 23:11:46", + "author_account_age_days": 5583 + }, + "https://github.com/pythongosssss/ComfyUI-Custom-Scripts": { + "stars": 1387, + "last_update": "2024-06-29 20:47:22", + "author_account_age_days": 513 + }, + "https://github.com/pythongosssss/ComfyUI-WD14-Tagger": { + "stars": 444, + "last_update": "2024-06-20 05:38:50", + "author_account_age_days": 513 + }, + "https://github.com/qwixiwp/queuetools": { + "stars": 0, + "last_update": "2024-06-14 10:27:57", + "author_account_age_days": 626 + }, + "https://github.com/ramyma/A8R8_ComfyUI_nodes": { + "stars": 40, + "last_update": "2024-06-29 01:20:57", + "author_account_age_days": 3232 + }, + "https://github.com/randjtw/advance-aesthetic-score": { + "stars": 0, + "last_update": "2024-05-23 01:14:47", + "author_account_age_days": 776 + }, + "https://github.com/ratulrafsan/Comfyui-SAL-VTON": { + "stars": 61, + "last_update": "2024-06-30 02:23:06", + "author_account_age_days": 4509 + }, + "https://github.com/rcfcu2000/zhihuige-nodes-comfyui": { + "stars": 0, + "last_update": "2024-05-22 22:13:55", + "author_account_age_days": 3440 + }, + "https://github.com/rcsaquino/comfyui-custom-nodes": { + "stars": 1, + "last_update": "2024-05-22 22:13:43", + "author_account_age_days": 1526 + }, + "https://github.com/receyuki/comfyui-prompt-reader-node": { + "stars": 215, + "last_update": "2024-06-28 07:20:59", + "author_account_age_days": 2608 + }, + "https://github.com/redhottensors/ComfyUI-ODE": { + "stars": 24, + "last_update": "2024-06-23 22:16:53", + "author_account_age_days": 154 + }, + "https://github.com/redhottensors/ComfyUI-Prediction": { + "stars": 10, + "last_update": "2024-06-14 10:25:44", + "author_account_age_days": 154 + }, + "https://github.com/rgthree/rgthree-comfy": { + "stars": 750, + "last_update": "2024-07-06 18:08:21", + "author_account_age_days": 4990 + }, + "https://github.com/rhdunn/comfyui-bus-plugin": { + "stars": 1, + "last_update": "2024-06-26 17:38:32", + "author_account_age_days": 5652 + }, + "https://github.com/richinsley/Comfy-LFO": { + "stars": 5, + "last_update": "2024-05-22 20:46:30", + "author_account_age_days": 2696 + }, + "https://github.com/ricklove/comfyui-ricklove": { + "stars": 0, + "last_update": "2024-05-22 23:21:25", + "author_account_age_days": 4848 + }, + "https://github.com/risunobushi/comfyUI_FrequencySeparation_RGB-HSV": { + "stars": 12, + "last_update": "2024-06-14 10:28:04", + "author_account_age_days": 662 + }, + "https://github.com/rklaffehn/rk-comfy-nodes": { + "stars": 2, + "last_update": "2024-06-14 10:24:43", + "author_account_age_days": 308 + }, + "https://github.com/romeobuilderotti/ComfyUI-PNG-Metadata": { + "stars": 4, + "last_update": "2024-05-22 21:29:25", + "author_account_age_days": 306 + }, + "https://github.com/ronniebasak/ComfyUI-Tara-LLM-Integration": { + "stars": 75, + "last_update": "2024-06-25 09:06:23", + "author_account_age_days": 4170 + }, + "https://github.com/royceschultz/ComfyUI-Notifications": { + "stars": 6, + "last_update": "2024-05-23 01:23:16", + "author_account_age_days": 2545 + }, + "https://github.com/royceschultz/ComfyUI-TranscriptionTools": { + "stars": 12, + "last_update": "2024-05-23 01:10:10", + "author_account_age_days": 2545 + }, + "https://github.com/rui40000/RUI-Nodes": { + "stars": 15, + "last_update": "2024-05-22 22:12:26", + "author_account_age_days": 489 + }, + "https://github.com/ruiqutech/ComfyUI-RuiquNodes": { + "stars": 0, + "last_update": "2024-05-23 01:21:50", + "author_account_age_days": 85 + }, + "https://github.com/runtime44/comfyui_r44_nodes": { + "stars": 32, + "last_update": "2024-07-01 08:02:04", + "author_account_age_days": 183 + }, + "https://github.com/saftle/suplex_comfy_nodes": { + "stars": 0, + "last_update": "2024-05-29 13:09:25", + "author_account_age_days": 4773 + }, + "https://github.com/sdfxai/SDFXBridgeForComfyUI": { + "stars": 8, + "last_update": "2024-06-14 10:26:56", + "author_account_age_days": 250 + }, + "https://github.com/seanlynch/comfyui-optical-flow": { + "stars": 26, + "last_update": "2024-05-22 20:52:17", + "author_account_age_days": 5320 + }, + "https://github.com/seanlynch/srl-nodes": { + "stars": 3, + "last_update": "2024-06-30 13:47:38", + "author_account_age_days": 5320 + }, + "https://github.com/sergekatzmann/ComfyUI_Nimbus-Pack": { + "stars": 2, + "last_update": "2024-05-22 21:34:15", + "author_account_age_days": 3348 + }, + "https://github.com/shadowcz007/comfyui-Image-reward": { + "stars": 21, + "last_update": "2024-06-14 10:24:49", + "author_account_age_days": 3330 + }, + "https://github.com/shadowcz007/comfyui-consistency-decoder": { + "stars": 2, + "last_update": "2024-06-14 10:23:35", + "author_account_age_days": 3330 + }, + "https://github.com/shadowcz007/comfyui-edit-mask": { + "stars": 6, + "last_update": "2024-06-20 01:42:48", + "author_account_age_days": 3330 + }, + "https://github.com/shadowcz007/comfyui-liveportrait": { + "stars": 190, + "last_update": "2024-07-07 15:59:06", + "author_account_age_days": 3330 + }, + "https://github.com/shadowcz007/comfyui-mixlab-nodes": { + "stars": 928, + "last_update": "2024-07-07 16:03:59", + "author_account_age_days": 3330 + }, + "https://github.com/shadowcz007/comfyui-sound-lab": { + "stars": 65, + "last_update": "2024-07-04 12:53:38", + "author_account_age_days": 3330 + }, + "https://github.com/shadowcz007/comfyui-ultralytics-yolo": { + "stars": 18, + "last_update": "2024-06-22 09:06:04", + "author_account_age_days": 3330 + }, + "https://github.com/shi3z/ComfyUI_Memeplex_DALLE": { + "stars": 2, + "last_update": "2024-05-23 00:14:25", + "author_account_age_days": 5108 + }, + "https://github.com/shiimizu/ComfyUI-PhotoMaker-Plus": { + "stars": 144, + "last_update": "2024-04-17 09:02:51", + "author_account_age_days": 1780 + }, + "https://github.com/shiimizu/ComfyUI-TiledDiffusion": { + "stars": 217, + "last_update": "2024-05-14 22:01:41", + "author_account_age_days": 1780 + }, + "https://github.com/shiimizu/ComfyUI_smZNodes": { + "stars": 158, + "last_update": "2024-06-18 07:30:24", + "author_account_age_days": 1780 + }, + "https://github.com/shingo1228/ComfyUI-SDXL-EmptyLatentImage": { + "stars": 27, + "last_update": "2024-05-22 20:41:29", + "author_account_age_days": 2238 + }, + "https://github.com/shingo1228/ComfyUI-send-eagle-slim": { + "stars": 22, + "last_update": "2024-05-22 20:41:15", + "author_account_age_days": 2238 + }, + "https://github.com/shinich39/comfyui-load-image-in-seq": { + "stars": 3, + "last_update": "2024-07-03 03:40:21", + "author_account_age_days": 328 + }, + "https://github.com/shinich39/comfyui-local-db": { + "stars": 1, + "last_update": "2024-07-03 03:42:46", + "author_account_age_days": 328 + }, + "https://github.com/shinich39/comfyui-ramdom-node": { + "stars": 2, + "last_update": "2024-07-03 03:11:28", + "author_account_age_days": 328 + }, + "https://github.com/shobhitic/ComfyUI-PlusMinusTextClip": { + "stars": 3, + "last_update": "2024-06-20 13:57:29", + "author_account_age_days": 4323 + }, + "https://github.com/shockz0rz/ComfyUI_InterpolateEverything": { + "stars": 23, + "last_update": "2024-05-22 18:13:49", + "author_account_age_days": 1641 + }, + "https://github.com/shockz0rz/comfy-easy-grids": { + "stars": 12, + "last_update": "2024-05-22 18:14:05", + "author_account_age_days": 1641 + }, + "https://github.com/siliconflow/onediff_comfy_nodes": { + "stars": 14, + "last_update": "2024-06-24 10:08:11", + "author_account_age_days": 321 + }, + "https://github.com/sipherxyz/comfyui-art-venture": { + "stars": 92, + "last_update": "2024-06-28 02:06:23", + "author_account_age_days": 1122 + }, + "https://github.com/skfoo/ComfyUI-Coziness": { + "stars": 22, + "last_update": "2024-05-27 18:24:29", + "author_account_age_days": 2097 + }, + "https://github.com/slyt/comfyui-ollama-nodes": { + "stars": 0, + "last_update": "2024-06-25 03:31:41", + "author_account_age_days": 3955 + }, + "https://github.com/smagnetize/kb-comfyui-nodes": { + "stars": 0, + "last_update": "2024-06-14 12:00:45", + "author_account_age_days": 2730 + }, + "https://github.com/smthemex/ComfyUI_AnyDoor": { + "stars": 19, + "last_update": "2024-07-09 07:37:40", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_ChatGLM_API": { + "stars": 18, + "last_update": "2024-06-25 04:10:29", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_CustomNet": { + "stars": 4, + "last_update": "2024-06-25 01:04:17", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_HiDiffusion_Pro": { + "stars": 31, + "last_update": "2024-07-04 11:51:49", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_ID_Animator": { + "stars": 20, + "last_update": "2024-06-27 08:32:11", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_Llama3_8B": { + "stars": 18, + "last_update": "2024-06-25 00:49:01", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_MS_Diffusion": { + "stars": 7, + "last_update": "2024-07-09 13:42:13", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_ParlerTTS": { + "stars": 21, + "last_update": "2024-06-25 00:38:01", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_Pic2Story": { + "stars": 3, + "last_update": "2024-06-25 01:16:30", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_Pipeline_Tool": { + "stars": 8, + "last_update": "2024-06-25 01:13:53", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_Pops": { + "stars": 16, + "last_update": "2024-07-04 13:09:15", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_StableAudio_Open": { + "stars": 7, + "last_update": "2024-06-25 00:56:09", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_StoryDiffusion": { + "stars": 69, + "last_update": "2024-07-09 12:11:17", + "author_account_age_days": 369 + }, + "https://github.com/smthemex/ComfyUI_Streamv2v_Plus": { + "stars": 0, + "last_update": "2024-06-25 00:52:41", + "author_account_age_days": 369 + }, + "https://github.com/space-nuko/ComfyUI-Disco-Diffusion": { + "stars": 42, + "last_update": "2024-05-22 18:10:36", + "author_account_age_days": 2740 + }, + "https://github.com/space-nuko/ComfyUI-OpenPose-Editor": { + "stars": 155, + "last_update": "2024-05-22 18:10:49", + "author_account_age_days": 2740 + }, + "https://github.com/space-nuko/nui-suite": { + "stars": 10, + "last_update": "2024-05-22 18:11:04", + "author_account_age_days": 2740 + }, + "https://github.com/spacepxl/ComfyUI-Florence-2": { + "stars": 39, + "last_update": "2024-06-29 13:13:01", + "author_account_age_days": 310 + }, + "https://github.com/spacepxl/ComfyUI-HQ-Image-Save": { + "stars": 32, + "last_update": "2024-06-21 04:42:58", + "author_account_age_days": 310 + }, + "https://github.com/spacepxl/ComfyUI-Image-Filters": { + "stars": 85, + "last_update": "2024-06-22 01:19:31", + "author_account_age_days": 310 + }, + "https://github.com/spacepxl/ComfyUI-RAVE": { + "stars": 83, + "last_update": "2024-05-22 20:56:19", + "author_account_age_days": 310 + }, + "https://github.com/spacepxl/ComfyUI-StyleGan": { + "stars": 5, + "last_update": "2024-06-10 20:16:34", + "author_account_age_days": 310 + }, + "https://github.com/spinagon/ComfyUI-seam-carving": { + "stars": 15, + "last_update": "2024-05-23 05:07:00", + "author_account_age_days": 4756 + }, + "https://github.com/spinagon/ComfyUI-seamless-tiling": { + "stars": 78, + "last_update": "2024-05-23 05:03:42", + "author_account_age_days": 4756 + }, + "https://github.com/spro/comfyui-mirror": { + "stars": 4, + "last_update": "2024-05-22 20:50:25", + "author_account_age_days": 5247 + }, + "https://github.com/ssitu/ComfyUI_UltimateSDUpscale": { + "stars": 656, + "last_update": "2024-06-27 04:16:12", + "author_account_age_days": 1704 + }, + "https://github.com/ssitu/ComfyUI_fabric": { + "stars": 84, + "last_update": "2024-05-22 18:10:19", + "author_account_age_days": 1704 + }, + "https://github.com/ssitu/ComfyUI_restart_sampling": { + "stars": 78, + "last_update": "2024-05-22 18:09:49", + "author_account_age_days": 1704 + }, + "https://github.com/ssitu/ComfyUI_roop": { + "stars": 61, + "last_update": "2024-05-22 18:10:03", + "author_account_age_days": 1704 + }, + "https://github.com/stavsap/comfyui-ollama": { + "stars": 206, + "last_update": "2024-06-28 04:00:40", + "author_account_age_days": 4099 + }, + "https://github.com/storyicon/comfyui_musev_evolved": { + "stars": 14, + "last_update": "2024-06-14 11:02:40", + "author_account_age_days": 2567 + }, + "https://github.com/storyicon/comfyui_segment_anything": { + "stars": 545, + "last_update": "2024-05-31 07:36:30", + "author_account_age_days": 2567 + }, + "https://github.com/strimmlarn/ComfyUI_Strimmlarns_aesthetic_score": { + "stars": 25, + "last_update": "2024-06-17 10:01:44", + "author_account_age_days": 2642 + }, + "https://github.com/styler00dollar/ComfyUI-deepcache": { + "stars": 8, + "last_update": "2024-05-22 22:18:18", + "author_account_age_days": 1861 + }, + "https://github.com/styler00dollar/ComfyUI-sudo-latent-upscale": { + "stars": 27, + "last_update": "2024-05-22 22:18:07", + "author_account_age_days": 1861 + }, + "https://github.com/subtleGradient/TinkerBot-tech-for-ComfyUI-Touchpad": { + "stars": 20, + "last_update": "2024-06-19 04:30:39", + "author_account_age_days": 5946 + }, + "https://github.com/sugarkwork/comfyui_cohere": { + "stars": 0, + "last_update": "2024-06-14 13:59:30", + "author_account_age_days": 891 + }, + "https://github.com/sugarkwork/comfyui_tag_fillter": { + "stars": 18, + "last_update": "2024-07-02 00:21:03", + "author_account_age_days": 891 + }, + "https://github.com/superyoman/comfyui_lumaAPI": { + "stars": 13, + "last_update": "2024-06-17 21:00:05", + "author_account_age_days": 464 + }, + "https://github.com/syllebra/bilbox-comfyui": { + "stars": 82, + "last_update": "2024-05-22 20:40:43", + "author_account_age_days": 3151 + }, + "https://github.com/sylym/comfy_vid2vid": { + "stars": 58, + "last_update": "2024-05-22 17:53:40", + "author_account_age_days": 1913 + }, + "https://github.com/szhublox/ambw_comfyui": { + "stars": 13, + "last_update": "2024-05-22 18:04:57", + "author_account_age_days": 1022 + }, + "https://github.com/taabata/LCM_Inpaint-Outpaint_Comfy": { + "stars": 227, + "last_update": "2024-06-17 10:01:50", + "author_account_age_days": 1698 + }, + "https://github.com/talesofai/comfyui-browser": { + "stars": 430, + "last_update": "2024-07-01 12:41:20", + "author_account_age_days": 571 + }, + "https://github.com/teward/ComfyUI-Helper-Nodes": { + "stars": 4, + "last_update": "2024-05-23 01:22:01", + "author_account_age_days": 5113 + }, + "https://github.com/theUpsider/ComfyUI-Logic": { + "stars": 112, + "last_update": "2024-07-02 09:38:11", + "author_account_age_days": 2738 + }, + "https://github.com/theUpsider/ComfyUI-Styles_CSV_Loader": { + "stars": 29, + "last_update": "2024-07-01 08:45:52", + "author_account_age_days": 2738 + }, + "https://github.com/thecooltechguy/ComfyUI-ComfyRun": { + "stars": 78, + "last_update": "2024-05-22 21:33:11", + "author_account_age_days": 2438 + }, + "https://github.com/thecooltechguy/ComfyUI-ComfyWorkflows": { + "stars": 33, + "last_update": "2024-05-22 21:33:47", + "author_account_age_days": 2438 + }, + "https://github.com/thecooltechguy/ComfyUI-MagicAnimate": { + "stars": 203, + "last_update": "2024-05-22 21:33:35", + "author_account_age_days": 2438 + }, + "https://github.com/thecooltechguy/ComfyUI-Stable-Video-Diffusion": { + "stars": 291, + "last_update": "2024-05-24 22:14:42", + "author_account_age_days": 2438 + }, + "https://github.com/tiankuan93/ComfyUI-V-Express": { + "stars": 87, + "last_update": "2024-06-26 02:41:00", + "author_account_age_days": 2965 + }, + "https://github.com/tianlang0704/ComfyUI-StableProjectorzBridge": { + "stars": 9, + "last_update": "2024-07-09 10:09:44", + "author_account_age_days": 3340 + }, + "https://github.com/tmagara/ComfyUI-Prediction-Boost": { + "stars": 1, + "last_update": "2024-06-21 05:28:58", + "author_account_age_days": 4390 + }, + "https://github.com/tocubed/ComfyUI-AudioReactor": { + "stars": 8, + "last_update": "2024-05-22 22:21:57", + "author_account_age_days": 3875 + }, + "https://github.com/tooldigital/ComfyUI-Yolo-Cropper": { + "stars": 6, + "last_update": "2024-06-14 13:59:48", + "author_account_age_days": 4333 + }, + "https://github.com/toxicwind/ComfyUI-TTools": { + "stars": 1, + "last_update": "2024-07-04 20:07:35", + "author_account_age_days": 4385 + }, + "https://github.com/toyxyz/ComfyUI_toyxyz_test_nodes": { + "stars": 472, + "last_update": "2024-06-18 15:27:19", + "author_account_age_days": 3665 + }, + "https://github.com/traugdor/ComfyUI-quadMoons-nodes": { + "stars": 9, + "last_update": "2024-06-22 14:28:25", + "author_account_age_days": 3835 + }, + "https://github.com/tritant/ComfyUI_CreaPrompt": { + "stars": 10, + "last_update": "2024-07-07 11:36:51", + "author_account_age_days": 3156 + }, + "https://github.com/trojblue/trNodes": { + "stars": 8, + "last_update": "2024-05-22 18:04:36", + "author_account_age_days": 2273 + }, + "https://github.com/trumanwong/ComfyUI-NSFW-Detection": { + "stars": 19, + "last_update": "2024-05-23 01:27:29", + "author_account_age_days": 2975 + }, + "https://github.com/tsogzark/ComfyUI-load-image-from-url": { + "stars": 7, + "last_update": "2024-06-14 13:59:05", + "author_account_age_days": 1544 + }, + "https://github.com/ttulttul/ComfyUI-Iterative-Mixer": { + "stars": 100, + "last_update": "2024-07-09 14:56:02", + "author_account_age_days": 4773 + }, + "https://github.com/ttulttul/ComfyUI-Tensor-Operations": { + "stars": 5, + "last_update": "2024-06-12 21:55:39", + "author_account_age_days": 4773 + }, + "https://github.com/tusharbhutt/Endless-Nodes": { + "stars": 22, + "last_update": "2024-06-14 12:02:17", + "author_account_age_days": 2680 + }, + "https://github.com/twri/sdxl_prompt_styler": { + "stars": 636, + "last_update": "2024-05-22 18:16:58", + "author_account_age_days": 4083 + }, + "https://github.com/txt2any/ComfyUI-PromptOrganizer": { + "stars": 0, + "last_update": "2024-05-23 01:10:33", + "author_account_age_days": 100 + }, + "https://github.com/ty0x2333/ComfyUI-Dev-Utils": { + "stars": 43, + "last_update": "2024-06-03 15:06:13", + "author_account_age_days": 3718 + }, + "https://github.com/tzwm/comfyui-profiler": { + "stars": 43, + "last_update": "2024-07-06 14:03:08", + "author_account_age_days": 4784 + }, + "https://github.com/uarefans/ComfyUI-Fans": { + "stars": 12, + "last_update": "2024-05-22 20:34:07", + "author_account_age_days": 1287 + }, + "https://github.com/uetuluk/comfyui-webcam-node": { + "stars": 2, + "last_update": "2024-06-14 08:25:13", + "author_account_age_days": 2329 + }, + "https://github.com/unwdef/unwdef-nodes-comfyui": { + "stars": 1, + "last_update": "2024-06-27 23:14:09", + "author_account_age_days": 89 + }, + "https://github.com/vanche1212/ComfyUI-ZMG-Nodes": { + "stars": 3, + "last_update": "2024-06-25 04:48:19", + "author_account_age_days": 2973 + }, + "https://github.com/vanillacode314/SimpleWildcardsComfyUI": { + "stars": 3, + "last_update": "2024-06-28 10:57:45", + "author_account_age_days": 872 + }, + "https://github.com/veighnsche/comfyui_gr85": { + "stars": 1, + "last_update": "2024-06-27 15:00:08", + "author_account_age_days": 3115 + }, + "https://github.com/victorchall/comfyui_webcamcapture": { + "stars": 6, + "last_update": "2024-06-22 18:59:10", + "author_account_age_days": 3161 + }, + "https://github.com/vienteck/ComfyUI-Chat-GPT-Integration": { + "stars": 27, + "last_update": "2024-05-22 22:11:14", + "author_account_age_days": 3442 + }, + "https://github.com/violet-chen/comfyui-psd2png": { + "stars": 16, + "last_update": "2024-06-12 15:30:14", + "author_account_age_days": 1413 + }, + "https://github.com/viperyl/ComfyUI-BiRefNet": { + "stars": 162, + "last_update": "2024-06-20 15:25:49", + "author_account_age_days": 2048 + }, + "https://github.com/viperyl/ComfyUI-RGT": { + "stars": 5, + "last_update": "2024-06-20 15:33:50", + "author_account_age_days": 2048 + }, + "https://github.com/vivax3794/ComfyUI-Sub-Nodes": { + "stars": 78, + "last_update": "2024-07-08 13:59:24", + "author_account_age_days": 1854 + }, + "https://github.com/vivax3794/ComfyUI-Vivax-Nodes": { + "stars": 3, + "last_update": "2024-07-07 21:44:01", + "author_account_age_days": 1854 + }, + "https://github.com/vsevolod-oparin/comfyui-kandinsky22": { + "stars": 8, + "last_update": "2024-05-23 00:14:03", + "author_account_age_days": 4999 + }, + "https://github.com/wTechArtist/ComfyUI-CustomNodes": { + "stars": 0, + "last_update": "2024-07-08 13:59:30", + "author_account_age_days": 1376 + }, + "https://github.com/wallish77/wlsh_nodes": { + "stars": 84, + "last_update": "2024-06-19 12:01:29", + "author_account_age_days": 2235 + }, + "https://github.com/wandbrandon/comfyui-pixel": { + "stars": 4, + "last_update": "2024-06-14 07:07:09", + "author_account_age_days": 3399 + }, + "https://github.com/web3nomad/ComfyUI_Invisible_Watermark": { + "stars": 1, + "last_update": "2024-05-23 01:16:54", + "author_account_age_days": 983 + }, + "https://github.com/wei30172/comfygen": { + "stars": 5, + "last_update": "2024-05-23 00:21:19", + "author_account_age_days": 1628 + }, + "https://github.com/whatbirdisthat/cyberdolphin": { + "stars": 14, + "last_update": "2024-05-23 03:43:08", + "author_account_age_days": 5502 + }, + "https://github.com/whmc76/ComfyUI-Openpose-Editor-Plus": { + "stars": 30, + "last_update": "2024-06-20 13:52:34", + "author_account_age_days": 467 + }, + "https://github.com/wmatson/easy-comfy-nodes": { + "stars": 13, + "last_update": "2024-07-08 22:05:26", + "author_account_age_days": 4133 + }, + "https://github.com/wolfden/ComfyUi_PromptStylers": { + "stars": 65, + "last_update": "2024-05-22 18:17:46", + "author_account_age_days": 5736 + }, + "https://github.com/wolfden/ComfyUi_String_Function_Tree": { + "stars": 8, + "last_update": "2024-05-22 18:29:16", + "author_account_age_days": 5736 + }, + "https://github.com/wujm424606/ComfyUi-Ollama-YN": { + "stars": 18, + "last_update": "2024-06-26 05:50:44", + "author_account_age_days": 2278 + }, + "https://github.com/wutipong/ComfyUI-TextUtils": { + "stars": 1, + "last_update": "2024-06-14 09:34:31", + "author_account_age_days": 4200 + }, + "https://github.com/wwwins/ComfyUI-Simple-Aspect-Ratio": { + "stars": 1, + "last_update": "2024-05-22 22:22:25", + "author_account_age_days": 5065 + }, + "https://github.com/xXAdonesXx/NodeGPT": { + "stars": 326, + "last_update": "2024-06-20 11:41:30", + "author_account_age_days": 1494 + }, + "https://github.com/xiaoxiaodesha/hd_node": { + "stars": 7, + "last_update": "2024-06-11 02:36:48", + "author_account_age_days": 2890 + }, + "https://github.com/xliry/ComfyUI_SendDiscord": { + "stars": 0, + "last_update": "2024-05-23 02:21:38", + "author_account_age_days": 1289 + }, + "https://github.com/xuhongming251/ComfyUI-GPEN": { + "stars": 2, + "last_update": "2024-06-15 14:33:37", + "author_account_age_days": 4121 + }, + "https://github.com/xuhongming251/ComfyUI-MuseTalkUtils": { + "stars": 12, + "last_update": "2024-06-15 14:32:32", + "author_account_age_days": 4121 + }, + "https://github.com/yffyhk/comfyui_auto_danbooru": { + "stars": 1, + "last_update": "2024-05-22 23:23:03", + "author_account_age_days": 3737 + }, + "https://github.com/yiwangsimple/ComfyUI_GroqChat": { + "stars": 20, + "last_update": "2024-07-07 04:16:08", + "author_account_age_days": 567 + }, + "https://github.com/yolain/ComfyUI-Easy-Use": { + "stars": 552, + "last_update": "2024-07-08 09:25:13", + "author_account_age_days": 1356 + }, + "https://github.com/yolanother/DTAIComfyImageSubmit": { + "stars": 1, + "last_update": "2024-05-22 18:14:56", + "author_account_age_days": 4879 + }, + "https://github.com/yolanother/DTAIComfyLoaders": { + "stars": 1, + "last_update": "2024-05-22 18:14:44", + "author_account_age_days": 4879 + }, + "https://github.com/yolanother/DTAIComfyPromptAgent": { + "stars": 5, + "last_update": "2024-05-22 18:14:18", + "author_account_age_days": 4879 + }, + "https://github.com/yolanother/DTAIComfyQRCodes": { + "stars": 2, + "last_update": "2024-05-22 18:15:09", + "author_account_age_days": 4879 + }, + "https://github.com/yolanother/DTAIComfyVariables": { + "stars": 8, + "last_update": "2024-05-22 18:15:21", + "author_account_age_days": 4879 + }, + "https://github.com/yolanother/DTAIImageToTextNode": { + "stars": 15, + "last_update": "2024-05-22 18:14:31", + "author_account_age_days": 4879 + }, + "https://github.com/youyegit/tdxh_node_comfyui": { + "stars": 2, + "last_update": "2024-05-23 17:55:42", + "author_account_age_days": 444 + }, + "https://github.com/yuvraj108c/ComfyUI-Depth-Anything-Tensorrt": { + "stars": 67, + "last_update": "2024-07-02 08:09:45", + "author_account_age_days": 2168 + }, + "https://github.com/yuvraj108c/ComfyUI-PiperTTS": { + "stars": 26, + "last_update": "2024-05-22 23:17:27", + "author_account_age_days": 2168 + }, + "https://github.com/yuvraj108c/ComfyUI-Pronodes": { + "stars": 1, + "last_update": "2024-05-22 23:16:51", + "author_account_age_days": 2168 + }, + "https://github.com/yuvraj108c/ComfyUI-Upscaler-Tensorrt": { + "stars": 42, + "last_update": "2024-05-31 05:50:59", + "author_account_age_days": 2168 + }, + "https://github.com/yuvraj108c/ComfyUI-Vsgan": { + "stars": 2, + "last_update": "2024-05-22 23:17:02", + "author_account_age_days": 2168 + }, + "https://github.com/yuvraj108c/ComfyUI-Whisper": { + "stars": 57, + "last_update": "2024-05-31 05:59:22", + "author_account_age_days": 2168 + }, + "https://github.com/yuvraj108c/ComfyUI-YoloNasPose-Tensorrt": { + "stars": 5, + "last_update": "2024-06-28 15:59:14", + "author_account_age_days": 2168 + }, + "https://github.com/za-wa-n-go/ComfyUI_Zwng_Nodes": { + "stars": 3, + "last_update": "2024-07-02 14:57:01", + "author_account_age_days": 603 + }, + "https://github.com/zcfrank1st/Comfyui-Toolbox": { + "stars": 4, + "last_update": "2024-05-22 22:08:07", + "author_account_age_days": 4430 + }, + "https://github.com/zcfrank1st/Comfyui-Yolov8": { + "stars": 17, + "last_update": "2024-06-14 07:08:40", + "author_account_age_days": 4430 + }, + "https://github.com/zcfrank1st/comfyui_visual_anagrams": { + "stars": 5, + "last_update": "2024-06-14 07:07:27", + "author_account_age_days": 4430 + }, + "https://github.com/zer0TF/cute-comfy": { + "stars": 29, + "last_update": "2024-05-22 21:18:53", + "author_account_age_days": 2685 + }, + "https://github.com/zeroxoxo/ComfyUI-Fast-Style-Transfer": { + "stars": 55, + "last_update": "2024-06-30 14:31:09", + "author_account_age_days": 2458 + }, + "https://github.com/zfkun/ComfyUI_zfkun": { + "stars": 14, + "last_update": "2024-05-27 11:21:51", + "author_account_age_days": 4878 + }, + "https://github.com/zhangp365/ComfyUI-utils-nodes": { + "stars": 6, + "last_update": "2024-07-09 09:02:11", + "author_account_age_days": 306 + }, + "https://github.com/zhongpei/ComfyUI-InstructIR": { + "stars": 60, + "last_update": "2024-05-22 23:19:43", + "author_account_age_days": 3474 + }, + "https://github.com/zhongpei/Comfyui_image2prompt": { + "stars": 245, + "last_update": "2024-05-22 23:19:30", + "author_account_age_days": 3474 + }, + "https://github.com/zhuanqianfish/ComfyUI-EasyNode": { + "stars": 59, + "last_update": "2024-06-14 07:10:18", + "author_account_age_days": 4250 + }, + "https://github.com/zhulu111/ComfyUI_Bxb": { + "stars": 89, + "last_update": "2024-07-08 23:57:50", + "author_account_age_days": 54 + }, + "https://github.com/zohac/ComfyUI_ZC_DrawShape": { + "stars": 3, + "last_update": "2024-06-25 15:05:28", + "author_account_age_days": 2677 + }, + "https://github.com/zombieyang/sd-ppp": { + "stars": 20, + "last_update": "2024-07-08 01:25:47", + "author_account_age_days": 3933 + } +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/glob/cm_global.py b/custom_nodes/ComfyUI-Manager/glob/cm_global.py new file mode 100644 index 000000000..4041bcb6d --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/glob/cm_global.py @@ -0,0 +1,112 @@ +import traceback + +# +# Global Var +# +# Usage: +# import cm_global +# cm_global.variables['comfyui.revision'] = 1832 +# print(f"log mode: {cm_global.variables['logger.enabled']}") +# +variables = {} + + +# +# Global API +# +# Usage: +# [register API] +# import cm_global +# +# def api_hello(msg): +# print(f"hello: {msg}") +# return msg +# +# cm_global.register_api('hello', api_hello) +# +# [use API] +# import cm_global +# +# test = cm_global.try_call(api='hello', msg='an example') +# print(f"'{test}' is returned") +# + +APIs = {} + + +def register_api(k, f): + global APIs + APIs[k] = f + + +def try_call(**kwargs): + if 'api' in kwargs: + api_name = kwargs['api'] + try: + api = APIs.get(api_name) + if api is not None: + del kwargs['api'] + return api(**kwargs) + else: + print(f"WARN: The '{kwargs['api']}' API has not been registered.") + except Exception as e: + print(f"ERROR: An exception occurred while calling the '{api_name}' API.") + raise e + else: + return None + + +# +# Extension Info +# +# Usage: +# import cm_global +# +# cm_global.extension_infos['my_extension'] = {'version': [0, 1], 'name': 'me', 'description': 'example extension', } +# +extension_infos = {} + +on_extension_registered_handlers = {} + + +def register_extension(extension_name, v): + global extension_infos + global on_extension_registered_handlers + extension_infos[extension_name] = v + + if extension_name in on_extension_registered_handlers: + for k, f in on_extension_registered_handlers[extension_name]: + try: + f(extension_name, v) + except Exception: + print(f"[ERROR] '{k}' on_extension_registered_handlers") + traceback.print_exc() + + del on_extension_registered_handlers[extension_name] + + +def add_on_extension_registered(k, extension_name, f): + global on_extension_registered_handlers + if extension_name in extension_infos: + try: + v = extension_infos[extension_name] + f(extension_name, v) + except Exception: + print(f"[ERROR] '{k}' on_extension_registered_handler") + traceback.print_exc() + else: + if extension_name not in on_extension_registered_handlers: + on_extension_registered_handlers[extension_name] = [] + + on_extension_registered_handlers[extension_name].append((k, f)) + + +def add_on_revision_detected(k, f): + if 'comfyui.revision' in variables: + try: + f(variables['comfyui.revision']) + except Exception: + print(f"[ERROR] '{k}' on_revision_detected_handler") + traceback.print_exc() + else: + variables['cm.on_revision_detected_handler'].append((k, f)) diff --git a/custom_nodes/ComfyUI-Manager/glob/manager_core.py b/custom_nodes/ComfyUI-Manager/glob/manager_core.py new file mode 100644 index 000000000..d9db77827 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/glob/manager_core.py @@ -0,0 +1,1217 @@ +import os +import sys +import subprocess +import re +import shutil +import configparser +import platform +from datetime import datetime +import git +from git.remote import RemoteProgress +from urllib.parse import urlparse +from tqdm.auto import tqdm +import aiohttp +import threading +import json +import time +import yaml +import zipfile + +glob_path = os.path.join(os.path.dirname(__file__)) # ComfyUI-Manager/glob +sys.path.append(glob_path) + +import cm_global +from manager_util import * + +version = [2, 46, 2] +version_str = f"V{version[0]}.{version[1]}" + (f'.{version[2]}' if len(version) > 2 else '') + + +comfyui_manager_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +custom_nodes_path = os.path.abspath(os.path.join(comfyui_manager_path, '..')) + +comfy_path = os.environ.get('COMFYUI_PATH') +if comfy_path is None: + comfy_path = os.path.abspath(os.path.join(custom_nodes_path, '..')) + +channel_list_path = os.path.join(comfyui_manager_path, 'channels.list') +config_path = os.path.join(comfyui_manager_path, "config.ini") +startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts") +git_script_path = os.path.join(comfyui_manager_path, "git_helper.py") +cache_dir = os.path.join(comfyui_manager_path, '.cache') +cached_config = None +js_path = None + +comfy_ui_required_revision = 1930 +comfy_ui_required_commit_datetime = datetime(2024, 1, 24, 0, 0, 0) + +comfy_ui_revision = "Unknown" +comfy_ui_commit_datetime = datetime(1900, 1, 1, 0, 0, 0) + + +cache_lock = threading.Lock() + + +channel_dict = None +channel_list = None +pip_map = None + + +def remap_pip_package(pkg): + if pkg in cm_global.pip_overrides: + res = cm_global.pip_overrides[pkg] + print(f"[ComfyUI-Manager] '{pkg}' is remapped to '{res}'") + return res + else: + return pkg + + +def get_installed_packages(): + global pip_map + + if pip_map is None: + try: + result = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], universal_newlines=True) + + pip_map = {} + for line in result.split('\n'): + x = line.strip() + if x: + y = line.split() + if y[0] == 'Package' or y[0].startswith('-'): + continue + + pip_map[y[0]] = y[1] + except subprocess.CalledProcessError as e: + print(f"[ComfyUI-Manager] Failed to retrieve the information of installed pip packages.") + return set() + + return pip_map + + +def clear_pip_cache(): + global pip_map + pip_map = None + + +def is_blacklisted(name): + name = name.strip() + + pattern = r'([^<>!=]+)([<>!=]=?)(.*)' + match = re.search(pattern, name) + + if match: + name = match.group(1) + + if name in cm_global.pip_downgrade_blacklist: + pips = get_installed_packages() + + if match is None: + if name in pips: + return True + elif match.group(2) in ['<=', '==', '<']: + if name in pips: + if StrictVersion(pips[name]) >= StrictVersion(match.group(3)): + return True + + return False + + +def is_installed(name): + name = name.strip() + + if name.startswith('#'): + return True + + pattern = r'([^<>!=]+)([<>!=]=?)(.*)' + match = re.search(pattern, name) + + if match: + name = match.group(1) + + if name in cm_global.pip_downgrade_blacklist: + pips = get_installed_packages() + + if match is None: + if name in pips: + return True + elif match.group(2) in ['<=', '==', '<']: + if name in pips: + if StrictVersion(pips[name]) >= StrictVersion(match.group(3)): + print(f"[ComfyUI-Manager] skip black listed pip installation: '{name}'") + return True + + return name.lower() in get_installed_packages() + + +def get_channel_dict(): + global channel_dict + + if channel_dict is None: + channel_dict = {} + + if not os.path.exists(channel_list_path): + shutil.copy(channel_list_path+'.template', channel_list_path) + + with open(os.path.join(comfyui_manager_path, 'channels.list'), 'r') as file: + channels = file.read() + for x in channels.split('\n'): + channel_info = x.split("::") + if len(channel_info) == 2: + channel_dict[channel_info[0]] = channel_info[1] + + return channel_dict + + +def get_channel_list(): + global channel_list + + if channel_list is None: + channel_list = [] + for k, v in get_channel_dict().items(): + channel_list.append(f"{k}::{v}") + + return channel_list + + +class ManagerFuncs: + def __init__(self): + pass + + def get_current_preview_method(self): + return "none" + + def run_script(self, cmd, cwd='.'): + if len(cmd) > 0 and cmd[0].startswith("#"): + print(f"[ComfyUI-Manager] Unexpected behavior: `{cmd}`") + return 0 + + new_env = os.environ.copy() + new_env["COMFYUI_PATH"] = comfy_path + subprocess.check_call(cmd, cwd=cwd, env=new_env) + + return 0 + + +manager_funcs = ManagerFuncs() + + +def write_config(): + config = configparser.ConfigParser() + config['default'] = { + 'preview_method': manager_funcs.get_current_preview_method(), + 'badge_mode': get_config()['badge_mode'], + 'git_exe': get_config()['git_exe'], + 'channel_url': get_config()['channel_url'], + 'share_option': get_config()['share_option'], + 'bypass_ssl': get_config()['bypass_ssl'], + "file_logging": get_config()['file_logging'], + 'default_ui': get_config()['default_ui'], + 'component_policy': get_config()['component_policy'], + 'double_click_policy': get_config()['double_click_policy'], + 'windows_selector_event_loop_policy': get_config()['windows_selector_event_loop_policy'], + 'model_download_by_agent': get_config()['model_download_by_agent'], + 'downgrade_blacklist': get_config()['downgrade_blacklist'], + 'security_level': get_config()['security_level'], + } + with open(config_path, 'w') as configfile: + config.write(configfile) + + +def read_config(): + try: + config = configparser.ConfigParser() + config.read(config_path) + default_conf = config['default'] + + # policy migration: disable_unsecure_features -> security_level + if 'disable_unsecure_features' in default_conf: + if default_conf['disable_unsecure_features'].lower() == 'true': + security_level = 'strong' + else: + security_level = 'normal' + else: + security_level = default_conf['security_level'] if 'security_level' in default_conf else 'normal' + + return { + 'preview_method': default_conf['preview_method'] if 'preview_method' in default_conf else manager_funcs.get_current_preview_method(), + 'badge_mode': default_conf['badge_mode'] if 'badge_mode' in default_conf else 'none', + 'git_exe': default_conf['git_exe'] if 'git_exe' in default_conf else '', + 'channel_url': default_conf['channel_url'] if 'channel_url' in default_conf else 'https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main', + 'share_option': default_conf['share_option'] if 'share_option' in default_conf else 'all', + 'bypass_ssl': default_conf['bypass_ssl'].lower() == 'true' if 'bypass_ssl' in default_conf else False, + 'file_logging': default_conf['file_logging'].lower() == 'true' if 'file_logging' in default_conf else True, + 'default_ui': default_conf['default_ui'] if 'default_ui' in default_conf else 'none', + 'component_policy': default_conf['component_policy'] if 'component_policy' in default_conf else 'workflow', + 'double_click_policy': default_conf['double_click_policy'] if 'double_click_policy' in default_conf else 'copy-all', + 'windows_selector_event_loop_policy': default_conf['windows_selector_event_loop_policy'].lower() == 'true' if 'windows_selector_event_loop_policy' in default_conf else False, + 'model_download_by_agent': default_conf['model_download_by_agent'].lower() == 'true' if 'model_download_by_agent' in default_conf else False, + 'downgrade_blacklist': default_conf['downgrade_blacklist'] if 'downgrade_blacklist' in default_conf else '', + 'security_level': security_level + } + + except Exception: + return { + 'preview_method': manager_funcs.get_current_preview_method(), + 'badge_mode': 'none', + 'git_exe': '', + 'channel_url': 'https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main', + 'share_option': 'all', + 'bypass_ssl': False, + 'file_logging': True, + 'default_ui': 'none', + 'component_policy': 'workflow', + 'double_click_policy': 'copy-all', + 'windows_selector_event_loop_policy': False, + 'model_download_by_agent': False, + 'downgrade_blacklist': '', + 'security_level': 'normal', + } + + +def get_config(): + global cached_config + + if cached_config is None: + cached_config = read_config() + + return cached_config + + +def switch_to_default_branch(repo): + show_result = repo.git.remote("show", "origin") + matches = re.search(r"\s*HEAD branch:\s*(.*)", show_result) + if matches: + default_branch = matches.group(1) + repo.git.checkout(default_branch) + + +def try_install_script(url, repo_path, install_cmd, instant_execution=False): + if not instant_execution and ((len(install_cmd) > 0 and install_cmd[0].startswith('#')) or (platform.system() == "Windows" and comfy_ui_commit_datetime.date() >= comfy_ui_required_commit_datetime.date())): + if not os.path.exists(startup_script_path): + os.makedirs(startup_script_path) + + script_path = os.path.join(startup_script_path, "install-scripts.txt") + with open(script_path, "a") as file: + obj = [repo_path] + install_cmd + file.write(f"{obj}\n") + + return True + else: + if len(install_cmd) == 5 and install_cmd[2:4] == ['pip', 'install']: + if is_blacklisted(install_cmd[4]): + print(f"[ComfyUI-Manager] skip black listed pip installation: '{install_cmd[4]}'") + return True + + print(f"\n## ComfyUI-Manager: EXECUTE => {install_cmd}") + code = manager_funcs.run_script(install_cmd, cwd=repo_path) + + if platform.system() != "Windows": + try: + if comfy_ui_commit_datetime.date() < comfy_ui_required_commit_datetime.date(): + print("\n\n###################################################################") + print(f"[WARN] ComfyUI-Manager: Your ComfyUI version ({comfy_ui_revision})[{comfy_ui_commit_datetime.date()}] is too old. Please update to the latest version.") + print(f"[WARN] The extension installation feature may not work properly in the current installed ComfyUI version on Windows environment.") + print("###################################################################\n\n") + except: + pass + + if code != 0: + if url is None: + url = os.path.dirname(repo_path) + print(f"install script failed: {url}") + return False + + +# use subprocess to avoid file system lock by git (Windows) +def __win_check_git_update(path, do_fetch=False, do_update=False): + if do_fetch: + command = [sys.executable, git_script_path, "--fetch", path] + elif do_update: + command = [sys.executable, git_script_path, "--pull", path] + else: + command = [sys.executable, git_script_path, "--check", path] + + new_env = os.environ.copy() + new_env["COMFYUI_PATH"] = comfy_path + process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=custom_nodes_path) + output, _ = process.communicate() + output = output.decode('utf-8').strip() + + if 'detected dubious' in output: + # fix and try again + safedir_path = path.replace('\\', '/') + try: + print(f"[ComfyUI-Manager] Try fixing 'dubious repository' error on '{safedir_path}' repo") + process = subprocess.Popen(['git', 'config', '--global', '--add', 'safe.directory', safedir_path], env=new_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, _ = process.communicate() + + process = subprocess.Popen(command, env=new_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, _ = process.communicate() + output = output.decode('utf-8').strip() + except Exception: + print(f'[ComfyUI-Manager] failed to fixing') + + if 'detected dubious' in output: + print(f'\n[ComfyUI-Manager] Failed to fixing repository setup. Please execute this command on cmd: \n' + f'-----------------------------------------------------------------------------------------\n' + f'git config --global --add safe.directory "{safedir_path}"\n' + f'-----------------------------------------------------------------------------------------\n') + + if do_update: + if "CUSTOM NODE PULL: Success" in output: + process.wait() + print(f"\rUpdated: {path}") + return True, True # updated + elif "CUSTOM NODE PULL: None" in output: + process.wait() + return False, True # there is no update + else: + print(f"\rUpdate error: {path}") + process.wait() + return False, False # update failed + else: + if "CUSTOM NODE CHECK: True" in output: + process.wait() + return True, True + elif "CUSTOM NODE CHECK: False" in output: + process.wait() + return False, True + else: + print(f"\rFetch error: {path}") + print(f"\n{output}\n") + process.wait() + return False, True + + +def __win_check_git_pull(path): + new_env = os.environ.copy() + new_env["COMFYUI_PATH"] = comfy_path + command = [sys.executable, git_script_path, "--pull", path] + process = subprocess.Popen(command, env=new_env, cwd=custom_nodes_path) + process.wait() + + +def execute_install_script(url, repo_path, lazy_mode=False, instant_execution=False): + install_script_path = os.path.join(repo_path, "install.py") + requirements_path = os.path.join(repo_path, "requirements.txt") + + if lazy_mode: + install_cmd = ["#LAZY-INSTALL-SCRIPT", sys.executable] + try_install_script(url, repo_path, install_cmd) + else: + if os.path.exists(requirements_path): + print("Install: pip packages") + with open(requirements_path, "r") as requirements_file: + for line in requirements_file: + package_name = remap_pip_package(line.strip()) + if package_name and not package_name.startswith('#'): + install_cmd = [sys.executable, "-m", "pip", "install", package_name] + if package_name.strip() != "" and not package_name.startswith('#'): + try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution) + + if os.path.exists(install_script_path): + print(f"Install: install script") + install_cmd = [sys.executable, "install.py"] + try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution) + + return True + + +def git_repo_has_updates(path, do_fetch=False, do_update=False): + if do_fetch: + print(f"\x1b[2K\rFetching: {path}", end='') + elif do_update: + print(f"\x1b[2K\rUpdating: {path}", end='') + + # Check if the path is a git repository + if not os.path.exists(os.path.join(path, '.git')): + raise ValueError('Not a git repository') + + if platform.system() == "Windows": + updated, success = __win_check_git_update(path, do_fetch, do_update) + if updated and success: + execute_install_script(None, path, lazy_mode=True) + return updated, success + else: + # Fetch the latest commits from the remote repository + repo = git.Repo(path) + + current_branch = repo.active_branch + branch_name = current_branch.name + + remote_name = 'origin' + remote = repo.remote(name=remote_name) + + # Get the current commit hash + commit_hash = repo.head.commit.hexsha + + if do_fetch or do_update: + remote.fetch() + + if do_update: + if repo.head.is_detached: + switch_to_default_branch(repo) + + remote_commit_hash = repo.refs[f'{remote_name}/{branch_name}'].object.hexsha + + if commit_hash == remote_commit_hash: + repo.close() + return False, True + + try: + remote.pull() + repo.git.submodule('update', '--init', '--recursive') + new_commit_hash = repo.head.commit.hexsha + + if commit_hash != new_commit_hash: + execute_install_script(None, path) + print(f"\x1b[2K\rUpdated: {path}") + return True, True + else: + return False, False + + except Exception as e: + print(f"\nUpdating failed: {path}\n{e}", file=sys.stderr) + return False, False + + if repo.head.is_detached: + repo.close() + return True, True + + # Get commit hash of the remote branch + current_branch = repo.active_branch + branch_name = current_branch.name + + remote_commit_hash = repo.refs[f'{remote_name}/{branch_name}'].object.hexsha + + # Compare the commit hashes to determine if the local repository is behind the remote repository + if commit_hash != remote_commit_hash: + # Get the commit dates + commit_date = repo.head.commit.committed_datetime + remote_commit_date = repo.refs[f'{remote_name}/{branch_name}'].object.committed_datetime + + # Compare the commit dates to determine if the local repository is behind the remote repository + if commit_date < remote_commit_date: + repo.close() + return True, True + + repo.close() + + return False, True + + +class GitProgress(RemoteProgress): + def __init__(self): + super().__init__() + self.pbar = tqdm() + + def update(self, op_code, cur_count, max_count=None, message=''): + self.pbar.total = max_count + self.pbar.n = cur_count + self.pbar.pos = 0 + self.pbar.refresh() + + +def is_valid_url(url): + try: + # Check for HTTP/HTTPS URL format + result = urlparse(url) + if all([result.scheme, result.netloc]): + return True + finally: + # Check for SSH git URL format + pattern = re.compile(r"^(.+@|ssh:\/\/).+:.+$") + if pattern.match(url): + return True + return False + + +def gitclone_install(files, instant_execution=False, msg_prefix=''): + print(f"{msg_prefix}Install: {files}") + for url in files: + if not is_valid_url(url): + print(f"Invalid git url: '{url}'") + return False + + if url.endswith("/"): + url = url[:-1] + try: + print(f"Download: git clone '{url}'") + repo_name = os.path.splitext(os.path.basename(url))[0] + repo_path = os.path.join(custom_nodes_path, repo_name) + + # Clone the repository from the remote URL + if not instant_execution and platform.system() == 'Windows': + res = manager_funcs.run_script([sys.executable, git_script_path, "--clone", custom_nodes_path, url], cwd=custom_nodes_path) + if res != 0: + return False + else: + repo = git.Repo.clone_from(url, repo_path, recursive=True, progress=GitProgress()) + repo.git.clear_cache() + repo.close() + + if not execute_install_script(url, repo_path, instant_execution=instant_execution): + return False + + except Exception as e: + print(f"Install(git-clone) error: {url} / {e}", file=sys.stderr) + return False + + print("Installation was successful.") + return True + + +def git_pull(path): + # Check if the path is a git repository + if not os.path.exists(os.path.join(path, '.git')): + raise ValueError('Not a git repository') + + # Pull the latest changes from the remote repository + if platform.system() == "Windows": + return __win_check_git_pull(path) + else: + repo = git.Repo(path) + + if repo.is_dirty(): + repo.git.stash() + + if repo.head.is_detached: + switch_to_default_branch(repo) + + current_branch = repo.active_branch + remote_name = current_branch.tracking_branch().remote_name + remote = repo.remote(name=remote_name) + + remote.pull() + repo.git.submodule('update', '--init', '--recursive') + + repo.close() + + return True + + +async def get_data(uri, silent=False): + if not silent: + print(f"FETCH DATA from: {uri}", end="") + + if uri.startswith("http"): + async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session: + async with session.get(uri) as resp: + json_text = await resp.text() + else: + with cache_lock: + with open(uri, "r", encoding="utf-8") as f: + json_text = f.read() + + json_obj = json.loads(json_text) + if not silent: + print(f" [DONE]") + return json_obj + + +def simple_hash(input_string): + hash_value = 0 + for char in input_string: + hash_value = (hash_value * 31 + ord(char)) % (2**32) + + return hash_value + + +def is_file_created_within_one_day(file_path): + if not os.path.exists(file_path): + return False + + file_creation_time = os.path.getctime(file_path) + current_time = datetime.now().timestamp() + time_difference = current_time - file_creation_time + + return time_difference <= 86400 + + +async def get_data_by_mode(mode, filename, channel_url=None): + if channel_url in get_channel_dict(): + channel_url = get_channel_dict()[channel_url] + + try: + if mode == "local": + uri = os.path.join(comfyui_manager_path, filename) + json_obj = await get_data(uri) + else: + if channel_url is None: + uri = get_config()['channel_url'] + '/' + filename + else: + uri = channel_url + '/' + filename + + cache_uri = str(simple_hash(uri))+'_'+filename + cache_uri = os.path.join(cache_dir, cache_uri) + + if mode == "cache": + if is_file_created_within_one_day(cache_uri): + json_obj = await get_data(cache_uri) + else: + json_obj = await get_data(uri) + with cache_lock: + with open(cache_uri, "w", encoding='utf-8') as file: + json.dump(json_obj, file, indent=4, sort_keys=True) + else: + json_obj = await get_data(uri) + with cache_lock: + with open(cache_uri, "w", encoding='utf-8') as file: + json.dump(json_obj, file, indent=4, sort_keys=True) + except Exception as e: + print(f"[ComfyUI-Manager] Due to a network error, switching to local mode.\n=> {filename}\n=> {e}") + uri = os.path.join(comfyui_manager_path, filename) + json_obj = await get_data(uri) + + return json_obj + + +def gitclone_fix(files, instant_execution=False): + print(f"Try fixing: {files}") + for url in files: + if not is_valid_url(url): + print(f"Invalid git url: '{url}'") + return False + + if url.endswith("/"): + url = url[:-1] + try: + repo_name = os.path.splitext(os.path.basename(url))[0] + repo_path = os.path.join(custom_nodes_path, repo_name) + + if os.path.exists(repo_path+'.disabled'): + repo_path = repo_path+'.disabled' + + if not execute_install_script(url, repo_path, instant_execution=instant_execution): + return False + + except Exception as e: + print(f"Install(git-clone) error: {url} / {e}", file=sys.stderr) + return False + + print(f"Attempt to fixing '{files}' is done.") + return True + + +def pip_install(packages): + install_cmd = ['#FORCE', sys.executable, "-m", "pip", "install", '-U'] + packages + try_install_script('pip install via manager', '..', install_cmd) + + +def rmtree(path): + retry_count = 3 + + while True: + try: + retry_count -= 1 + + if platform.system() == "Windows": + manager_funcs.run_script(['attrib', '-R', path + '\\*', '/S']) + shutil.rmtree(path) + + return True + + except Exception as ex: + print(f"ex: {ex}") + time.sleep(3) + + if retry_count < 0: + raise ex + + print(f"Uninstall retry({retry_count})") + + +def gitclone_uninstall(files): + import os + + print(f"Uninstall: {files}") + for url in files: + if url.endswith("/"): + url = url[:-1] + try: + dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "") + dir_path = os.path.join(custom_nodes_path, dir_name) + + # safety check + if dir_path == '/' or dir_path[1:] == ":/" or dir_path == '': + print(f"Uninstall(git-clone) error: invalid path '{dir_path}' for '{url}'") + return False + + install_script_path = os.path.join(dir_path, "uninstall.py") + disable_script_path = os.path.join(dir_path, "disable.py") + if os.path.exists(install_script_path): + uninstall_cmd = [sys.executable, "uninstall.py"] + code = manager_funcs.run_script(uninstall_cmd, cwd=dir_path) + + if code != 0: + print(f"An error occurred during the execution of the uninstall.py script. Only the '{dir_path}' will be deleted.") + elif os.path.exists(disable_script_path): + disable_script = [sys.executable, "disable.py"] + code = manager_funcs.run_script(disable_script, cwd=dir_path) + if code != 0: + print(f"An error occurred during the execution of the disable.py script. Only the '{dir_path}' will be deleted.") + + if os.path.exists(dir_path): + rmtree(dir_path) + elif os.path.exists(dir_path + ".disabled"): + rmtree(dir_path + ".disabled") + except Exception as e: + print(f"Uninstall(git-clone) error: {url} / {e}", file=sys.stderr) + return False + + print("Uninstallation was successful.") + return True + + +def gitclone_set_active(files, is_disable): + import os + + if is_disable: + action_name = "Disable" + else: + action_name = "Enable" + + print(f"{action_name}: {files}") + for url in files: + if url.endswith("/"): + url = url[:-1] + try: + dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "") + dir_path = os.path.join(custom_nodes_path, dir_name) + + # safety check + if dir_path == '/' or dir_path[1:] == ":/" or dir_path == '': + print(f"{action_name}(git-clone) error: invalid path '{dir_path}' for '{url}'") + return False + + if is_disable: + current_path = dir_path + new_path = dir_path + ".disabled" + else: + current_path = dir_path + ".disabled" + new_path = dir_path + + os.rename(current_path, new_path) + + if is_disable: + if os.path.exists(os.path.join(new_path, "disable.py")): + disable_script = [sys.executable, "disable.py"] + try_install_script(url, new_path, disable_script) + else: + if os.path.exists(os.path.join(new_path, "enable.py")): + enable_script = [sys.executable, "enable.py"] + try_install_script(url, new_path, enable_script) + + except Exception as e: + print(f"{action_name}(git-clone) error: {url} / {e}", file=sys.stderr) + return False + + print(f"{action_name} was successful.") + return True + + +def gitclone_update(files, instant_execution=False, skip_script=False, msg_prefix=""): + import os + + print(f"{msg_prefix}Update: {files}") + for url in files: + if url.endswith("/"): + url = url[:-1] + try: + repo_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "") + repo_path = os.path.join(custom_nodes_path, repo_name) + + if os.path.exists(repo_path+'.disabled'): + repo_path = repo_path+'.disabled' + + git_pull(repo_path) + + if not skip_script: + if instant_execution: + if not execute_install_script(url, repo_path, lazy_mode=False, instant_execution=True): + return False + else: + if not execute_install_script(url, repo_path, lazy_mode=True): + return False + + except Exception as e: + print(f"Update(git-clone) error: {url} / {e}", file=sys.stderr) + return False + + if not skip_script: + print("Update was successful.") + return True + + +def update_path(repo_path, instant_execution=False): + if not os.path.exists(os.path.join(repo_path, '.git')): + return "fail" + + # version check + repo = git.Repo(repo_path) + + if repo.head.is_detached: + switch_to_default_branch(repo) + + current_branch = repo.active_branch + branch_name = current_branch.name + + if current_branch.tracking_branch() is None: + print(f"[ComfyUI-Manager] There is no tracking branch ({current_branch})") + remote_name = 'origin' + else: + remote_name = current_branch.tracking_branch().remote_name + remote = repo.remote(name=remote_name) + + try: + remote.fetch() + except Exception as e: + if 'detected dubious' in str(e): + print(f"[ComfyUI-Manager] Try fixing 'dubious repository' error on 'ComfyUI' repository") + safedir_path = comfy_path.replace('\\', '/') + subprocess.run(['git', 'config', '--global', '--add', 'safe.directory', safedir_path]) + try: + remote.fetch() + except Exception: + print(f"\n[ComfyUI-Manager] Failed to fixing repository setup. Please execute this command on cmd: \n" + f"-----------------------------------------------------------------------------------------\n" + f'git config --global --add safe.directory "{safedir_path}"\n' + f"-----------------------------------------------------------------------------------------\n") + + commit_hash = repo.head.commit.hexsha + remote_commit_hash = repo.refs[f'{remote_name}/{branch_name}'].object.hexsha + + if commit_hash != remote_commit_hash: + git_pull(repo_path) + execute_install_script("ComfyUI", repo_path, instant_execution=instant_execution) + return "updated" + else: + return "skipped" + + +def lookup_customnode_by_url(data, target): + for x in data['custom_nodes']: + if target in x['files']: + dir_name = os.path.splitext(os.path.basename(target))[0].replace(".git", "") + dir_path = os.path.join(custom_nodes_path, dir_name) + if os.path.exists(dir_path): + x['installed'] = 'True' + elif os.path.exists(dir_path + ".disabled"): + x['installed'] = 'Disabled' + return x + + return None + + +def simple_check_custom_node(url): + dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "") + dir_path = os.path.join(custom_nodes_path, dir_name) + if os.path.exists(dir_path): + return 'installed' + elif os.path.exists(dir_path+'.disabled'): + return 'disabled' + + return 'not-installed' + + +def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do_update=False): + item['installed'] = 'None' + + if item['install_type'] == 'git-clone' and len(item['files']) == 1: + url = item['files'][0] + + if url.endswith("/"): + url = url[:-1] + + dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "") + dir_path = os.path.join(custom_nodes_path, dir_name) + if os.path.exists(dir_path): + try: + item['installed'] = 'True' # default + + if cm_global.try_call(api="cm.is_import_failed_extension", name=dir_name): + item['installed'] = 'Fail' + + if do_update_check: + update_state, success = git_repo_has_updates(dir_path, do_fetch, do_update) + if (do_update_check or do_update) and update_state: + item['installed'] = 'Update' + elif do_update and not success: + item['installed'] = 'Fail' + except: + if cm_global.try_call(api="cm.is_import_failed_extension", name=dir_name): + item['installed'] = 'Fail' + else: + item['installed'] = 'True' + + elif os.path.exists(dir_path + ".disabled"): + item['installed'] = 'Disabled' + + else: + item['installed'] = 'False' + + elif item['install_type'] == 'copy' and len(item['files']) == 1: + dir_name = os.path.basename(item['files'][0]) + + if item['files'][0].endswith('.py'): + base_path = custom_nodes_path + elif 'js_path' in item: + base_path = os.path.join(js_path, item['js_path']) + else: + base_path = js_path + + file_path = os.path.join(base_path, dir_name) + if os.path.exists(file_path): + if cm_global.try_call(api="cm.is_import_failed_extension", name=dir_name): + item['installed'] = 'Fail' + else: + item['installed'] = 'True' + elif os.path.exists(file_path + ".disabled"): + item['installed'] = 'Disabled' + else: + item['installed'] = 'False' + + +def get_installed_pip_packages(): + # extract pip package infos + pips = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'], text=True).split('\n') + + res = {} + for x in pips: + if x.strip() == "": + continue + + if ' @ ' in x: + spec_url = x.split(' @ ') + res[spec_url[0]] = spec_url[1] + else: + res[x] = "" + + return res + + +def get_current_snapshot(): + # Get ComfyUI hash + repo_path = comfy_path + + if not os.path.exists(os.path.join(repo_path, '.git')): + print(f"ComfyUI update fail: The installed ComfyUI does not have a Git repository.") + return {} + + repo = git.Repo(repo_path) + comfyui_commit_hash = repo.head.commit.hexsha + + git_custom_nodes = {} + file_custom_nodes = [] + + # Get custom nodes hash + for path in os.listdir(custom_nodes_path): + fullpath = os.path.join(custom_nodes_path, path) + + if os.path.isdir(fullpath): + is_disabled = path.endswith(".disabled") + + try: + git_dir = os.path.join(fullpath, '.git') + + if not os.path.exists(git_dir): + continue + + repo = git.Repo(fullpath) + commit_hash = repo.head.commit.hexsha + url = repo.remotes.origin.url + git_custom_nodes[url] = { + 'hash': commit_hash, + 'disabled': is_disabled + } + + except: + print(f"Failed to extract snapshots for the custom node '{path}'.") + + elif path.endswith('.py'): + is_disabled = path.endswith(".py.disabled") + filename = os.path.basename(path) + item = { + 'filename': filename, + 'disabled': is_disabled + } + + file_custom_nodes.append(item) + + pip_packages = get_installed_pip_packages() + + return { + 'comfyui': comfyui_commit_hash, + 'git_custom_nodes': git_custom_nodes, + 'file_custom_nodes': file_custom_nodes, + 'pips': pip_packages, + } + + +def save_snapshot_with_postfix(postfix, path=None): + if path is None: + now = datetime.now() + + date_time_format = now.strftime("%Y-%m-%d_%H-%M-%S") + file_name = f"{date_time_format}_{postfix}" + + path = os.path.join(comfyui_manager_path, 'snapshots', f"{file_name}.json") + else: + file_name = path.replace('\\', '/').split('/')[-1] + file_name = file_name.split('.')[-2] + + snapshot = get_current_snapshot() + if path.endswith('.json'): + with open(path, "w") as json_file: + json.dump(snapshot, json_file, indent=4) + + return file_name + '.json' + + elif path.endswith('.yaml'): + with open(path, "w") as yaml_file: + snapshot = {'custom_nodes': snapshot} + yaml.dump(snapshot, yaml_file, allow_unicode=True) + + return path + + +async def extract_nodes_from_workflow(filepath, mode='local', channel_url='default'): + # prepare json data + workflow = None + if filepath.endswith('.json'): + with open(filepath, "r", encoding="UTF-8", errors="ignore") as json_file: + try: + workflow = json.load(json_file) + except: + print(f"Invalid workflow file: {filepath}") + exit(-1) + + elif filepath.endswith('.png'): + from PIL import Image + with Image.open(filepath) as img: + if 'workflow' not in img.info: + print(f"The specified .png file doesn't have a workflow: {filepath}") + exit(-1) + else: + try: + workflow = json.loads(img.info['workflow']) + except: + print(f"This is not a valid .png file containing a ComfyUI workflow: {filepath}") + exit(-1) + + if workflow is None: + print(f"Invalid workflow file: {filepath}") + exit(-1) + + # extract nodes + used_nodes = set() + + def extract_nodes(sub_workflow): + for x in sub_workflow['nodes']: + node_name = x.get('type') + + # skip virtual nodes + if node_name in ['Reroute', 'Note']: + continue + + if node_name is not None and not node_name.startswith('workflow/'): + used_nodes.add(node_name) + + if 'nodes' in workflow: + extract_nodes(workflow) + + if 'extra' in workflow: + if 'groupNodes' in workflow['extra']: + for x in workflow['extra']['groupNodes'].values(): + extract_nodes(x) + + # lookup dependent custom nodes + ext_map = await get_data_by_mode(mode, 'extension-node-map.json', channel_url) + + rext_map = {} + preemption_map = {} + patterns = [] + for k, v in ext_map.items(): + if k == 'https://github.com/comfyanonymous/ComfyUI': + for x in v[0]: + if x not in preemption_map: + preemption_map[x] = [] + + preemption_map[x] = k + continue + + for x in v[0]: + if x not in rext_map: + rext_map[x] = [] + + rext_map[x].append(k) + + if 'preemptions' in v[1]: + for x in v[1]['preemptions']: + if x not in preemption_map: + preemption_map[x] = [] + + preemption_map[x] = k + + if 'nodename_pattern' in v[1]: + patterns.append((v[1]['nodename_pattern'], k)) + + # identify used extensions + used_exts = set() + unknown_nodes = set() + + for node_name in used_nodes: + ext = preemption_map.get(node_name) + + if ext is None: + ext = rext_map.get(node_name) + if ext is not None: + ext = ext[0] + + if ext is None: + for pat_ext in patterns: + if re.search(pat_ext[0], node_name): + ext = pat_ext[1] + break + + if ext == 'https://github.com/comfyanonymous/ComfyUI': + pass + elif ext is not None: + if 'Fooocus' in ext: + print(f">> {node_name}") + + used_exts.add(ext) + else: + unknown_nodes.add(node_name) + + return used_exts, unknown_nodes + + +def unzip(model_path): + if not os.path.exists(model_path): + print(f"[ComfyUI-Manager] unzip: File not found: {model_path}") + return False + + base_dir = os.path.dirname(model_path) + filename = os.path.basename(model_path) + target_dir = os.path.join(base_dir, filename[:-4]) + + os.makedirs(target_dir, exist_ok=True) + + with zipfile.ZipFile(model_path, 'r') as zip_ref: + zip_ref.extractall(target_dir) + + # Check if there's only one directory inside the target directory + contents = os.listdir(target_dir) + if len(contents) == 1 and os.path.isdir(os.path.join(target_dir, contents[0])): + nested_dir = os.path.join(target_dir, contents[0]) + # Move each file and sub-directory in the nested directory up to the target directory + for item in os.listdir(nested_dir): + shutil.move(os.path.join(nested_dir, item), os.path.join(target_dir, item)) + # Remove the now empty nested directory + os.rmdir(nested_dir) + + os.remove(model_path) + return True + diff --git a/custom_nodes/ComfyUI-Manager/glob/manager_downloader.py b/custom_nodes/ComfyUI-Manager/glob/manager_downloader.py new file mode 100644 index 000000000..8a8c73c03 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/glob/manager_downloader.py @@ -0,0 +1,70 @@ +import os +from urllib.parse import urlparse + +aria2 = os.getenv('COMFYUI_MANAGER_ARIA2_SERVER') +HF_ENDPOINT = os.getenv('HF_ENDPOINT') + +if aria2 is not None: + secret = os.getenv('COMFYUI_MANAGER_ARIA2_SECRET') + url = urlparse(aria2) + port = url.port + host = url.scheme + '://' + url.hostname + import aria2p + + aria2 = aria2p.API(aria2p.Client(host=host, port=port, secret=secret)) + + +def download_url(model_url: str, model_dir: str, filename: str): + if aria2: + return aria2_download_url(model_url, model_dir, filename) + else: + from torchvision.datasets.utils import download_url as torchvision_download_url + + return torchvision_download_url(model_url, model_dir, filename) + + +def aria2_find_task(dir: str, filename: str): + target = os.path.join(dir, filename) + + downloads = aria2.get_downloads() + + for download in downloads: + for file in download.files: + if file.is_metadata: + continue + if str(file.path) == target: + return download + + +def aria2_download_url(model_url: str, model_dir: str, filename: str): + import manager_core as core + import tqdm + import time + + if model_dir.startswith(core.comfy_path): + model_dir = model_dir[len(core.comfy_path) :] + + if HF_ENDPOINT: + model_url = model_url.replace('https://huggingface.co', HF_ENDPOINT) + + download_dir = model_dir if model_dir.startswith('/') else os.path.join('/models', model_dir) + + download = aria2_find_task(download_dir, filename) + if download is None: + options = {'dir': download_dir, 'out': filename} + download = aria2.add(model_url, options)[0] + + if download.is_active: + with tqdm.tqdm( + total=download.total_length, + bar_format='{l_bar}{bar}{r_bar}', + desc=filename, + unit='B', + unit_scale=True, + ) as progress_bar: + while download.is_active: + if progress_bar.total == 0 and download.total_length != 0: + progress_bar.reset(download.total_length) + progress_bar.update(download.completed_length - progress_bar.n) + time.sleep(1) + download.update() diff --git a/custom_nodes/ComfyUI-Manager/glob/manager_server.py b/custom_nodes/ComfyUI-Manager/glob/manager_server.py new file mode 100644 index 000000000..f157fca79 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/glob/manager_server.py @@ -0,0 +1,1707 @@ +import mimetypes +import traceback + +import folder_paths +import locale +import subprocess # don't remove this +import concurrent +import nodes +import hashlib +import os +import sys +import threading +import re +import shutil +import git + +from server import PromptServer +import manager_core as core +import cm_global + +print(f"### Loading: ComfyUI-Manager ({core.version_str})") + +comfy_ui_hash = "-" + + +def handle_stream(stream, prefix): + stream.reconfigure(encoding=locale.getpreferredencoding(), errors='replace') + for msg in stream: + if prefix == '[!]' and ('it/s]' in msg or 's/it]' in msg) and ('%|' in msg or 'it [' in msg): + if msg.startswith('100%'): + print('\r' + msg, end="", file=sys.stderr), + else: + print('\r' + msg[:-1], end="", file=sys.stderr), + else: + if prefix == '[!]': + print(prefix, msg, end="", file=sys.stderr) + else: + print(prefix, msg, end="") + + +from comfy.cli_args import args +import latent_preview + + +is_local_mode = args.listen.startswith('127.') or args.listen.startswith('local.') + + +def is_allowed_security_level(level): + if level == 'high': + if is_local_mode: + return core.get_config()['security_level'].lower() in ['weak', 'normal'] + else: + return core.get_config()['security_level'].lower() == 'weak' + elif level == 'middle': + return core.get_config()['security_level'].lower() in ['weak', 'normal'] + else: + return True + + +async def get_risky_level(files): + json_data1 = await core.get_data_by_mode('local', 'custom-node-list.json') + json_data2 = await core.get_data_by_mode('cache', 'custom-node-list.json', channel_url='https://github.com/ltdrdata/ComfyUI-Manager/raw/main/custom-node-list.json') + + all_urls = set() + for x in json_data1['custom_nodes'] + json_data2['custom_nodes']: + all_urls.update(x['files']) + + for x in files: + if x not in all_urls: + return "high" + + return "middle" + + +class ManagerFuncsInComfyUI(core.ManagerFuncs): + def get_current_preview_method(self): + if args.preview_method == latent_preview.LatentPreviewMethod.Auto: + return "auto" + elif args.preview_method == latent_preview.LatentPreviewMethod.Latent2RGB: + return "latent2rgb" + elif args.preview_method == latent_preview.LatentPreviewMethod.TAESD: + return "taesd" + else: + return "none" + + def run_script(self, cmd, cwd='.'): + if len(cmd) > 0 and cmd[0].startswith("#"): + print(f"[ComfyUI-Manager] Unexpected behavior: `{cmd}`") + return 0 + + process = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=1) + + stdout_thread = threading.Thread(target=handle_stream, args=(process.stdout, "")) + stderr_thread = threading.Thread(target=handle_stream, args=(process.stderr, "[!]")) + + stdout_thread.start() + stderr_thread.start() + + stdout_thread.join() + stderr_thread.join() + + return process.wait() + + +core.manager_funcs = ManagerFuncsInComfyUI() + +sys.path.append('../..') + +from manager_downloader import download_url + +core.comfy_path = os.path.dirname(folder_paths.__file__) +core.js_path = os.path.join(core.comfy_path, "web", "extensions") + +local_db_model = os.path.join(core.comfyui_manager_path, "model-list.json") +local_db_alter = os.path.join(core.comfyui_manager_path, "alter-list.json") +local_db_custom_node_list = os.path.join(core.comfyui_manager_path, "custom-node-list.json") +local_db_extension_node_mappings = os.path.join(core.comfyui_manager_path, "extension-node-map.json") +components_path = os.path.join(core.comfyui_manager_path, 'components') + + +def set_preview_method(method): + if method == 'auto': + args.preview_method = latent_preview.LatentPreviewMethod.Auto + elif method == 'latent2rgb': + args.preview_method = latent_preview.LatentPreviewMethod.Latent2RGB + elif method == 'taesd': + args.preview_method = latent_preview.LatentPreviewMethod.TAESD + else: + args.preview_method = latent_preview.LatentPreviewMethod.NoPreviews + + core.get_config()['preview_method'] = args.preview_method + + +set_preview_method(core.get_config()['preview_method']) + + +def set_badge_mode(mode): + core.get_config()['badge_mode'] = mode + + +def set_default_ui_mode(mode): + core.get_config()['default_ui'] = mode + + +def set_component_policy(mode): + core.get_config()['component_policy'] = mode + + +def set_double_click_policy(mode): + core.get_config()['double_click_policy'] = mode + + +def print_comfyui_version(): + global comfy_ui_hash + + is_detached = False + try: + repo = git.Repo(os.path.dirname(folder_paths.__file__)) + core.comfy_ui_revision = len(list(repo.iter_commits('HEAD'))) + + comfy_ui_hash = repo.head.commit.hexsha + cm_global.variables['comfyui.revision'] = core.comfy_ui_revision + + core.comfy_ui_commit_datetime = repo.head.commit.committed_datetime + cm_global.variables['comfyui.commit_datetime'] = core.comfy_ui_commit_datetime + + is_detached = repo.head.is_detached + current_branch = repo.active_branch.name + + try: + if core.comfy_ui_commit_datetime.date() < core.comfy_ui_required_commit_datetime.date(): + print(f"\n\n## [WARN] ComfyUI-Manager: Your ComfyUI version ({core.comfy_ui_revision})[{core.comfy_ui_commit_datetime.date()}] is too old. Please update to the latest version. ##\n\n") + except: + pass + + # process on_revision_detected --> + if 'cm.on_revision_detected_handler' in cm_global.variables: + for k, f in cm_global.variables['cm.on_revision_detected_handler']: + try: + f(core.comfy_ui_revision) + except Exception: + print(f"[ERROR] '{k}' on_revision_detected_handler") + traceback.print_exc() + + del cm_global.variables['cm.on_revision_detected_handler'] + else: + print(f"[ComfyUI-Manager] Some features are restricted due to your ComfyUI being outdated.") + # <-- + + if current_branch == "master": + print(f"### ComfyUI Revision: {core.comfy_ui_revision} [{comfy_ui_hash[:8]}] | Released on '{core.comfy_ui_commit_datetime.date()}'") + else: + print(f"### ComfyUI Revision: {core.comfy_ui_revision} on '{current_branch}' [{comfy_ui_hash[:8]}] | Released on '{core.comfy_ui_commit_datetime.date()}'") + except: + if is_detached: + print(f"### ComfyUI Revision: {core.comfy_ui_revision} [{comfy_ui_hash[:8]}] *DETACHED | Released on '{core.comfy_ui_commit_datetime.date()}'") + else: + print("### ComfyUI Revision: UNKNOWN (The currently installed ComfyUI is not a Git repository)") + + +print_comfyui_version() + + +async def populate_github_stats(json_obj, json_obj_github): + if 'custom_nodes' in json_obj: + for i, node in enumerate(json_obj['custom_nodes']): + url = node['reference'] + if url in json_obj_github: + json_obj['custom_nodes'][i]['stars'] = json_obj_github[url]['stars'] + json_obj['custom_nodes'][i]['last_update'] = json_obj_github[url]['last_update'] + json_obj['custom_nodes'][i]['trust'] = json_obj_github[url]['author_account_age_days'] > 180 + else: + json_obj['custom_nodes'][i]['stars'] = -1 + json_obj['custom_nodes'][i]['last_update'] = -1 + json_obj['custom_nodes'][i]['trust'] = False + return json_obj + + +def setup_environment(): + git_exe = core.get_config()['git_exe'] + + if git_exe != '': + git.Git().update_environment(GIT_PYTHON_GIT_EXECUTABLE=git_exe) + + +setup_environment() + +# Expand Server api + +import server +from aiohttp import web +import aiohttp +import json +import zipfile +import urllib.request + + +def get_model_dir(data): + if data['save_path'] != 'default': + if '..' in data['save_path'] or data['save_path'].startswith('/'): + print(f"[WARN] '{data['save_path']}' is not allowed path. So it will be saved into 'models/etc'.") + base_model = "etc" + else: + if data['save_path'].startswith("custom_nodes"): + base_model = os.path.join(core.comfy_path, data['save_path']) + else: + base_model = os.path.join(folder_paths.models_dir, data['save_path']) + else: + model_type = data['type'] + if model_type == "checkpoints": + base_model = folder_paths.folder_names_and_paths["checkpoints"][0][0] + elif model_type == "unclip": + base_model = folder_paths.folder_names_and_paths["checkpoints"][0][0] + elif model_type == "VAE": + base_model = folder_paths.folder_names_and_paths["vae"][0][0] + elif model_type == "lora": + base_model = folder_paths.folder_names_and_paths["loras"][0][0] + elif model_type == "T2I-Adapter": + base_model = folder_paths.folder_names_and_paths["controlnet"][0][0] + elif model_type == "T2I-Style": + base_model = folder_paths.folder_names_and_paths["controlnet"][0][0] + elif model_type == "controlnet": + base_model = folder_paths.folder_names_and_paths["controlnet"][0][0] + elif model_type == "clip_vision": + base_model = folder_paths.folder_names_and_paths["clip_vision"][0][0] + elif model_type == "gligen": + base_model = folder_paths.folder_names_and_paths["gligen"][0][0] + elif model_type == "upscale": + base_model = folder_paths.folder_names_and_paths["upscale_models"][0][0] + elif model_type == "embeddings": + base_model = folder_paths.folder_names_and_paths["embeddings"][0][0] + else: + base_model = "etc" + + return base_model + + +def get_model_path(data): + base_model = get_model_dir(data) + return os.path.join(base_model, data['filename']) + + +def check_custom_nodes_installed(json_obj, do_fetch=False, do_update_check=True, do_update=False): + if do_fetch: + print("Start fetching...", end="") + elif do_update: + print("Start updating...", end="") + elif do_update_check: + print("Start update check...", end="") + + def process_custom_node(item): + core.check_a_custom_node_installed(item, do_fetch, do_update_check, do_update) + + with concurrent.futures.ThreadPoolExecutor(4) as executor: + for item in json_obj['custom_nodes']: + executor.submit(process_custom_node, item) + + if do_fetch: + print(f"\x1b[2K\rFetching done.") + elif do_update: + update_exists = any(item['installed'] == 'Update' for item in json_obj['custom_nodes']) + if update_exists: + print(f"\x1b[2K\rUpdate done.") + else: + print(f"\x1b[2K\rAll extensions are already up-to-date.") + elif do_update_check: + print(f"\x1b[2K\rUpdate check done.") + + +def nickname_filter(json_obj): + preemptions_map = {} + + for k, x in json_obj.items(): + if 'preemptions' in x[1]: + for y in x[1]['preemptions']: + preemptions_map[y] = k + elif k.endswith("/ComfyUI"): + for y in x[0]: + preemptions_map[y] = k + + updates = {} + for k, x in json_obj.items(): + removes = set() + for y in x[0]: + k2 = preemptions_map.get(y) + if k2 is not None and k != k2: + removes.add(y) + + if len(removes) > 0: + updates[k] = [y for y in x[0] if y not in removes] + + for k, v in updates.items(): + json_obj[k][0] = v + + return json_obj + + +@PromptServer.instance.routes.get("/customnode/getmappings") +async def fetch_customnode_mappings(request): + mode = request.rel_url.query["mode"] + + nickname_mode = False + if mode == "nickname": + mode = "local" + nickname_mode = True + + json_obj = await core.get_data_by_mode(mode, 'extension-node-map.json') + + if nickname_mode: + json_obj = nickname_filter(json_obj) + + all_nodes = set() + patterns = [] + for k, x in json_obj.items(): + all_nodes.update(set(x[0])) + + if 'nodename_pattern' in x[1]: + patterns.append((x[1]['nodename_pattern'], x[0])) + + missing_nodes = set(nodes.NODE_CLASS_MAPPINGS.keys()) - all_nodes + + for x in missing_nodes: + for pat, item in patterns: + if re.match(pat, x): + item.append(x) + + return web.json_response(json_obj, content_type='application/json') + + +@PromptServer.instance.routes.get("/customnode/fetch_updates") +async def fetch_updates(request): + try: + json_obj = await core.get_data_by_mode(request.rel_url.query["mode"], 'custom-node-list.json') + + check_custom_nodes_installed(json_obj, True) + + update_exists = any('custom_nodes' in json_obj and 'installed' in node and node['installed'] == 'Update' for node in + json_obj['custom_nodes']) + + if update_exists: + return web.Response(status=201) + + return web.Response(status=200) + except: + return web.Response(status=400) + + +@PromptServer.instance.routes.get("/customnode/update_all") +async def update_all(request): + if not is_allowed_security_level('middle'): + print(f"ERROR: To use this action, a security_level of `middle or below` is required. Please contact the administrator.") + return web.Response(status=403) + + try: + core.save_snapshot_with_postfix('autosave') + + json_obj = await core.get_data_by_mode(request.rel_url.query["mode"], 'custom-node-list.json') + + check_custom_nodes_installed(json_obj, do_update=True) + + updated = [item['title'] for item in json_obj['custom_nodes'] if item['installed'] == 'Update'] + failed = [item['title'] for item in json_obj['custom_nodes'] if item['installed'] == 'Fail'] + + res = {'updated': updated, 'failed': failed} + + if len(updated) == 0 and len(failed) == 0: + status = 200 + else: + status = 201 + + return web.json_response(res, status=status, content_type='application/json') + except: + return web.Response(status=400) + finally: + core.clear_pip_cache() + + +def convert_markdown_to_html(input_text): + pattern_a = re.compile(r'\[a/([^]]+)\]\(([^)]+)\)') + pattern_w = re.compile(r'\[w/([^]]+)\]') + pattern_i = re.compile(r'\[i/([^]]+)\]') + pattern_bold = re.compile(r'\*\*([^*]+)\*\*') + pattern_white = re.compile(r'%%([^*]+)%%') + + def replace_a(match): + return f"{match.group(1)}" + + def replace_w(match): + return f"

{match.group(1)}

" + + def replace_i(match): + return f"

{match.group(1)}

" + + def replace_bold(match): + return f"{match.group(1)}" + + def replace_white(match): + return f"{match.group(1)}" + + input_text = input_text.replace('\\[', '[').replace('\\]', ']').replace('<', '<').replace('>', '>') + + result_text = re.sub(pattern_a, replace_a, input_text) + result_text = re.sub(pattern_w, replace_w, result_text) + result_text = re.sub(pattern_i, replace_i, result_text) + result_text = re.sub(pattern_bold, replace_bold, result_text) + result_text = re.sub(pattern_white, replace_white, result_text) + + return result_text.replace("\n", "
") + + +def populate_markdown(x): + if 'description' in x: + x['description'] = convert_markdown_to_html(x['description']) + + if 'name' in x: + x['name'] = x['name'].replace('<', '<').replace('>', '>') + + if 'title' in x: + x['title'] = x['title'].replace('<', '<').replace('>', '>') + + +@PromptServer.instance.routes.get("/customnode/getlist") +async def fetch_customnode_list(request): + if "skip_update" in request.rel_url.query and request.rel_url.query["skip_update"] == "true": + skip_update = True + else: + skip_update = False + + if request.rel_url.query["mode"] == "local": + channel = 'local' + else: + channel = core.get_config()['channel_url'] + + json_obj = await core.get_data_by_mode(request.rel_url.query["mode"], 'custom-node-list.json') + json_obj_github = await core.get_data_by_mode(request.rel_url.query["mode"], 'github-stats.json', 'default') + json_obj = await populate_github_stats(json_obj, json_obj_github) + + def is_ignored_notice(code): + if code is not None and code.startswith('#NOTICE_'): + try: + notice_version = [int(x) for x in code[8:].split('.')] + return notice_version[0] < core.version[0] or (notice_version[0] == core.version[0] and notice_version[1] <= core.version[1]) + except Exception: + return False + else: + return False + + json_obj['custom_nodes'] = [record for record in json_obj['custom_nodes'] if not is_ignored_notice(record.get('author'))] + + check_custom_nodes_installed(json_obj, False, not skip_update) + + for x in json_obj['custom_nodes']: + populate_markdown(x) + + if channel != 'local': + found = 'custom' + + for name, url in core.get_channel_dict().items(): + if url == channel: + found = name + break + + channel = found + + json_obj['channel'] = channel + + return web.json_response(json_obj, content_type='application/json') + + +@PromptServer.instance.routes.get("/customnode/alternatives") +async def fetch_customnode_alternatives(request): + alter_json = await core.get_data_by_mode(request.rel_url.query["mode"], 'alter-list.json') + + for item in alter_json['items']: + populate_markdown(item) + + return web.json_response(alter_json, content_type='application/json') + + +@PromptServer.instance.routes.get("/alternatives/getlist") +async def fetch_alternatives_list(request): + if "skip_update" in request.rel_url.query and request.rel_url.query["skip_update"] == "true": + skip_update = True + else: + skip_update = False + + alter_json = await core.get_data_by_mode(request.rel_url.query["mode"], 'alter-list.json') + custom_node_json = await core.get_data_by_mode(request.rel_url.query["mode"], 'custom-node-list.json') + + fileurl_to_custom_node = {} + + for item in custom_node_json['custom_nodes']: + for fileurl in item['files']: + fileurl_to_custom_node[fileurl] = item + + for item in alter_json['items']: + fileurl = item['id'] + if fileurl in fileurl_to_custom_node: + custom_node = fileurl_to_custom_node[fileurl] + core.check_a_custom_node_installed(custom_node, not skip_update) + + populate_markdown(item) + populate_markdown(custom_node) + item['custom_node'] = custom_node + + return web.json_response(alter_json, content_type='application/json') + + +def check_model_installed(json_obj): + def process_model(item): + model_path = get_model_path(item) + item['installed'] = 'None' + + if model_path is not None: + if model_path.endswith('.zip'): + if os.path.exists(model_path[:-4]): + item['installed'] = 'True' + else: + item['installed'] = 'False' + elif os.path.exists(model_path): + item['installed'] = 'True' + else: + item['installed'] = 'False' + + with concurrent.futures.ThreadPoolExecutor(8) as executor: + for item in json_obj['models']: + executor.submit(process_model, item) + + +@PromptServer.instance.routes.get("/externalmodel/getlist") +async def fetch_externalmodel_list(request): + json_obj = await core.get_data_by_mode(request.rel_url.query["mode"], 'model-list.json') + + check_model_installed(json_obj) + + for x in json_obj['models']: + populate_markdown(x) + + return web.json_response(json_obj, content_type='application/json') + + +@PromptServer.instance.routes.get("/snapshot/get_current") +async def get_snapshot_list(request): + json_obj = core.get_current_snapshot() + return web.json_response(json_obj, content_type='application/json') + + +@PromptServer.instance.routes.get("/snapshot/getlist") +async def get_snapshot_list(request): + snapshots_directory = os.path.join(core.comfyui_manager_path, 'snapshots') + items = [f[:-5] for f in os.listdir(snapshots_directory) if f.endswith('.json')] + items.sort(reverse=True) + return web.json_response({'items': items}, content_type='application/json') + + +@PromptServer.instance.routes.get("/snapshot/remove") +async def remove_snapshot(request): + if not is_allowed_security_level('middle'): + print(f"ERROR: To use this action, a security_level of `middle or below` is required. Please contact the administrator.") + return web.Response(status=403) + + try: + target = request.rel_url.query["target"] + + path = os.path.join(core.comfyui_manager_path, 'snapshots', f"{target}.json") + if os.path.exists(path): + os.remove(path) + + return web.Response(status=200) + except: + return web.Response(status=400) + + +@PromptServer.instance.routes.get("/snapshot/restore") +async def remove_snapshot(request): + if not is_allowed_security_level('middle'): + print(f"ERROR: To use this action, a security_level of `middle or below` is required. Please contact the administrator.") + return web.Response(status=403) + + try: + target = request.rel_url.query["target"] + + path = os.path.join(core.comfyui_manager_path, 'snapshots', f"{target}.json") + if os.path.exists(path): + if not os.path.exists(core.startup_script_path): + os.makedirs(core.startup_script_path) + + target_path = os.path.join(core.startup_script_path, "restore-snapshot.json") + shutil.copy(path, target_path) + + print(f"Snapshot restore scheduled: `{target}`") + return web.Response(status=200) + + print(f"Snapshot file not found: `{path}`") + return web.Response(status=400) + except: + return web.Response(status=400) + + +@PromptServer.instance.routes.get("/snapshot/get_current") +async def get_current_snapshot_api(request): + try: + return web.json_response(core.get_current_snapshot(), content_type='application/json') + except: + return web.Response(status=400) + + +@PromptServer.instance.routes.get("/snapshot/save") +async def save_snapshot(request): + try: + core.save_snapshot_with_postfix('snapshot') + return web.Response(status=200) + except: + return web.Response(status=400) + + +def unzip_install(files): + temp_filename = 'manager-temp.zip' + for url in files: + if url.endswith("/"): + url = url[:-1] + try: + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'} + + req = urllib.request.Request(url, headers=headers) + response = urllib.request.urlopen(req) + data = response.read() + + with open(temp_filename, 'wb') as f: + f.write(data) + + with zipfile.ZipFile(temp_filename, 'r') as zip_ref: + zip_ref.extractall(core.custom_nodes_path) + + os.remove(temp_filename) + except Exception as e: + print(f"Install(unzip) error: {url} / {e}", file=sys.stderr) + return False + + print("Installation was successful.") + return True + + +def download_url_with_agent(url, save_path): + try: + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'} + + req = urllib.request.Request(url, headers=headers) + response = urllib.request.urlopen(req) + data = response.read() + + if not os.path.exists(os.path.dirname(save_path)): + os.makedirs(os.path.dirname(save_path)) + + with open(save_path, 'wb') as f: + f.write(data) + + except Exception as e: + print(f"Download error: {url} / {e}", file=sys.stderr) + return False + + print("Installation was successful.") + return True + + +def copy_install(files, js_path_name=None): + for url in files: + if url.endswith("/"): + url = url[:-1] + try: + filename = os.path.basename(url) + if url.endswith(".py"): + download_url(url, core.custom_nodes_path, filename) + else: + path = os.path.join(core.js_path, js_path_name) if js_path_name is not None else core.js_path + if not os.path.exists(path): + os.makedirs(path) + download_url(url, path, filename) + + except Exception as e: + print(f"Install(copy) error: {url} / {e}", file=sys.stderr) + return False + + print("Installation was successful.") + return True + + +def copy_uninstall(files, js_path_name='.'): + for url in files: + if url.endswith("/"): + url = url[:-1] + dir_name = os.path.basename(url) + base_path = core.custom_nodes_path if url.endswith('.py') else os.path.join(core.js_path, js_path_name) + file_path = os.path.join(base_path, dir_name) + + try: + if os.path.exists(file_path): + os.remove(file_path) + elif os.path.exists(file_path + ".disabled"): + os.remove(file_path + ".disabled") + except Exception as e: + print(f"Uninstall(copy) error: {url} / {e}", file=sys.stderr) + return False + + print("Uninstallation was successful.") + return True + + +def copy_set_active(files, is_disable, js_path_name='.'): + if is_disable: + action_name = "Disable" + else: + action_name = "Enable" + + for url in files: + if url.endswith("/"): + url = url[:-1] + dir_name = os.path.basename(url) + base_path = core.custom_nodes_path if url.endswith('.py') else os.path.join(core.js_path, js_path_name) + file_path = os.path.join(base_path, dir_name) + + try: + if is_disable: + current_name = file_path + new_name = file_path + ".disabled" + else: + current_name = file_path + ".disabled" + new_name = file_path + + os.rename(current_name, new_name) + + except Exception as e: + print(f"{action_name}(copy) error: {url} / {e}", file=sys.stderr) + + return False + + print(f"{action_name} was successful.") + return True + + +@PromptServer.instance.routes.post("/customnode/install") +async def install_custom_node(request): + if not is_allowed_security_level('middle'): + print(f"ERROR: To use this action, a security_level of `middle or below` is required. Please contact the administrator.") + return web.Response(status=403) + + json_data = await request.json() + + risky_level = await get_risky_level(json_data['files']) + if not is_allowed_security_level(risky_level): + print(f"ERROR: This installation is not allowed in this security_level. Please contact the administrator.") + return web.Response(status=404) + + install_type = json_data['install_type'] + + print(f"Install custom node '{json_data['title']}'") + + res = False + + if len(json_data['files']) == 0: + return web.Response(status=400) + + if install_type == "unzip": + res = unzip_install(json_data['files']) + + if install_type == "copy": + js_path_name = json_data['js_path'] if 'js_path' in json_data else '.' + res = copy_install(json_data['files'], js_path_name) + + elif install_type == "git-clone": + res = core.gitclone_install(json_data['files']) + + if 'pip' in json_data: + for pname in json_data['pip']: + pkg = core.remap_pip_package(pname) + install_cmd = [sys.executable, "-m", "pip", "install", pkg] + core.try_install_script(json_data['files'][0], ".", install_cmd) + + core.clear_pip_cache() + + if res: + print(f"After restarting ComfyUI, please refresh the browser.") + return web.json_response({}, content_type='application/json') + + return web.Response(status=400) + + +@PromptServer.instance.routes.post("/customnode/fix") +async def fix_custom_node(request): + if not is_allowed_security_level('middle'): + print(f"ERROR: To use this action, a security_level of `middle or below` is required. Please contact the administrator.") + return web.Response(status=403) + + json_data = await request.json() + + install_type = json_data['install_type'] + + print(f"Install custom node '{json_data['title']}'") + + res = False + + if len(json_data['files']) == 0: + return web.Response(status=400) + + if install_type == "git-clone": + res = core.gitclone_fix(json_data['files']) + else: + return web.Response(status=400) + + if 'pip' in json_data: + for pname in json_data['pip']: + install_cmd = [sys.executable, "-m", "pip", "install", '-U', pname] + core.try_install_script(json_data['files'][0], ".", install_cmd) + + if res: + print(f"After restarting ComfyUI, please refresh the browser.") + return web.json_response({}, content_type='application/json') + + return web.Response(status=400) + + +@PromptServer.instance.routes.post("/customnode/install/git_url") +async def install_custom_node_git_url(request): + if not is_allowed_security_level('high'): + print(f"ERROR: To use this feature, you must set '--listen' to a local IP and set the security level to 'middle' or 'weak'. Please contact the administrator.") + return web.Response(status=403) + + url = await request.text() + res = core.gitclone_install([url]) + + if res: + print(f"After restarting ComfyUI, please refresh the browser.") + return web.Response(status=200) + + return web.Response(status=400) + + +@PromptServer.instance.routes.post("/customnode/install/pip") +async def install_custom_node_git_url(request): + if not is_allowed_security_level('high'): + print(f"ERROR: To use this feature, you must set '--listen' to a local IP and set the security level to 'middle' or 'weak'. Please contact the administrator.") + return web.Response(status=403) + + packages = await request.text() + core.pip_install(packages.split(' ')) + + return web.Response(status=200) + + +@PromptServer.instance.routes.post("/customnode/uninstall") +async def uninstall_custom_node(request): + if not is_allowed_security_level('middle'): + print(f"ERROR: To use this action, a security_level of `middle or below` is required. Please contact the administrator.") + return web.Response(status=403) + + json_data = await request.json() + + install_type = json_data['install_type'] + + print(f"Uninstall custom node '{json_data['title']}'") + + res = False + + if install_type == "copy": + js_path_name = json_data['js_path'] if 'js_path' in json_data else '.' + res = copy_uninstall(json_data['files'], js_path_name) + + elif install_type == "git-clone": + res = core.gitclone_uninstall(json_data['files']) + + if res: + print(f"After restarting ComfyUI, please refresh the browser.") + return web.json_response({}, content_type='application/json') + + return web.Response(status=400) + + +@PromptServer.instance.routes.post("/customnode/update") +async def update_custom_node(request): + if not is_allowed_security_level('middle'): + print(f"ERROR: To use this action, a security_level of `middle or below` is required. Please contact the administrator.") + return web.Response(status=403) + + json_data = await request.json() + + install_type = json_data['install_type'] + + print(f"Update custom node '{json_data['title']}'") + + res = False + + if install_type == "git-clone": + res = core.gitclone_update(json_data['files']) + + core.clear_pip_cache() + + if res: + print(f"After restarting ComfyUI, please refresh the browser.") + return web.json_response({}, content_type='application/json') + + return web.Response(status=400) + + +@PromptServer.instance.routes.get("/comfyui_manager/update_comfyui") +async def update_comfyui(request): + print(f"Update ComfyUI") + + try: + repo_path = os.path.dirname(folder_paths.__file__) + res = core.update_path(repo_path) + if res == "fail": + print(f"ComfyUI update fail: The installed ComfyUI does not have a Git repository.") + return web.Response(status=400) + elif res == "updated": + return web.Response(status=201) + else: # skipped + return web.Response(status=200) + except Exception as e: + print(f"ComfyUI update fail: {e}", file=sys.stderr) + + return web.Response(status=400) + + +@PromptServer.instance.routes.post("/customnode/toggle_active") +async def toggle_active(request): + json_data = await request.json() + + install_type = json_data['install_type'] + is_disabled = json_data['installed'] == "Disabled" + + print(f"Update custom node '{json_data['title']}'") + + res = False + + if install_type == "git-clone": + res = core.gitclone_set_active(json_data['files'], not is_disabled) + elif install_type == "copy": + res = copy_set_active(json_data['files'], not is_disabled, json_data.get('js_path', None)) + + if res: + return web.json_response({}, content_type='application/json') + + return web.Response(status=400) + + +@PromptServer.instance.routes.post("/model/install") +async def install_model(request): + json_data = await request.json() + + model_path = get_model_path(json_data) + + res = False + + try: + if model_path is not None: + print(f"Install model '{json_data['name']}' into '{model_path}'") + + model_url = json_data['url'] + if not core.get_config()['model_download_by_agent'] and ( + model_url.startswith('https://github.com') or model_url.startswith('https://huggingface.co') or model_url.startswith('https://heibox.uni-heidelberg.de')): + model_dir = get_model_dir(json_data) + download_url(model_url, model_dir, filename=json_data['filename']) + if model_path.endswith('.zip'): + res = core.unzip(model_path) + else: + res = True + + if res: + return web.json_response({}, content_type='application/json') + else: + res = download_url_with_agent(model_url, model_path) + if res and model_path.endswith('.zip'): + res = core.unzip(model_path) + else: + print(f"Model installation error: invalid model type - {json_data['type']}") + + if res: + return web.json_response({}, content_type='application/json') + except Exception as e: + print(f"[ERROR] {e}", file=sys.stderr) + + return web.Response(status=400) + + +class ManagerTerminalHook: + def write_stderr(self, msg): + PromptServer.instance.send_sync("manager-terminal-feedback", {"data": msg}) + + def write_stdout(self, msg): + PromptServer.instance.send_sync("manager-terminal-feedback", {"data": msg}) + + +manager_terminal_hook = ManagerTerminalHook() + + +@PromptServer.instance.routes.get("/manager/terminal") +async def terminal_mode(request): + if not is_allowed_security_level('high'): + print(f"ERROR: To use this action, a security_level of `weak` is required. Please contact the administrator.") + return web.Response(status=403) + + if "mode" in request.rel_url.query: + if request.rel_url.query['mode'] == 'true': + sys.__comfyui_manager_terminal_hook.add_hook('cm', manager_terminal_hook) + else: + sys.__comfyui_manager_terminal_hook.remove_hook('cm') + + return web.Response(status=200) + + +@PromptServer.instance.routes.get("/manager/preview_method") +async def preview_method(request): + if "value" in request.rel_url.query: + set_preview_method(request.rel_url.query['value']) + core.write_config() + else: + return web.Response(text=core.manager_funcs.get_current_preview_method(), status=200) + + return web.Response(status=200) + + +@PromptServer.instance.routes.get("/manager/badge_mode") +async def badge_mode(request): + if "value" in request.rel_url.query: + set_badge_mode(request.rel_url.query['value']) + core.write_config() + else: + return web.Response(text=core.get_config()['badge_mode'], status=200) + + return web.Response(status=200) + + +@PromptServer.instance.routes.get("/manager/default_ui") +async def default_ui_mode(request): + if "value" in request.rel_url.query: + set_default_ui_mode(request.rel_url.query['value']) + core.write_config() + else: + return web.Response(text=core.get_config()['default_ui'], status=200) + + return web.Response(status=200) + + +@PromptServer.instance.routes.get("/manager/component/policy") +async def component_policy(request): + if "value" in request.rel_url.query: + set_component_policy(request.rel_url.query['value']) + core.write_config() + else: + return web.Response(text=core.get_config()['component_policy'], status=200) + + return web.Response(status=200) + + +@PromptServer.instance.routes.get("/manager/dbl_click/policy") +async def dbl_click_policy(request): + if "value" in request.rel_url.query: + set_double_click_policy(request.rel_url.query['value']) + core.write_config() + else: + return web.Response(text=core.get_config()['double_click_policy'], status=200) + + return web.Response(status=200) + + +@PromptServer.instance.routes.get("/manager/channel_url_list") +async def channel_url_list(request): + channels = core.get_channel_dict() + if "value" in request.rel_url.query: + channel_url = channels.get(request.rel_url.query['value']) + if channel_url is not None: + core.get_config()['channel_url'] = channel_url + core.write_config() + else: + selected = 'custom' + selected_url = core.get_config()['channel_url'] + + for name, url in channels.items(): + if url == selected_url: + selected = name + break + + res = {'selected': selected, + 'list': core.get_channel_list()} + return web.json_response(res, status=200) + + return web.Response(status=200) + + +def add_target_blank(html_text): + pattern = r'(]*)(>)' + + def add_target(match): + if 'target=' not in match.group(1): + return match.group(1) + ' target="_blank"' + match.group(2) + return match.group(0) + + modified_html = re.sub(pattern, add_target, html_text) + + return modified_html + + +@PromptServer.instance.routes.get("/manager/notice") +async def get_notice(request): + url = "github.com" + path = "/ltdrdata/ltdrdata.github.io/wiki/News" + + async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session: + async with session.get(f"https://{url}{path}") as response: + if response.status == 200: + # html_content = response.read().decode('utf-8') + html_content = await response.text() + + pattern = re.compile(r'
([\s\S]*?)
') + match = pattern.search(html_content) + + if match: + markdown_content = match.group(1) + markdown_content += f"
ComfyUI: {core.comfy_ui_revision}[{comfy_ui_hash[:6]}]({core.comfy_ui_commit_datetime.date()})" + # markdown_content += f"
         ()" + markdown_content += f"
Manager: {core.version_str}" + + markdown_content = add_target_blank(markdown_content) + + try: + if core.comfy_ui_required_commit_datetime.date() > core.comfy_ui_commit_datetime.date(): + markdown_content = f'

Your ComfyUI is too OUTDATED!!!

' + markdown_content + except: + pass + + return web.Response(text=markdown_content, status=200) + else: + return web.Response(text="Unable to retrieve Notice", status=200) + else: + return web.Response(text="Unable to retrieve Notice", status=200) + + +@PromptServer.instance.routes.get("/manager/reboot") +def restart(self): + if not is_allowed_security_level('middle'): + print(f"ERROR: To use this action, a security_level of `middle or below` is required. Please contact the administrator.") + return web.Response(status=403) + + try: + sys.stdout.close_log() + except Exception as e: + pass + + if '__COMFY_CLI_SESSION__' in os.environ: + with open(os.path.join(os.environ['__COMFY_CLI_SESSION__'] + '.reboot'), 'w') as file: + pass + + print(f"\nRestarting...\n\n") + exit(0) + + print(f"\nRestarting... [Legacy Mode]\n\n") + if sys.platform.startswith('win32'): + return os.execv(sys.executable, ['"' + sys.executable + '"', '"' + sys.argv[0] + '"'] + sys.argv[1:]) + else: + return os.execv(sys.executable, [sys.executable] + sys.argv) + + +def sanitize_filename(input_string): + # 알파벳, 숫자, 및 밑줄 이외의 문자를 밑줄로 대체 + result_string = re.sub(r'[^a-zA-Z0-9_]', '_', input_string) + return result_string + + +@PromptServer.instance.routes.post("/manager/component/save") +async def save_component(request): + try: + data = await request.json() + name = data['name'] + workflow = data['workflow'] + + if not os.path.exists(components_path): + os.mkdir(components_path) + + if 'packname' in workflow and workflow['packname'] != '': + sanitized_name = sanitize_filename(workflow['packname']) + '.pack' + else: + sanitized_name = sanitize_filename(name) + '.json' + + filepath = os.path.join(components_path, sanitized_name) + components = {} + if os.path.exists(filepath): + with open(filepath) as f: + components = json.load(f) + + components[name] = workflow + + with open(filepath, 'w') as f: + json.dump(components, f, indent=4, sort_keys=True) + return web.Response(text=filepath, status=200) + except: + return web.Response(status=400) + + +@PromptServer.instance.routes.post("/manager/component/loads") +async def load_components(request): + try: + json_files = [f for f in os.listdir(components_path) if f.endswith('.json')] + pack_files = [f for f in os.listdir(components_path) if f.endswith('.pack')] + + components = {} + for json_file in json_files + pack_files: + file_path = os.path.join(components_path, json_file) + with open(file_path, 'r') as file: + try: + # When there is a conflict between the .pack and the .json, the pack takes precedence and overrides. + components.update(json.load(file)) + except json.JSONDecodeError as e: + print(f"[ComfyUI-Manager] Error decoding component file in file {json_file}: {e}") + + return web.json_response(components) + except Exception as e: + print(f"[ComfyUI-Manager] failed to load components\n{e}") + return web.Response(status=400) + + +@PromptServer.instance.routes.get("/manager/share_option") +async def share_option(request): + if "value" in request.rel_url.query: + core.get_config()['share_option'] = request.rel_url.query['value'] + core.write_config() + else: + return web.Response(text=core.get_config()['share_option'], status=200) + + return web.Response(status=200) + + +def get_openart_auth(): + if not os.path.exists(os.path.join(core.comfyui_manager_path, ".openart_key")): + return None + try: + with open(os.path.join(core.comfyui_manager_path, ".openart_key"), "r") as f: + openart_key = f.read().strip() + return openart_key if openart_key else None + except: + return None + + +def get_matrix_auth(): + if not os.path.exists(os.path.join(core.comfyui_manager_path, "matrix_auth")): + return None + try: + with open(os.path.join(core.comfyui_manager_path, "matrix_auth"), "r") as f: + matrix_auth = f.read() + homeserver, username, password = matrix_auth.strip().split("\n") + if not homeserver or not username or not password: + return None + return { + "homeserver": homeserver, + "username": username, + "password": password, + } + except: + return None + + +def get_comfyworkflows_auth(): + if not os.path.exists(os.path.join(core.comfyui_manager_path, "comfyworkflows_sharekey")): + return None + try: + with open(os.path.join(core.comfyui_manager_path, "comfyworkflows_sharekey"), "r") as f: + share_key = f.read() + if not share_key.strip(): + return None + return share_key + except: + return None + + +def get_youml_settings(): + if not os.path.exists(os.path.join(core.comfyui_manager_path, ".youml")): + return None + try: + with open(os.path.join(core.comfyui_manager_path, ".youml"), "r") as f: + youml_settings = f.read().strip() + return youml_settings if youml_settings else None + except: + return None + + +def set_youml_settings(settings): + with open(os.path.join(core.comfyui_manager_path, ".youml"), "w") as f: + f.write(settings) + + +@PromptServer.instance.routes.get("/manager/get_openart_auth") +async def api_get_openart_auth(request): + # print("Getting stored Matrix credentials...") + openart_key = get_openart_auth() + if not openart_key: + return web.Response(status=404) + return web.json_response({"openart_key": openart_key}) + + +@PromptServer.instance.routes.post("/manager/set_openart_auth") +async def api_set_openart_auth(request): + json_data = await request.json() + openart_key = json_data['openart_key'] + with open(os.path.join(core.comfyui_manager_path, ".openart_key"), "w") as f: + f.write(openart_key) + return web.Response(status=200) + + +@PromptServer.instance.routes.get("/manager/get_matrix_auth") +async def api_get_matrix_auth(request): + # print("Getting stored Matrix credentials...") + matrix_auth = get_matrix_auth() + if not matrix_auth: + return web.Response(status=404) + return web.json_response(matrix_auth) + + +@PromptServer.instance.routes.get("/manager/youml/settings") +async def api_get_youml_settings(request): + youml_settings = get_youml_settings() + if not youml_settings: + return web.Response(status=404) + return web.json_response(json.loads(youml_settings)) + + +@PromptServer.instance.routes.post("/manager/youml/settings") +async def api_set_youml_settings(request): + json_data = await request.json() + set_youml_settings(json.dumps(json_data)) + return web.Response(status=200) + + +@PromptServer.instance.routes.get("/manager/get_comfyworkflows_auth") +async def api_get_comfyworkflows_auth(request): + # Check if the user has provided Matrix credentials in a file called 'matrix_accesstoken' + # in the same directory as the ComfyUI base folder + # print("Getting stored Comfyworkflows.com auth...") + comfyworkflows_auth = get_comfyworkflows_auth() + if not comfyworkflows_auth: + return web.Response(status=404) + return web.json_response({"comfyworkflows_sharekey": comfyworkflows_auth}) + + +args.enable_cors_header = "*" +if hasattr(PromptServer.instance, "app"): + app = PromptServer.instance.app + cors_middleware = server.create_cors_middleware(args.enable_cors_header) + app.middlewares.append(cors_middleware) + + +@PromptServer.instance.routes.post("/manager/set_esheep_workflow_and_images") +async def set_esheep_workflow_and_images(request): + json_data = await request.json() + current_workflow = json_data['workflow'] + images = json_data['images'] + with open(os.path.join(core.comfyui_manager_path, "esheep_share_message.json"), "w", encoding='utf-8') as file: + json.dump(json_data, file, indent=4) + return web.Response(status=200) + + +@PromptServer.instance.routes.get("/manager/get_esheep_workflow_and_images") +async def get_esheep_workflow_and_images(request): + with open(os.path.join(core.comfyui_manager_path, "esheep_share_message.json"), 'r', encoding='utf-8') as file: + data = json.load(file) + return web.Response(status=200, text=json.dumps(data)) + + +def set_matrix_auth(json_data): + homeserver = json_data['homeserver'] + username = json_data['username'] + password = json_data['password'] + with open(os.path.join(core.comfyui_manager_path, "matrix_auth"), "w") as f: + f.write("\n".join([homeserver, username, password])) + + +def set_comfyworkflows_auth(comfyworkflows_sharekey): + with open(os.path.join(core.comfyui_manager_path, "comfyworkflows_sharekey"), "w") as f: + f.write(comfyworkflows_sharekey) + + +def has_provided_matrix_auth(matrix_auth): + return matrix_auth['homeserver'].strip() and matrix_auth['username'].strip() and matrix_auth['password'].strip() + + +def has_provided_comfyworkflows_auth(comfyworkflows_sharekey): + return comfyworkflows_sharekey.strip() + + +def extract_model_file_names(json_data): + """Extract unique file names from the input JSON data.""" + file_names = set() + model_filename_extensions = {'.safetensors', '.ckpt', '.pt', '.pth', '.bin'} + + # Recursively search for file names in the JSON data + def recursive_search(data): + if isinstance(data, dict): + for value in data.values(): + recursive_search(value) + elif isinstance(data, list): + for item in data: + recursive_search(item) + elif isinstance(data, str) and '.' in data: + file_names.add(os.path.basename(data)) # file_names.add(data) + + recursive_search(json_data) + return [f for f in list(file_names) if os.path.splitext(f)[1] in model_filename_extensions] + + +def find_file_paths(base_dir, file_names): + """Find the paths of the files in the base directory.""" + file_paths = {} + + for root, dirs, files in os.walk(base_dir): + # Exclude certain directories + dirs[:] = [d for d in dirs if d not in ['.git']] + + for file in files: + if file in file_names: + file_paths[file] = os.path.join(root, file) + return file_paths + + +def compute_sha256_checksum(filepath): + """Compute the SHA256 checksum of a file, in chunks""" + sha256 = hashlib.sha256() + with open(filepath, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b''): + sha256.update(chunk) + return sha256.hexdigest() + + +@PromptServer.instance.routes.post("/manager/share") +async def share_art(request): + # get json data + json_data = await request.json() + + matrix_auth = json_data['matrix_auth'] + comfyworkflows_sharekey = json_data['cw_auth']['cw_sharekey'] + + set_matrix_auth(matrix_auth) + set_comfyworkflows_auth(comfyworkflows_sharekey) + + share_destinations = json_data['share_destinations'] + credits = json_data['credits'] + title = json_data['title'] + description = json_data['description'] + is_nsfw = json_data['is_nsfw'] + prompt = json_data['prompt'] + potential_outputs = json_data['potential_outputs'] + selected_output_index = json_data['selected_output_index'] + + try: + output_to_share = potential_outputs[int(selected_output_index)] + except: + # for now, pick the first output + output_to_share = potential_outputs[0] + + assert output_to_share['type'] in ('image', 'output') + output_dir = folder_paths.get_output_directory() + + if output_to_share['type'] == 'image': + asset_filename = output_to_share['image']['filename'] + asset_subfolder = output_to_share['image']['subfolder'] + + if output_to_share['image']['type'] == 'temp': + output_dir = folder_paths.get_temp_directory() + else: + asset_filename = output_to_share['output']['filename'] + asset_subfolder = output_to_share['output']['subfolder'] + + if asset_subfolder: + asset_filepath = os.path.join(output_dir, asset_subfolder, asset_filename) + else: + asset_filepath = os.path.join(output_dir, asset_filename) + + # get the mime type of the asset + assetFileType = mimetypes.guess_type(asset_filepath)[0] + + share_website_host = "UNKNOWN" + if "comfyworkflows" in share_destinations: + share_website_host = "https://comfyworkflows.com" + share_endpoint = f"{share_website_host}/api" + + # get presigned urls + async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session: + async with session.post( + f"{share_endpoint}/get_presigned_urls", + json={ + "assetFileName": asset_filename, + "assetFileType": assetFileType, + "workflowJsonFileName": 'workflow.json', + "workflowJsonFileType": 'application/json', + }, + ) as resp: + assert resp.status == 200 + presigned_urls_json = await resp.json() + assetFilePresignedUrl = presigned_urls_json["assetFilePresignedUrl"] + assetFileKey = presigned_urls_json["assetFileKey"] + workflowJsonFilePresignedUrl = presigned_urls_json["workflowJsonFilePresignedUrl"] + workflowJsonFileKey = presigned_urls_json["workflowJsonFileKey"] + + # upload asset + async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session: + async with session.put(assetFilePresignedUrl, data=open(asset_filepath, "rb")) as resp: + assert resp.status == 200 + + # upload workflow json + async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session: + async with session.put(workflowJsonFilePresignedUrl, data=json.dumps(prompt['workflow']).encode('utf-8')) as resp: + assert resp.status == 200 + + model_filenames = extract_model_file_names(prompt['workflow']) + model_file_paths = find_file_paths(folder_paths.base_path, model_filenames) + + models_info = {} + for filename, filepath in model_file_paths.items(): + models_info[filename] = { + "filename": filename, + "sha256_checksum": compute_sha256_checksum(filepath), + "relative_path": os.path.relpath(filepath, folder_paths.base_path), + } + + # make a POST request to /api/upload_workflow with form data key values + async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session: + form = aiohttp.FormData() + if comfyworkflows_sharekey: + form.add_field("shareKey", comfyworkflows_sharekey) + form.add_field("source", "comfyui_manager") + form.add_field("assetFileKey", assetFileKey) + form.add_field("assetFileType", assetFileType) + form.add_field("workflowJsonFileKey", workflowJsonFileKey) + form.add_field("sharedWorkflowWorkflowJsonString", json.dumps(prompt['workflow'])) + form.add_field("sharedWorkflowPromptJsonString", json.dumps(prompt['output'])) + form.add_field("shareWorkflowCredits", credits) + form.add_field("shareWorkflowTitle", title) + form.add_field("shareWorkflowDescription", description) + form.add_field("shareWorkflowIsNSFW", str(is_nsfw).lower()) + form.add_field("currentSnapshot", json.dumps(core.get_current_snapshot())) + form.add_field("modelsInfo", json.dumps(models_info)) + + async with session.post( + f"{share_endpoint}/upload_workflow", + data=form, + ) as resp: + assert resp.status == 200 + upload_workflow_json = await resp.json() + workflowId = upload_workflow_json["workflowId"] + + # check if the user has provided Matrix credentials + if "matrix" in share_destinations: + comfyui_share_room_id = '!LGYSoacpJPhIfBqVfb:matrix.org' + filename = os.path.basename(asset_filepath) + content_type = assetFileType + + try: + from matrix_client.api import MatrixHttpApi + from matrix_client.client import MatrixClient + + homeserver = 'matrix.org' + if matrix_auth: + homeserver = matrix_auth.get('homeserver', 'matrix.org') + homeserver = homeserver.replace("http://", "https://") + if not homeserver.startswith("https://"): + homeserver = "https://" + homeserver + + client = MatrixClient(homeserver) + try: + token = client.login(username=matrix_auth['username'], password=matrix_auth['password']) + if not token: + return web.json_response({"error": "Invalid Matrix credentials."}, content_type='application/json', status=400) + except: + return web.json_response({"error": "Invalid Matrix credentials."}, content_type='application/json', status=400) + + matrix = MatrixHttpApi(homeserver, token=token) + with open(asset_filepath, 'rb') as f: + mxc_url = matrix.media_upload(f.read(), content_type, filename=filename)['content_uri'] + + workflow_json_mxc_url = matrix.media_upload(prompt['workflow'], 'application/json', filename='workflow.json')['content_uri'] + + text_content = "" + if title: + text_content += f"{title}\n" + if description: + text_content += f"{description}\n" + if credits: + text_content += f"\ncredits: {credits}\n" + response = matrix.send_message(comfyui_share_room_id, text_content) + response = matrix.send_content(comfyui_share_room_id, mxc_url, filename, 'm.image') + response = matrix.send_content(comfyui_share_room_id, workflow_json_mxc_url, 'workflow.json', 'm.file') + except: + import traceback + traceback.print_exc() + return web.json_response({"error": "An error occurred when sharing your art to Matrix."}, content_type='application/json', status=500) + + return web.json_response({ + "comfyworkflows": { + "url": None if "comfyworkflows" not in share_destinations else f"{share_website_host}/workflows/{workflowId}", + }, + "matrix": { + "success": None if "matrix" not in share_destinations else True + } + }, content_type='application/json', status=200) + + +def sanitize(data): + return data.replace("<", "<").replace(">", ">") + + +async def _confirm_try_install(sender, custom_node_url, msg): + json_obj = await core.get_data_by_mode('default', 'custom-node-list.json') + + sender = sanitize(sender) + msg = sanitize(msg) + target = core.lookup_customnode_by_url(json_obj, custom_node_url) + + if target is not None: + PromptServer.instance.send_sync("cm-api-try-install-customnode", + {"sender": sender, "target": target, "msg": msg}) + else: + print(f"[ComfyUI Manager API] Failed to try install - Unknown custom node url '{custom_node_url}'") + + +def confirm_try_install(sender, custom_node_url, msg): + asyncio.run(_confirm_try_install(sender, custom_node_url, msg)) + + +cm_global.register_api('cm.try-install-custom-node', confirm_try_install) + +import asyncio + + +async def default_cache_update(): + async def get_cache(filename): + uri = 'https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/' + filename + cache_uri = str(core.simple_hash(uri)) + '_' + filename + cache_uri = os.path.join(core.cache_dir, cache_uri) + + json_obj = await core.get_data(uri, True) + + with core.cache_lock: + with open(cache_uri, "w", encoding='utf-8') as file: + json.dump(json_obj, file, indent=4, sort_keys=True) + print(f"[ComfyUI-Manager] default cache updated: {uri}") + + a = get_cache("custom-node-list.json") + b = get_cache("extension-node-map.json") + c = get_cache("model-list.json") + d = get_cache("alter-list.json") + e = get_cache("github-stats.json") + + await asyncio.gather(a, b, c, d, e) + + +threading.Thread(target=lambda: asyncio.run(default_cache_update())).start() + +if not os.path.exists(core.config_path): + core.get_config() + core.write_config() + + +cm_global.register_extension('ComfyUI-Manager', + {'version': core.version, + 'name': 'ComfyUI Manager', + 'nodes': {'Terminal Log //CM'}, + 'description': 'It provides the ability to manage custom nodes in ComfyUI.', }) + diff --git a/custom_nodes/ComfyUI-Manager/glob/manager_util.py b/custom_nodes/ComfyUI-Manager/glob/manager_util.py new file mode 100644 index 000000000..5dc66b538 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/glob/manager_util.py @@ -0,0 +1,63 @@ +try: + from distutils.version import StrictVersion +except: + print(f"[ComfyUI-Manager] 'distutils' package not found. Activating fallback mode for compatibility.") + class StrictVersion: + def __init__(self, version_string): + self.version_string = version_string + self.major = 0 + self.minor = 0 + self.patch = 0 + self.pre_release = None + self.parse_version_string() + + def parse_version_string(self): + parts = self.version_string.split('.') + if not parts: + raise ValueError("Version string must not be empty") + + self.major = int(parts[0]) + self.minor = int(parts[1]) if len(parts) > 1 else 0 + self.patch = int(parts[2]) if len(parts) > 2 else 0 + + # Handling pre-release versions if present + if len(parts) > 3: + self.pre_release = parts[3] + + def __str__(self): + version = f"{self.major}.{self.minor}.{self.patch}" + if self.pre_release: + version += f"-{self.pre_release}" + return version + + def __eq__(self, other): + return (self.major, self.minor, self.patch, self.pre_release) == \ + (other.major, other.minor, other.patch, other.pre_release) + + def __lt__(self, other): + if (self.major, self.minor, self.patch) == (other.major, other.minor, other.patch): + return self.pre_release_compare(self.pre_release, other.pre_release) < 0 + return (self.major, self.minor, self.patch) < (other.major, other.minor, other.patch) + + @staticmethod + def pre_release_compare(pre1, pre2): + if pre1 == pre2: + return 0 + if pre1 is None: + return 1 + if pre2 is None: + return -1 + return -1 if pre1 < pre2 else 1 + + def __le__(self, other): + return self == other or self < other + + def __gt__(self, other): + return not self <= other + + def __ge__(self, other): + return not self < other + + def __ne__(self, other): + return not self == other + diff --git a/custom_nodes/ComfyUI-Manager/glob/security_check.py b/custom_nodes/ComfyUI-Manager/glob/security_check.py new file mode 100644 index 000000000..1c6fdf6fc --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/glob/security_check.py @@ -0,0 +1,80 @@ +import sys +import subprocess +import os + + +def security_check(): + print("[START] Security scan") + + custom_nodes_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) + comfyui_path = os.path.abspath(os.path.join(custom_nodes_path, '..')) + + guide = { + "ComfyUI_LLMVISION": """ +0.Remove ComfyUI\\custom_nodes\\ComfyUI_LLMVISION. +1.Remove pip packages: openai-1.16.3.dist-info, anthropic-0.21.4.dist-info, openai-1.30.2.dist-info, anthropic-0.26.1.dist-info, %LocalAppData%\\rundll64.exe + (For portable versions, it is recommended to reinstall. If you are using a venv, it is advised to recreate the venv.) +2.Remove these files in your system: lib/browser/admin.py, Cadmino.py, Fadmino.py, VISION-D.exe, BeamNG.UI.exe +3.Check your Windows registry for the key listed above and remove it. + (HKEY_CURRENT_USER\\Software\\OpenAICLI) +4.Run a malware scanner. +5.Change all of your passwords, everywhere. + +(Reinstall OS is recommended.) +\n +Detailed information: https://old.reddit.com/r/comfyui/comments/1dbls5n/psa_if_youve_used_the_comfyui_llmvision_node_from/ + """, + "lolMiner": """ +1. Remove pip packages: lolMiner* +2. Remove files: lolMiner*, 4G_Ethash_Linux_Readme.txt, mine* in ComfyUI dir. + +(Reinstall ComfyUI is recommended.) + """ + } + + node_blacklist = {"ComfyUI_LLMVISION": "ComfyUI_LLMVISION"} + + pip_blacklist = {"AppleBotzz": "ComfyUI_LLMVISION"} + + file_blacklist = { + "ComfyUI_LLMVISION": ["%LocalAppData%\\rundll64.exe"], + "lolMiner": [os.path.join(comfyui_path, 'lolMiner')] + } + + installed_pips = subprocess.check_output([sys.executable, '-m', "pip", "freeze"], text=True) + + detected = set() + for k, v in node_blacklist.items(): + if os.path.exists(os.path.join(custom_nodes_path, k)): + print(f"[SECURITY ALERT] custom node '{k}' is dangerous.") + detected.add(v) + + for k, v in pip_blacklist.items(): + if k in installed_pips: + detected.add(v) + break + + for k, v in file_blacklist.items(): + for x in v: + if os.path.exists(os.path.expandvars(x)): + detected.add(k) + break + + if len(detected) > 0: + for line in installed_pips.split('\n'): + for k, v in pip_blacklist.items(): + if k in line: + print(f"[SECURITY ALERT] '{line}' is dangerous.") + + print("\n########################################################################") + print(" Malware has been detected, forcibly terminating ComfyUI execution.") + print("########################################################################\n") + + for x in detected: + print(f"\n======== TARGET: {x} =========") + print(f"\nTODO:") + print(guide.get(x)) + + exit(-1) + + print("[DONE] Security scan") diff --git a/custom_nodes/ComfyUI-Manager/js/cm-api.js b/custom_nodes/ComfyUI-Manager/js/cm-api.js new file mode 100644 index 000000000..1a6309d38 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/cm-api.js @@ -0,0 +1,63 @@ +import { api } from "../../scripts/api.js"; +import { app } from "../../scripts/app.js"; +import { sleep } from "./common.js"; + +async function tryInstallCustomNode(event) { + let msg = '-= [ComfyUI Manager] extension installation request =-\n\n'; + msg += `The '${event.detail.sender}' extension requires the installation of the '${event.detail.title}' extension. `; + + if(event.detail.target.installed == 'Disabled') { + msg += 'However, the extension is currently disabled. Would you like to enable it and reboot?' + } + else if(event.detail.target.installed == 'True') { + msg += 'However, it seems that the extension is in an import-fail state or is not compatible with the current version. Please address this issue.'; + } + else { + msg += `Would you like to install it and reboot?`; + } + + msg += `\n\nRequest message:\n${event.detail.msg}`; + + if(event.detail.target.installed == 'True') { + alert(msg); + return; + } + + let res = confirm(msg); + if(res) { + if(event.detail.target.installed == 'Disabled') { + const response = await api.fetchApi(`/customnode/toggle_active`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(event.detail.target) + }); + } + else { + await sleep(300); + app.ui.dialog.show(`Installing... '${event.detail.target.title}'`); + + const response = await api.fetchApi(`/customnode/install`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(event.detail.target) + }); + + if(response.status == 403) { + show_message('This action is not allowed with this security level configuration.'); + return false; + } + } + + let response = await api.fetchApi("/manager/reboot"); + if(response.status == 403) { + show_message('This action is not allowed with this security level configuration.'); + return false; + } + + await sleep(300); + + app.ui.dialog.show(`Rebooting...`); + } +} + +api.addEventListener("cm-api-try-install-customnode", tryInstallCustomNode); diff --git a/custom_nodes/ComfyUI-Manager/js/comfyui-manager.js b/custom_nodes/ComfyUI-Manager/js/comfyui-manager.js new file mode 100644 index 000000000..ee825bdef --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/comfyui-manager.js @@ -0,0 +1,1513 @@ +import { api } from "../../scripts/api.js"; +import { app } from "../../scripts/app.js"; +import { $el, ComfyDialog } from "../../scripts/ui.js"; +import { + SUPPORTED_OUTPUT_NODE_TYPES, + ShareDialog, + ShareDialogChooser, + getPotentialOutputsAndOutputNodes, + showOpenArtShareDialog, + showShareDialog, + showYouMLShareDialog +} from "./comfyui-share-common.js"; +import { OpenArtShareDialog } from "./comfyui-share-openart.js"; +import { free_models, install_pip, install_via_git_url, manager_instance, rebootAPI, setManagerInstance, show_message } from "./common.js"; +import { ComponentBuilderDialog, getPureName, load_components, set_component_policy } from "./components-manager.js"; +import { CustomNodesManager } from "./custom-nodes-manager.js"; +import { ModelManager } from "./model-manager.js"; +import { set_double_click_policy } from "./node_fixer.js"; +import { SnapshotManager } from "./snapshot.js"; + +var docStyle = document.createElement('style'); +docStyle.innerHTML = ` +.comfy-toast { + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + background-color: rgba(0, 0, 0, 0.7); + color: white; + padding: 10px 20px; + border-radius: 5px; + z-index: 1000; + transition: opacity 0.5s; +} + +.comfy-toast-fadeout { + opacity: 0; +} + +#cm-manager-dialog { + width: 1000px; + height: 520px; + box-sizing: content-box; + z-index: 10000; + overflow-y: auto; +} + +.cb-widget { + width: 400px; + height: 25px; + box-sizing: border-box; + z-index: 10000; + margin-top: 10px; + margin-bottom: 5px; +} + +.cb-widget-input { + width: 305px; + height: 25px; + box-sizing: border-box; +} +.cb-widget-input:disabled { + background-color: #444444; + color: white; +} + +.cb-widget-input-label { + width: 90px; + height: 25px; + box-sizing: border-box; + color: white; + text-align: right; + display: inline-block; + margin-right: 5px; +} + +.cm-menu-container { + column-gap: 20px; + display: flex; + flex-wrap: wrap; + justify-content: center; + box-sizing: content-box; +} + +.cm-menu-column { + display: flex; + flex-direction: column; + flex: 1 1 auto; + width: 300px; + box-sizing: content-box; +} + +.cm-title { + background-color: black; + text-align: center; + height: 40px; + width: calc(100% - 10px); + font-weight: bold; + justify-content: center; + align-content: center; + vertical-align: middle; +} + +#cm-channel-badge { + color: white; + background-color: #AA0000; + width: 220px; + height: 23px; + font-size: 13px; + border-radius: 5px; + left: 5px; + top: 5px; + align-content: center; + justify-content: center; + text-align: center; + font-weight: bold; + float: left; + vertical-align: middle; + position: relative; +} + +#custom-nodes-grid a { + color: #5555FF; + font-weight: bold; + text-decoration: none; +} + +#custom-nodes-grid a:hover { + color: #7777FF; + text-decoration: underline; +} + +#external-models-grid a { + color: #5555FF; + font-weight: bold; + text-decoration: none; +} + +#external-models-grid a:hover { + color: #7777FF; + text-decoration: underline; +} + +#alternatives-grid a { + color: #5555FF; + font-weight: bold; + text-decoration: none; +} + +#alternatives-grid a:hover { + color: #7777FF; + text-decoration: underline; +} + +.cm-notice-board { + width: 290px; + height: 270px; + overflow: auto; + color: var(--input-text); + border: 1px solid var(--descrip-text); + padding: 5px 10px; + overflow-x: hidden; + box-sizing: content-box; +} + +.cm-notice-board > ul { + display: block; + list-style-type: disc; + margin-block-start: 1em; + margin-block-end: 1em; + margin-inline-start: 0px; + margin-inline-end: 0px; + padding-inline-start: 40px; +} + +.cm-conflicted-nodes-text { + background-color: #CCCC55 !important; + color: #AA3333 !important; + font-size: 10px; + border-radius: 5px; + padding: 10px; +} + +.cm-warn-note { + background-color: #101010 !important; + color: #FF3800 !important; + font-size: 13px; + border-radius: 5px; + padding: 10px; + overflow-x: hidden; + overflow: auto; +} + +.cm-info-note { + background-color: #101010 !important; + color: #FF3800 !important; + font-size: 13px; + border-radius: 5px; + padding: 10px; + overflow-x: hidden; + overflow: auto; +} +`; + +document.head.appendChild(docStyle); + +var update_comfyui_button = null; +var fetch_updates_button = null; +var update_all_button = null; +var badge_mode = "none"; +let share_option = 'all'; + +// copied style from https://github.com/pythongosssss/ComfyUI-Custom-Scripts +const style = ` +#workflowgallery-button { + width: 310px; + height: 27px; + padding: 0px !important; + position: relative; + overflow: hidden; + font-size: 17px !important; +} +#cm-nodeinfo-button { + width: 310px; + height: 27px; + padding: 0px !important; + position: relative; + overflow: hidden; + font-size: 17px !important; +} +#cm-manual-button { + width: 310px; + height: 27px; + position: relative; + overflow: hidden; +} + +.cm-button { + width: 310px; + height: 30px; + position: relative; + overflow: hidden; + font-size: 17px !important; +} + +.cm-button-red { + width: 310px; + height: 30px; + position: relative; + overflow: hidden; + font-size: 17px !important; + background-color: #500000 !important; + color: white !important; +} + +.cm-experimental-button { + width: 290px; + height: 30px; + position: relative; + overflow: hidden; + font-size: 17px !important; +} + +.cm-experimental { + width: 310px; + border: 1px solid #555; + border-radius: 5px; + padding: 10px; + align-items: center; + text-align: center; + justify-content: center; + box-sizing: border-box; +} + +.cm-experimental-legend { + margin-top: -20px; + margin-left: 50%; + width:auto; + height:20px; + font-size: 13px; + font-weight: bold; + background-color: #990000; + color: #CCFFFF; + border-radius: 5px; + text-align: center; + transform: translateX(-50%); + display: block; +} + +.cm-menu-combo { + cursor: pointer; + width: 310px; + box-sizing: border-box; +} + +.cm-small-button { + width: 120px; + height: 30px; + position: relative; + overflow: hidden; + box-sizing: border-box; + font-size: 17px !important; +} + +#cm-install-customnodes-button { + width: 200px; + height: 30px; + position: relative; + overflow: hidden; + box-sizing: border-box; + font-size: 17px !important; +} + +.cm-search-filter { + width: 200px; + height: 30px !important; + position: relative; + overflow: hidden; + box-sizing: border-box; +} + +.cb-node-label { + width: 400px; + height:28px; + color: black; + background-color: #777777; + font-size: 18px; + text-align: center; + font-weight: bold; +} + +#cm-close-button { + width: calc(100% - 65px); + bottom: 10px; + position: absolute; + overflow: hidden; +} + +#cm-save-button { + width: calc(100% - 65px); + bottom:40px; + position: absolute; + overflow: hidden; +} +#cm-save-button:disabled { + background-color: #444444; +} + +.pysssss-workflow-arrow-2 { + position: absolute; + top: 0; + bottom: 0; + right: 0; + font-size: 12px; + display: flex; + align-items: center; + width: 24px; + justify-content: center; + background: rgba(255,255,255,0.1); + content: "▼"; +} +.pysssss-workflow-arrow-2:after { + content: "▼"; + } + .pysssss-workflow-arrow-2:hover { + filter: brightness(1.6); + background-color: var(--comfy-menu-bg); + } +.pysssss-workflow-popup-2 ~ .litecontextmenu { + transform: scale(1.3); +} +#workflowgallery-button-menu { + z-index: 10000000000 !important; +} +#cm-manual-button-menu { + z-index: 10000000000 !important; +} +`; + + + +async function init_badge_mode() { + api.fetchApi('/manager/badge_mode') + .then(response => response.text()) + .then(data => { badge_mode = data; }) +} + +async function init_share_option() { + api.fetchApi('/manager/share_option') + .then(response => response.text()) + .then(data => { + share_option = data || 'all'; + }); +} + +async function init_notice(notice) { + api.fetchApi('/manager/notice') + .then(response => response.text()) + .then(data => { + notice.innerHTML = data; + }) +} + +await init_badge_mode(); +await init_share_option(); + +async function fetchNicknames() { + const response1 = await api.fetchApi(`/customnode/getmappings?mode=nickname`); + const mappings = await response1.json(); + + let result = {}; + let nickname_patterns = []; + + for (let i in mappings) { + let item = mappings[i]; + var nickname; + if (item[1].nickname) { + nickname = item[1].nickname; + } + else if (item[1].title) { + nickname = item[1].title; + } + else { + nickname = item[1].title_aux; + } + + for (let j in item[0]) { + result[item[0][j]] = nickname; + } + + if(item[1].nodename_pattern) { + nickname_patterns.push([item[1].nodename_pattern, nickname]); + } + } + + return [result, nickname_patterns]; +} + +const [nicknames, nickname_patterns] = await fetchNicknames(); + +function getNickname(node, nodename) { + if(node.nickname) { + return node.nickname; + } + else { + if (nicknames[nodename]) { + node.nickname = nicknames[nodename]; + } + else if(node.getInnerNodes) { + let pure_name = getPureName(node); + let groupNode = app.graph.extra?.groupNodes?.[pure_name]; + if(groupNode) { + let packname = groupNode.packname; + node.nickname = packname; + } + return node.nickname; + } + else { + for(let i in nickname_patterns) { + let item = nickname_patterns[i]; + if(nodename.match(item[0])) { + node.nickname = item[1]; + } + } + } + + return node.nickname; + } +} + +function drawBadge(node, orig, restArgs) { + let ctx = restArgs[0]; + const r = orig?.apply?.(node, restArgs); + + if (!node.flags.collapsed && badge_mode != 'none' && node.constructor.title_mode != LiteGraph.NO_TITLE) { + let text = ""; + if (badge_mode.startsWith('id_nick')) + text = `#${node.id} `; + + let nick = node.getNickname(); + if (nick) { + if (nick == 'ComfyUI') { + if(badge_mode.endsWith('hide')) { + nick = ""; + } + else { + nick = "🦊" + } + } + + if (nick.length > 25) { + text += nick.substring(0, 23) + ".."; + } + else { + text += nick; + } + } + + if (text != "") { + let fgColor = "white"; + let bgColor = "#0F1F0F"; + let visible = true; + + ctx.save(); + ctx.font = "12px sans-serif"; + const sz = ctx.measureText(text); + ctx.fillStyle = bgColor; + ctx.beginPath(); + ctx.roundRect(node.size[0] - sz.width - 12, -LiteGraph.NODE_TITLE_HEIGHT - 20, sz.width + 12, 20, 5); + ctx.fill(); + + ctx.fillStyle = fgColor; + ctx.fillText(text, node.size[0] - sz.width - 6, -LiteGraph.NODE_TITLE_HEIGHT - 6); + ctx.restore(); + + if (node.has_errors) { + ctx.save(); + ctx.font = "bold 14px sans-serif"; + const sz2 = ctx.measureText(node.type); + ctx.fillStyle = 'white'; + ctx.fillText(node.type, node.size[0] / 2 - sz2.width / 2, node.size[1] / 2); + ctx.restore(); + } + } + } + return r; +} + + +async function updateComfyUI() { + let prev_text = update_comfyui_button.innerText; + update_comfyui_button.innerText = "Updating ComfyUI..."; + update_comfyui_button.disabled = true; + update_comfyui_button.style.backgroundColor = "gray"; + + try { + const response = await api.fetchApi('/comfyui_manager/update_comfyui'); + + if (response.status == 400) { + show_message('Failed to update ComfyUI.'); + return false; + } + + if (response.status == 201) { + show_message('ComfyUI has been successfully updated.'); + } + else { + show_message('ComfyUI is already up to date with the latest version.'); + } + + return true; + } + catch (exception) { + show_message(`Failed to update ComfyUI / ${exception}`); + return false; + } + finally { + update_comfyui_button.disabled = false; + update_comfyui_button.innerText = prev_text; + update_comfyui_button.style.backgroundColor = ""; + } +} + +async function fetchUpdates(update_check_checkbox) { + let prev_text = fetch_updates_button.innerText; + fetch_updates_button.innerText = "Fetching updates..."; + fetch_updates_button.disabled = true; + fetch_updates_button.style.backgroundColor = "gray"; + + try { + var mode = manager_instance.datasrc_combo.value; + + const response = await api.fetchApi(`/customnode/fetch_updates?mode=${mode}`); + + if (response.status != 200 && response.status != 201) { + show_message('Failed to fetch updates.'); + return false; + } + + if (response.status == 201) { + show_message("There is an updated extension available.

NOTE:
Fetch Updates is not an update.
Please update from

"); + + const button = document.getElementById('cm-install-customnodes-button'); + button.addEventListener("click", + async function() { + app.ui.dialog.close(); + + if(!CustomNodesManager.instance) { + CustomNodesManager.instance = new CustomNodesManager(app, self); + } + await CustomNodesManager.instance.show(CustomNodesManager.ShowMode.UPDATE); + } + ); + + update_check_checkbox.checked = false; + } + else { + show_message('All extensions are already up-to-date with the latest versions.'); + } + + return true; + } + catch (exception) { + show_message(`Failed to update custom nodes / ${exception}`); + return false; + } + finally { + fetch_updates_button.disabled = false; + fetch_updates_button.innerText = prev_text; + fetch_updates_button.style.backgroundColor = ""; + } +} + +async function updateAll(update_check_checkbox, manager_dialog) { + let prev_text = update_all_button.innerText; + update_all_button.innerText = "Updating all...(ComfyUI)"; + update_all_button.disabled = true; + update_all_button.style.backgroundColor = "gray"; + + try { + var mode = manager_instance.datasrc_combo.value; + + update_all_button.innerText = "Updating all..."; + const response1 = await api.fetchApi('/comfyui_manager/update_comfyui'); + const response2 = await api.fetchApi(`/customnode/update_all?mode=${mode}`); + + if (response2.status == 403) { + show_message('This action is not allowed with this security level configuration.'); + return false; + } + + if (response1.status == 400 || response2.status == 400) { + show_message('Failed to update ComfyUI or several extensions.

See terminal log.
'); + return false; + } + + if(response1.status == 201 || response2.status == 201) { + const update_info = await response2.json(); + + let failed_list = ""; + if(update_info.failed.length > 0) { + failed_list = "
FAILED: "+update_info.failed.join(", "); + } + + let updated_list = ""; + if(update_info.updated.length > 0) { + updated_list = "
UPDATED: "+update_info.updated.join(", "); + } + + show_message( + "ComfyUI and all extensions have been updated to the latest version.
To apply the updated custom node, please ComfyUI. And refresh browser.
" + +failed_list + +updated_list + ); + + const rebootButton = document.getElementById('cm-reboot-button5'); + rebootButton.addEventListener("click", + function() { + if(rebootAPI()) { + manager_dialog.close(); + } + }); + } + else { + show_message('ComfyUI and all extensions are already up-to-date with the latest versions.'); + } + + return true; + } + catch (exception) { + show_message(`Failed to update ComfyUI or several extensions / ${exception}`); + return false; + } + finally { + update_all_button.disabled = false; + update_all_button.innerText = prev_text; + update_all_button.style.backgroundColor = ""; + } +} + +function newDOMTokenList(initialTokens) { + const tmp = document.createElement(`div`); + + const classList = tmp.classList; + if (initialTokens) { + initialTokens.forEach(token => { + classList.add(token); + }); + } + + return classList; + } + +/** + * Check whether the node is a potential output node (img, gif or video output) + */ +const isOutputNode = (node) => { + return SUPPORTED_OUTPUT_NODE_TYPES.includes(node.type); +} + +// ----------- +class ManagerMenuDialog extends ComfyDialog { + createControlsMid() { + let self = this; + + update_comfyui_button = + $el("button.cm-button", { + type: "button", + textContent: "Update ComfyUI", + onclick: + () => updateComfyUI() + }); + + fetch_updates_button = + $el("button.cm-button", { + type: "button", + textContent: "Fetch Updates", + onclick: + () => fetchUpdates(this.update_check_checkbox) + }); + + update_all_button = + $el("button.cm-button", { + type: "button", + textContent: "Update All", + onclick: + () => updateAll(this.update_check_checkbox, self) + }); + + const res = + [ + $el("button.cm-button", { + type: "button", + textContent: "Custom Nodes Manager", + onclick: + () => { + if(!CustomNodesManager.instance) { + CustomNodesManager.instance = new CustomNodesManager(app, self); + } + CustomNodesManager.instance.show(CustomNodesManager.ShowMode.NORMAL); + } + }), + + $el("button.cm-button", { + type: "button", + textContent: "Install Missing Custom Nodes", + onclick: + () => { + if(!CustomNodesManager.instance) { + CustomNodesManager.instance = new CustomNodesManager(app, self); + } + CustomNodesManager.instance.show(CustomNodesManager.ShowMode.MISSING); + } + }), + + + $el("button.cm-button", { + type: "button", + textContent: "Model Manager", + onclick: + () => { + if(!ModelManager.instance) { + ModelManager.instance = new ModelManager(app, self); + } + ModelManager.instance.show(); + } + }), + + $el("button.cm-button", { + type: "button", + textContent: "Install via Git URL", + onclick: () => { + var url = prompt("Please enter the URL of the Git repository to install", ""); + + if (url !== null) { + install_via_git_url(url, self); + } + } + }), + + $el("br", {}, []), + update_all_button, + update_comfyui_button, + fetch_updates_button, + + $el("br", {}, []), + $el("button.cm-button", { + type: "button", + textContent: "Alternatives of A1111", + onclick: + () => { + if(!CustomNodesManager.instance) { + CustomNodesManager.instance = new CustomNodesManager(app, self); + } + CustomNodesManager.instance.show(CustomNodesManager.ShowMode.ALTERNATIVES); + } + }), + + $el("br", {}, []), + $el("button.cm-button-red", { + type: "button", + textContent: "Restart", + onclick: () => rebootAPI() + }), + ]; + + return res; + } + + createControlsLeft() { + let self = this; + + this.update_check_checkbox = $el("input",{type:'checkbox', id:"skip_update_check"},[]) + const uc_checkbox_text = $el("label",{for:"skip_update_check"},[" Skip update check"]) + uc_checkbox_text.style.color = "var(--fg-color)"; + uc_checkbox_text.style.cursor = "pointer"; + this.update_check_checkbox.checked = true; + + // db mode + this.datasrc_combo = document.createElement("select"); + this.datasrc_combo.setAttribute("title", "Configure where to retrieve node/model information. If set to 'local,' the channel is ignored, and if set to 'channel (remote),' it fetches the latest information each time the list is opened."); + this.datasrc_combo.className = "cm-menu-combo"; + this.datasrc_combo.appendChild($el('option', { value: 'cache', text: 'DB: Channel (1day cache)' }, [])); + this.datasrc_combo.appendChild($el('option', { value: 'local', text: 'DB: Local' }, [])); + this.datasrc_combo.appendChild($el('option', { value: 'url', text: 'DB: Channel (remote)' }, [])); + + // preview method + let preview_combo = document.createElement("select"); + preview_combo.setAttribute("title", "Configure how latent variables will be decoded during preview in the sampling process."); + preview_combo.className = "cm-menu-combo"; + preview_combo.appendChild($el('option', { value: 'auto', text: 'Preview method: Auto' }, [])); + preview_combo.appendChild($el('option', { value: 'taesd', text: 'Preview method: TAESD (slow)' }, [])); + preview_combo.appendChild($el('option', { value: 'latent2rgb', text: 'Preview method: Latent2RGB (fast)' }, [])); + preview_combo.appendChild($el('option', { value: 'none', text: 'Preview method: None (very fast)' }, [])); + + api.fetchApi('/manager/preview_method') + .then(response => response.text()) + .then(data => { preview_combo.value = data; }); + + preview_combo.addEventListener('change', function (event) { + api.fetchApi(`/manager/preview_method?value=${event.target.value}`); + }); + + // nickname + let badge_combo = document.createElement("select"); + badge_combo.setAttribute("title", "Configure the content to be displayed on the badge at the top right corner of the node. The ID is the identifier of the node. If 'hide built-in' is selected, both unknown nodes and built-in nodes will be omitted, making them indistinguishable"); + badge_combo.className = "cm-menu-combo"; + badge_combo.appendChild($el('option', { value: 'none', text: 'Badge: None' }, [])); + badge_combo.appendChild($el('option', { value: 'nick', text: 'Badge: Nickname' }, [])); + badge_combo.appendChild($el('option', { value: 'nick_hide', text: 'Badge: Nickname (hide built-in)' }, [])); + badge_combo.appendChild($el('option', { value: 'id_nick', text: 'Badge: #ID Nickname' }, [])); + badge_combo.appendChild($el('option', { value: 'id_nick_hide', text: 'Badge: #ID Nickname (hide built-in)' }, [])); + + api.fetchApi('/manager/badge_mode') + .then(response => response.text()) + .then(data => { badge_combo.value = data; badge_mode = data; }); + + badge_combo.addEventListener('change', function (event) { + api.fetchApi(`/manager/badge_mode?value=${event.target.value}`); + badge_mode = event.target.value; + app.graph.setDirtyCanvas(true); + }); + + // channel + let channel_combo = document.createElement("select"); + channel_combo.setAttribute("title", "Configure the channel for retrieving data from the Custom Node list (including missing nodes) or the Model list. Note that the badge utilizes local information."); + channel_combo.className = "cm-menu-combo"; + api.fetchApi('/manager/channel_url_list') + .then(response => response.json()) + .then(async data => { + try { + let urls = data.list; + for (let i in urls) { + if (urls[i] != '') { + let name_url = urls[i].split('::'); + channel_combo.appendChild($el('option', { value: name_url[0], text: `Channel: ${name_url[0]}` }, [])); + } + } + + channel_combo.addEventListener('change', function (event) { + api.fetchApi(`/manager/channel_url_list?value=${event.target.value}`); + }); + + channel_combo.value = data.selected; + } + catch (exception) { + + } + }); + + // default ui state + let default_ui_combo = document.createElement("select"); + default_ui_combo.setAttribute("title", "Set the default state to be displayed in the main menu when the browser starts."); + default_ui_combo.className = "cm-menu-combo"; + default_ui_combo.appendChild($el('option', { value: 'none', text: 'Default UI: None' }, [])); + default_ui_combo.appendChild($el('option', { value: 'history', text: 'Default UI: History' }, [])); + default_ui_combo.appendChild($el('option', { value: 'queue', text: 'Default UI: Queue' }, [])); + api.fetchApi('/manager/default_ui') + .then(response => response.text()) + .then(data => { default_ui_combo.value = data; }); + + default_ui_combo.addEventListener('change', function (event) { + api.fetchApi(`/manager/default_ui?value=${event.target.value}`); + }); + + + // share + let share_combo = document.createElement("select"); + share_combo.setAttribute("title", "Hide the share button in the main menu or set the default action upon clicking it. Additionally, configure the default share site when sharing via the context menu's share button."); + share_combo.className = "cm-menu-combo"; + const share_options = [ + ['none', 'None'], + ['openart', 'OpenArt AI'], + ['youml', 'YouML'], + ['matrix', 'Matrix Server'], + ['comfyworkflows', 'ComfyWorkflows'], + ['copus', 'Copus'], + ['all', 'All'], + ]; + for (const option of share_options) { + share_combo.appendChild($el('option', { value: option[0], text: `Share: ${option[1]}` }, [])); + } + + // default ui state + let component_policy_combo = document.createElement("select"); + component_policy_combo.setAttribute("title", "When loading the workflow, configure which version of the component to use."); + component_policy_combo.className = "cm-menu-combo"; + component_policy_combo.appendChild($el('option', { value: 'workflow', text: 'Component: Use workflow version' }, [])); + component_policy_combo.appendChild($el('option', { value: 'higher', text: 'Component: Use higher version' }, [])); + component_policy_combo.appendChild($el('option', { value: 'mine', text: 'Component: Use my version' }, [])); + api.fetchApi('/manager/component/policy') + .then(response => response.text()) + .then(data => { + component_policy_combo.value = data; + set_component_policy(data); + }); + + component_policy_combo.addEventListener('change', function (event) { + api.fetchApi(`/manager/component/policy?value=${event.target.value}`); + set_component_policy(event.target.value); + }); + + let dbl_click_policy_combo = document.createElement("select"); + dbl_click_policy_combo.setAttribute("title", "Sets the behavior when you double-click the title area of a node."); + dbl_click_policy_combo.className = "cm-menu-combo"; + dbl_click_policy_combo.appendChild($el('option', { value: 'none', text: 'Double-Click: None' }, [])); + dbl_click_policy_combo.appendChild($el('option', { value: 'copy-all', text: 'Double-Click: Copy All Connections' }, [])); + dbl_click_policy_combo.appendChild($el('option', { value: 'copy-input', text: 'Double-Click: Copy Input Connections' }, [])); + dbl_click_policy_combo.appendChild($el('option', { value: 'possible-input', text: 'Double-Click: Possible Input Connections' }, [])); + dbl_click_policy_combo.appendChild($el('option', { value: 'dual', text: 'Double-Click: Possible(left) + Copy(right)' }, [])); + + api.fetchApi('/manager/dbl_click/policy') + .then(response => response.text()) + .then(data => { + dbl_click_policy_combo.value = data; + set_double_click_policy(data); + }); + + dbl_click_policy_combo.addEventListener('change', function (event) { + api.fetchApi(`/manager/dbl_click/policy?value=${event.target.value}`); + set_double_click_policy(event.target.value); + }); + + api.fetchApi('/manager/share_option') + .then(response => response.text()) + .then(data => { + share_combo.value = data || 'all'; + share_option = data || 'all'; + }); + + share_combo.addEventListener('change', function (event) { + const value = event.target.value; + share_option = value; + api.fetchApi(`/manager/share_option?value=${value}`); + const shareButton = document.getElementById("shareButton"); + if (value === 'none') { + shareButton.style.display = "none"; + } else { + shareButton.style.display = "inline-block"; + } + }); + + return [ + $el("div", {}, [this.update_check_checkbox, uc_checkbox_text]), + $el("br", {}, []), + this.datasrc_combo, + channel_combo, + preview_combo, + badge_combo, + default_ui_combo, + share_combo, + component_policy_combo, + dbl_click_policy_combo, + $el("br", {}, []), + + $el("br", {}, []), + $el("filedset.cm-experimental", {}, [ + $el("legend.cm-experimental-legend", {}, ["EXPERIMENTAL"]), + $el("button.cm-experimental-button", { + type: "button", + textContent: "Snapshot Manager", + onclick: + () => { + if(!SnapshotManager.instance) + SnapshotManager.instance = new SnapshotManager(app, self); + SnapshotManager.instance.show(); + } + }), + $el("button.cm-experimental-button", { + type: "button", + textContent: "Install PIP packages", + onclick: + () => { + var url = prompt("Please enumerate the pip packages to be installed.\n\nExample: insightface opencv-python-headless>=4.1.1\n", ""); + + if (url !== null) { + install_pip(url, self); + } + } + }), + $el("button.cm-experimental-button", { + type: "button", + textContent: "Unload models", + onclick: () => { free_models(); } + }) + ]), + ]; + } + + createControlsRight() { + const elts = [ + $el("button.cm-button", { + id: 'cm-manual-button', + type: "button", + textContent: "Community Manual", + onclick: () => { window.open("https://blenderneko.github.io/ComfyUI-docs/", "comfyui-community-manual"); } + }, [ + $el("div.pysssss-workflow-arrow-2", { + id: `cm-manual-button-arrow`, + onclick: (e) => { + e.preventDefault(); + e.stopPropagation(); + + LiteGraph.closeAllContextMenus(); + const menu = new LiteGraph.ContextMenu( + [ + { + title: "Comfy Custom Node How To", + callback: () => { window.open("https://github.com/chrisgoringe/Comfy-Custom-Node-How-To/wiki/aaa_index", "comfyui-community-manual1"); }, + }, + { + title: "ComfyUI Guide To Making Custom Nodes", + callback: () => { window.open("https://github.com/Suzie1/ComfyUI_Guide_To_Making_Custom_Nodes/wiki", "comfyui-community-manual2"); }, + }, + { + title: "ComfyUI Examples", + callback: () => { window.open("https://comfyanonymous.github.io/ComfyUI_examples", "comfyui-community-manual3"); }, + }, + { + title: "Close", + callback: () => { + LiteGraph.closeAllContextMenus(); + }, + } + ], + { + event: e, + scale: 1.3, + }, + window + ); + // set the id so that we can override the context menu's z-index to be above the comfyui manager menu + menu.root.id = "cm-manual-button-menu"; + menu.root.classList.add("pysssss-workflow-popup-2"); + }, + }) + ]), + + $el("button", { + id: 'workflowgallery-button', + type: "button", + style: { + ...(localStorage.getItem("wg_last_visited") ? {height: '50px'} : {}) + }, + onclick: (e) => { + const last_visited_site = localStorage.getItem("wg_last_visited") + if (!!last_visited_site) { + window.open(last_visited_site, last_visited_site); + } else { + this.handleWorkflowGalleryButtonClick(e) + } + }, + }, [ + $el("p", { + textContent: 'Workflow Gallery', + style: { + 'text-align': 'center', + 'color': 'white', + 'font-size': '18px', + 'margin': 0, + 'padding': 0, + } + }, [ + $el("p", { + id: 'workflowgallery-button-last-visited-label', + textContent: `(${localStorage.getItem("wg_last_visited") ? localStorage.getItem("wg_last_visited").split('/')[2] : ''})`, + style: { + 'text-align': 'center', + 'color': 'white', + 'font-size': '12px', + 'margin': 0, + 'padding': 0, + } + }) + ]), + $el("div.pysssss-workflow-arrow-2", { + id: `comfyworkflows-button-arrow`, + onclick: this.handleWorkflowGalleryButtonClick + }) + ]), + + $el("button.cm-button", { + id: 'cm-nodeinfo-button', + type: "button", + textContent: "Nodes Info", + onclick: () => { window.open("https://ltdrdata.github.io/", "comfyui-node-info"); } + }), + $el("br", {}, []), + ]; + + var textarea = document.createElement("div"); + textarea.className = "cm-notice-board"; + elts.push(textarea); + + init_notice(textarea); + + return elts; + } + + constructor() { + super(); + + const close_button = $el("button", { id: "cm-close-button", type: "button", textContent: "Close", onclick: () => this.close() }); + + const content = + $el("div.comfy-modal-content", + [ + $el("tr.cm-title", {}, [ + $el("font", {size:6, color:"white"}, [`ComfyUI Manager Menu`])] + ), + $el("br", {}, []), + $el("div.cm-menu-container", + [ + $el("div.cm-menu-column", [...this.createControlsLeft()]), + $el("div.cm-menu-column", [...this.createControlsMid()]), + $el("div.cm-menu-column", [...this.createControlsRight()]) + ]), + + $el("br", {}, []), + close_button, + ] + ); + + content.style.width = '100%'; + content.style.height = '100%'; + + this.element = $el("div.comfy-modal", { id:'cm-manager-dialog', parent: document.body }, [ content ]); + } + + show() { + this.element.style.display = "block"; + } + + handleWorkflowGalleryButtonClick(e) { + e.preventDefault(); + e.stopPropagation(); + LiteGraph.closeAllContextMenus(); + + // Modify the style of the button so that the UI can indicate the last + // visited site right away. + const modifyButtonStyle = (url) => { + const workflowGalleryButton = document.getElementById('workflowgallery-button'); + workflowGalleryButton.style.height = '50px'; + const lastVisitedLabel = document.getElementById('workflowgallery-button-last-visited-label'); + lastVisitedLabel.textContent = `(${url.split('/')[2]})`; + } + + const menu = new LiteGraph.ContextMenu( + [ + { + title: "Share your art", + callback: () => { + if (share_option === 'openart') { + showOpenArtShareDialog(); + return; + } else if (share_option === 'matrix' || share_option === 'comfyworkflows') { + showShareDialog(share_option); + return; + } else if (share_option === 'youml') { + showYouMLShareDialog(); + return; + } + + if (!ShareDialogChooser.instance) { + ShareDialogChooser.instance = new ShareDialogChooser(); + } + ShareDialogChooser.instance.show(); + }, + }, + { + title: "Open 'openart.ai'", + callback: () => { + const url = "https://openart.ai/workflows/dev"; + localStorage.setItem("wg_last_visited", url); + window.open(url, url); + modifyButtonStyle(url); + }, + }, + { + title: "Open 'youml.com'", + callback: () => { + const url = "https://youml.com/?from=comfyui-share"; + localStorage.setItem("wg_last_visited", url); + window.open(url, url); + modifyButtonStyle(url); + }, + }, + { + title: "Open 'comfyworkflows.com'", + callback: () => { + const url = "https://comfyworkflows.com/"; + localStorage.setItem("wg_last_visited", url); + window.open(url, url); + modifyButtonStyle(url); + }, + }, + { + title: "Open 'flowt.ai'", + callback: () => { + const url = "https://flowt.ai/"; + localStorage.setItem("wg_last_visited", url); + window.open(url, url); + modifyButtonStyle(url); + }, + }, + { + title: "Open 'esheep'", + callback: () => { + const url = "https://www.esheep.com"; + localStorage.setItem("wg_last_visited", url); + window.open(url, url); + modifyButtonStyle(url); + }, + }, + { + title: "Open 'Copus.io'", + callback: () => { + const url = "https://www.copus.io"; + localStorage.setItem("wg_last_visited", url); + window.open(url, url); + modifyButtonStyle(url); + }, + }, + { + title: "Close", + callback: () => { + LiteGraph.closeAllContextMenus(); + }, + } + ], + { + event: e, + scale: 1.3, + }, + window + ); + // set the id so that we can override the context menu's z-index to be above the comfyui manager menu + menu.root.id = "workflowgallery-button-menu"; + menu.root.classList.add("pysssss-workflow-popup-2"); + } +} + + +app.registerExtension({ + name: "Comfy.ManagerMenu", + init() { + $el("style", { + textContent: style, + parent: document.head, + }); + }, + async setup() { + let orig_clear = app.graph.clear; + app.graph.clear = function () { + orig_clear.call(app.graph); + load_components(); + }; + + load_components(); + + const menu = document.querySelector(".comfy-menu"); + const separator = document.createElement("hr"); + + separator.style.margin = "20px 0"; + separator.style.width = "100%"; + menu.append(separator); + + try { + // new style Manager buttons + + // unload models button into new style Manager button + let cmGroup = new (await import("../../scripts/ui/components/buttonGroup.js")).ComfyButtonGroup( + new(await import("../../scripts/ui/components/button.js")).ComfyButton({ + icon: "puzzle", + action: () => { + if(!manager_instance) + setManagerInstance(new ManagerMenuDialog()); + manager_instance.show(); + }, + tooltip: "ComfyUI Manager", + content: "Manager", + classList: "comfyui-button comfyui-menu-mobile-collapse primary" + }).element, + new(await import("../../scripts/ui/components/button.js")).ComfyButton({ + icon: "vacuum-outline", + action: () => { + free_models(); + }, + tooltip: "Unload Models" + }).element, + new(await import("../../scripts/ui/components/button.js")).ComfyButton({ + icon: "vacuum", + action: () => { + free_models(true); + }, + tooltip: "Free model and node cache" + }).element, + new(await import("../../scripts/ui/components/button.js")).ComfyButton({ + icon: "share", + action: () => { + if (share_option === 'openart') { + showOpenArtShareDialog(); + return; + } else if (share_option === 'matrix' || share_option === 'comfyworkflows') { + showShareDialog(share_option); + return; + } else if (share_option === 'youml') { + showYouMLShareDialog(); + return; + } + + if(!ShareDialogChooser.instance) { + ShareDialogChooser.instance = new ShareDialogChooser(); + } + ShareDialogChooser.instance.show(); + }, + tooltip: "Share" + }).element + ); + + app.menu?.settingsGroup.element.before(cmGroup.element); + } + catch(exception) { + console.log('ComfyUI is outdated. New style menu based features are disabled.'); + } + + // old style Manager button + const managerButton = document.createElement("button"); + managerButton.textContent = "Manager"; + managerButton.onclick = () => { + if(!manager_instance) + setManagerInstance(new ManagerMenuDialog()); + manager_instance.show(); + } + menu.append(managerButton); + + const shareButton = document.createElement("button"); + shareButton.id = "shareButton"; + shareButton.textContent = "Share"; + shareButton.onclick = () => { + if (share_option === 'openart') { + showOpenArtShareDialog(); + return; + } else if (share_option === 'matrix' || share_option === 'comfyworkflows') { + showShareDialog(share_option); + return; + } else if (share_option === 'youml') { + showYouMLShareDialog(); + return; + } + + if(!ShareDialogChooser.instance) { + ShareDialogChooser.instance = new ShareDialogChooser(); + } + ShareDialogChooser.instance.show(); + } + // make the background color a gradient of blue to green + shareButton.style.background = "linear-gradient(90deg, #00C9FF 0%, #92FE9D 100%)"; + shareButton.style.color = "black"; + + // Load share option from local storage to determine whether to show + // the share button. + const shouldShowShareButton = share_option !== 'none'; + shareButton.style.display = shouldShowShareButton ? "inline-block" : "none"; + + menu.append(shareButton); + }, + + async beforeRegisterNodeDef(nodeType, nodeData, app) { + this._addExtraNodeContextMenu(nodeType, app); + }, + + async nodeCreated(node, app) { + if(!node.badge_enabled) { + node.getNickname = function () { return getNickname(node, node.comfyClass.trim()) }; + let orig = node.onDrawForeground; + if(!orig) + orig = node.__proto__.onDrawForeground; + + node.onDrawForeground = function (ctx) { + drawBadge(node, orig, arguments) + }; + node.badge_enabled = true; + } + }, + + async loadedGraphNode(node, app) { + if(!node.badge_enabled) { + const orig = node.onDrawForeground; + node.getNickname = function () { return getNickname(node, node.type.trim()) }; + node.onDrawForeground = function (ctx) { drawBadge(node, orig, arguments) }; + } + }, + + _addExtraNodeContextMenu(node, app) { + const origGetExtraMenuOptions = node.prototype.getExtraMenuOptions; + node.prototype.cm_menu_added = true; + node.prototype.getExtraMenuOptions = function (_, options) { + origGetExtraMenuOptions?.apply?.(this, arguments); + + if (node.category.startsWith('group nodes/')) { + options.push({ + content: "Save As Component", + callback: (obj) => { + if (!ComponentBuilderDialog.instance) { + ComponentBuilderDialog.instance = new ComponentBuilderDialog(); + } + ComponentBuilderDialog.instance.target_node = node; + ComponentBuilderDialog.instance.show(); + } + }, null); + } + + if (isOutputNode(node)) { + const { potential_outputs } = getPotentialOutputsAndOutputNodes([this]); + const hasOutput = potential_outputs.length > 0; + + // Check if the previous menu option is `null`. If it's not, + // then we need to add a `null` as a separator. + if (options[options.length - 1] !== null) { + options.push(null); + } + + options.push({ + content: "🏞️ Share Output", + disabled: !hasOutput, + callback: (obj) => { + if (!ShareDialog.instance) { + ShareDialog.instance = new ShareDialog(); + } + const shareButton = document.getElementById("shareButton"); + if (shareButton) { + const currentNode = this; + if (!OpenArtShareDialog.instance) { + OpenArtShareDialog.instance = new OpenArtShareDialog(); + } + OpenArtShareDialog.instance.selectedNodeId = currentNode.id; + if (!ShareDialog.instance) { + ShareDialog.instance = new ShareDialog(share_option); + } + ShareDialog.instance.selectedNodeId = currentNode.id; + shareButton.click(); + } + } + }, null); + } + } + }, +}); + + +async function set_default_ui() +{ + let res = await api.fetchApi('/manager/default_ui'); + if(res.status == 200) { + let mode = await res.text(); + switch(mode) { + case 'history': + app.ui.queue.hide(); + app.ui.history.show(); + break; + case 'queue': + app.ui.queue.show(); + app.ui.history.hide(); + break; + default: + // do nothing + break; + } + } +} + +set_default_ui(); \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/js/comfyui-share-common.js b/custom_nodes/ComfyUI-Manager/js/comfyui-share-common.js new file mode 100644 index 000000000..1fbf0485b --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/comfyui-share-common.js @@ -0,0 +1,1064 @@ +import { api } from "../../scripts/api.js"; +import { app } from "../../scripts/app.js"; +import { $el, ComfyDialog } from "../../scripts/ui.js"; +import { CopusShareDialog } from "./comfyui-share-copus.js"; +import { OpenArtShareDialog } from "./comfyui-share-openart.js"; +import { YouMLShareDialog } from "./comfyui-share-youml.js"; + +export const SUPPORTED_OUTPUT_NODE_TYPES = [ + "PreviewImage", + "SaveImage", + "VHS_VideoCombine", + "ADE_AnimateDiffCombine", + "SaveAnimatedWEBP", + "CR Image Output" +] + +var docStyle = document.createElement('style'); +docStyle.innerHTML = ` +.cm-menu-container { + column-gap: 20px; + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.cm-menu-column { + display: flex; + flex-direction: column; +} + +.cm-title { + padding: 10px 10px 0 10p; + background-color: black; + text-align: center; + height: 45px; +} +`; +document.head.appendChild(docStyle); + +export function getPotentialOutputsAndOutputNodes(nodes) { + const potential_outputs = []; + const potential_output_nodes = []; + + // iterate over the array of nodes to find the ones that are marked as SaveImage + // TODO: Add support for AnimateDiffCombine, etc. nodes that save videos/gifs, etc. + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + if (!SUPPORTED_OUTPUT_NODE_TYPES.includes(node.type)) { + continue; + } + + if (node.type === "SaveImage" || node.type === "CR Image Output") { + // check if node has an 'images' array property + if (node.hasOwnProperty("images") && Array.isArray(node.images)) { + // iterate over the images array and add each image to the potential_outputs array + for (let j = 0; j < node.images.length; j++) { + potential_output_nodes.push(node); + potential_outputs.push({ "type": "image", "image": node.images[j], "title": node.title, "node_id": node.id }); + } + } + } + else if (node.type === "PreviewImage") { + // check if node has an 'images' array property + if (node.hasOwnProperty("images") && Array.isArray(node.images)) { + // iterate over the images array and add each image to the potential_outputs array + for (let j = 0; j < node.images.length; j++) { + potential_output_nodes.push(node); + potential_outputs.push({ "type": "image", "image": node.images[j], "title": node.title, "node_id": node.id }); + } + } + } + else if (node.type === "VHS_VideoCombine") { + // check if node has a 'widgets' array property, with type 'image' + if (node.hasOwnProperty("widgets") && Array.isArray(node.widgets)) { + // iterate over the widgets array and add each image to the potential_outputs array + for (let j = 0; j < node.widgets.length; j++) { + if (node.widgets[j].type === "image") { + const widgetValue = node.widgets[j].value; + const parsedURLVals = parseURLPath(widgetValue); + + // ensure that the parsedURLVals have 'filename', 'subfolder', 'type', and 'format' properties + if (parsedURLVals.hasOwnProperty("filename") && parsedURLVals.hasOwnProperty("subfolder") && parsedURLVals.hasOwnProperty("type") && parsedURLVals.hasOwnProperty("format")) { + if (parsedURLVals.type !== "output") { + // TODO + } + potential_output_nodes.push(node); + potential_outputs.push({ "type": "output", 'title': node.title, "node_id": node.id , "output": { "filename": parsedURLVals.filename, "subfolder": parsedURLVals.subfolder, "value": widgetValue, "format": parsedURLVals.format } }); + } + } else if (node.widgets[j].type === "preview") { + const widgetValue = node.widgets[j].value; + const parsedURLVals = widgetValue.params; + + if(!parsedURLVals.format?.startsWith('image')) { + // video isn't supported format + continue; + } + + // ensure that the parsedURLVals have 'filename', 'subfolder', 'type', and 'format' properties + if (parsedURLVals.hasOwnProperty("filename") && parsedURLVals.hasOwnProperty("subfolder") && parsedURLVals.hasOwnProperty("type") && parsedURLVals.hasOwnProperty("format")) { + if (parsedURLVals.type !== "output") { + // TODO + } + potential_output_nodes.push(node); + potential_outputs.push({ "type": "output", 'title': node.title, "node_id": node.id , "output": { "filename": parsedURLVals.filename, "subfolder": parsedURLVals.subfolder, "value": `/view?filename=${parsedURLVals.filename}&subfolder=${parsedURLVals.subfolder}&type=${parsedURLVals.type}&format=${parsedURLVals.format}`, "format": parsedURLVals.format } }); + } + } + } + } + } + else if (node.type === "ADE_AnimateDiffCombine") { + // check if node has a 'widgets' array property, with type 'image' + if (node.hasOwnProperty("widgets") && Array.isArray(node.widgets)) { + // iterate over the widgets array and add each image to the potential_outputs array + for (let j = 0; j < node.widgets.length; j++) { + if (node.widgets[j].type === "image") { + const widgetValue = node.widgets[j].value; + const parsedURLVals = parseURLPath(widgetValue); + // ensure that the parsedURLVals have 'filename', 'subfolder', 'type', and 'format' properties + if (parsedURLVals.hasOwnProperty("filename") && parsedURLVals.hasOwnProperty("subfolder") && parsedURLVals.hasOwnProperty("type") && parsedURLVals.hasOwnProperty("format")) { + if (parsedURLVals.type !== "output") { + // TODO + continue; + } + potential_output_nodes.push(node); + potential_outputs.push({ "type": "output", 'title': node.title, "output": { "filename": parsedURLVals.filename, "subfolder": parsedURLVals.subfolder, "type": parsedURLVals.type, "value": widgetValue, "format": parsedURLVals.format } }); + } + } + } + } + } + else if (node.type === "SaveAnimatedWEBP") { + // check if node has an 'images' array property + if (node.hasOwnProperty("images") && Array.isArray(node.images)) { + // iterate over the images array and add each image to the potential_outputs array + for (let j = 0; j < node.images.length; j++) { + potential_output_nodes.push(node); + potential_outputs.push({ "type": "image", "image": node.images[j], "title": node.title }); + } + } + } + } + + // Note: make sure that two arrays are the same length + return { potential_outputs, potential_output_nodes }; +} + + +export function parseURLPath(urlPath) { + // Extract the query string from the URL path + var queryString = urlPath.split('?')[1]; + + // Use the URLSearchParams API to parse the query string + var params = new URLSearchParams(queryString); + + // Create an object to store the parsed parameters + var parsedParams = {}; + + // Iterate over each parameter and add it to the object + for (var pair of params.entries()) { + parsedParams[pair[0]] = pair[1]; + } + + // Return the object with the parsed parameters + return parsedParams; +} + + +export const shareToEsheep= () => { + app.graphToPrompt() + .then(prompt => { + const nodes = app.graph._nodes + const { potential_outputs, potential_output_nodes } = getPotentialOutputsAndOutputNodes(nodes); + const workflow = prompt['workflow'] + api.fetchApi(`/manager/set_esheep_workflow_and_images`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + workflow: workflow, + images: potential_outputs + }) + }).then(response => { + var domain = window.location.hostname; + var port = window.location.port; + port = port || (window.location.protocol === 'http:' ? '80' : window.location.protocol === 'https:' ? '443' : ''); + var full_domin = domain + ':' + port + window.open('https://www.esheep.com/app/workflow_upload?from_local='+ full_domin, '_blank'); + }); + }) +} + +export const showCopusShareDialog = () => { + if (!CopusShareDialog.instance) { + CopusShareDialog.instance = new CopusShareDialog(); + } + + return app.graphToPrompt() + .then(prompt => { + return app.graph._nodes; + }) + .then(nodes => { + const { potential_outputs, potential_output_nodes } = getPotentialOutputsAndOutputNodes(nodes); + CopusShareDialog.instance.show({ potential_outputs, potential_output_nodes}); + }) +} + +export const showOpenArtShareDialog = () => { + if (!OpenArtShareDialog.instance) { + OpenArtShareDialog.instance = new OpenArtShareDialog(); + } + + return app.graphToPrompt() + .then(prompt => { + // console.log({ prompt }) + return app.graph._nodes; + }) + .then(nodes => { + const { potential_outputs, potential_output_nodes } = getPotentialOutputsAndOutputNodes(nodes); + OpenArtShareDialog.instance.show({ potential_outputs, potential_output_nodes}); + }) +} + + +export const showYouMLShareDialog = () => { + if (!YouMLShareDialog.instance) { + YouMLShareDialog.instance = new YouMLShareDialog(); + } + + return app.graphToPrompt() + .then(prompt => { + return app.graph._nodes; + }) + .then(nodes => { + const { potential_outputs, potential_output_nodes } = getPotentialOutputsAndOutputNodes(nodes); + YouMLShareDialog.instance.show(potential_outputs, potential_output_nodes); + }) +} + + +export const showShareDialog = async (share_option) => { + if (!ShareDialog.instance) { + ShareDialog.instance = new ShareDialog(share_option); + } + return app.graphToPrompt() + .then(prompt => { + // console.log({ prompt }) + return app.graph._nodes; + }) + .then(nodes => { + // console.log({ nodes }); + const { potential_outputs, potential_output_nodes } = getPotentialOutputsAndOutputNodes(nodes); + if (potential_outputs.length === 0) { + if (potential_output_nodes.length === 0) { + // todo: add support for other output node types (animatediff combine, etc.) + const supported_nodes_string = SUPPORTED_OUTPUT_NODE_TYPES.join(", "); + alert(`No supported output node found (${supported_nodes_string}). To share this workflow, please add an output node to your graph and re-run your prompt.`); + } else { + alert("To share this, first run a prompt. Once it's done, click 'Share'.\n\nNOTE: Images of the Share target can only be selected in the PreviewImage, SaveImage, and VHS_VideoCombine nodes. In the case of VHS_VideoCombine, only the image/gif and image/webp formats are supported."); + } + return false; + } + ShareDialog.instance.show({ potential_outputs, potential_output_nodes, share_option }); + return true; + }); +} + +export class ShareDialogChooser extends ComfyDialog { + static instance = null; + constructor() { + super(); + this.element = $el("div.comfy-modal", { + parent: document.body, style: { + 'overflow-y': "auto", + } + }, + [$el("div.comfy-modal-content", + {}, + [...this.createButtons()]), + ]); + this.selectedNodeId = null; + } + createButtons() { + const buttons = [ + { + key: "openart", + textContent: "OpenArt AI", + website: "https://openart.ai/workflows/", + description: "Share ComfyUI workflows and art on OpenArt.ai", + onclick: () => { + showOpenArtShareDialog(); + this.close(); + } + }, + { + key: "youml", + textContent: "YouML", + website: "https://youml.com", + description: "Share your workflow or transform it into an interactive app on YouML.com", + onclick: () => { + showYouMLShareDialog(); + this.close(); + } + }, + { + key: "matrix", + textContent: "Matrix Server", + website: "https://app.element.io/#/room/%23comfyui_space%3Amatrix.org", + description: "Share your art on the official ComfyUI matrix server", + onclick: async () => { + showShareDialog('matrix').then((suc) => { + suc && this.close(); + }) + } + }, + { + key: "comfyworkflows", + textContent: "ComfyWorkflows", + website: "https://comfyworkflows.com", + description: "Share & browse thousands of ComfyUI workflows and art 🎨

ComfyWorkflows.com", + onclick: () => { + showShareDialog('comfyworkflows').then((suc) => { + suc && this.close(); + }) + } + }, + { + key: "esheep", + textContent: "eSheep", + website: "https://www.esheep.com", + description: "Share & download thousands of ComfyUI workflows on esheep.com", + onclick: () => { + shareToEsheep(); + this.close(); + } + }, + { + key: "Copus", + textContent: "Copus", + website: "https://www.copus.io", + description: "🔴 Permanently store and secure ownership of your workflow on the open-source platform: Copus.io", + onclick: () => { + showCopusShareDialog(); + this.close(); + } + }, + ]; + + function createShareButtonsWithDescriptions() { + // Responsive container + const container = $el("div", { + style: { + display: "flex", + 'flex-wrap': 'wrap', + 'justify-content': 'space-around', + 'padding': '10px', + } + }); + + buttons.forEach(b => { + const button = $el("button", { + type: "button", + textContent: b.textContent, + onclick: b.onclick, + style: { + 'width': '25%', + 'minWidth': '200px', + 'background-color': b.backgroundColor || '', + 'border-radius': '5px', + 'cursor': 'pointer', + 'padding': '5px 5px', + 'margin-bottom': '5px', + 'transition': 'background-color 0.3s', + } + }); + button.addEventListener('mouseover', () => { + button.style.backgroundColor = '#007BFF'; // Change color on hover + }); + button.addEventListener('mouseout', () => { + button.style.backgroundColor = b.backgroundColor || ''; + }); + + const description = $el("p", { + innerHTML: b.description, + style: { + 'text-align': 'left', + color: 'white', + 'font-size': '14px', + 'margin-bottom': '0', + }, + }); + + const websiteLink = $el("a", { + textContent: "🌐 Website", + href: b.website, + target: "_blank", + style: { + color: 'white', + 'margin-left': '10px', + 'font-size': '12px', + 'text-decoration': 'none', + 'align-self': 'center', + }, + }); + + // Add highlight to the website link + websiteLink.addEventListener('mouseover', () => { + websiteLink.style.opacity = '0.7'; + }); + + websiteLink.addEventListener('mouseout', () => { + websiteLink.style.opacity = '1'; + }); + + const buttonLinkContainer = $el("div", { + style: { + display: 'flex', + 'align-items': 'center', + 'margin-bottom': '10px', + } + }, [button, websiteLink]); + + const column = $el("div", { + style: { + 'flex-basis': '100%', + 'margin': '10px', + 'padding': '10px 20px', + 'border': '1px solid #ddd', + 'border-radius': '5px', + 'box-shadow': '0 2px 4px rgba(0, 0, 0, 0.1)', + } + }, [buttonLinkContainer, description]); + + container.appendChild(column); + }); + + return container; + } + + return [ + $el("p", { + textContent: 'Choose a platform to share your workflow', + style: { + 'text-align': 'center', + 'color': 'white', + 'font-size': '18px', + 'margin-bottom': '10px', + }, + } + ), + + $el("div.cm-menu-container", { + id: "comfyui-share-container" + }, [ + $el("div.cm-menu-column", [ + createShareButtonsWithDescriptions(), + $el("br", {}, []), + ]), + ]), + $el("div.cm-menu-container", { + id: "comfyui-share-container" + }, [ + $el("button", { + type: "button", + style: { + margin: "0 25px", + width: "100%", + }, + textContent: "Close", + onclick: () => { + this.close() + } + }), + $el("br", {}, []), + ]), + ]; + } + show() { + this.element.style.display = "block"; + this.element.style.zIndex = 10001; + } +} +export class ShareDialog extends ComfyDialog { + static instance = null; + static matrix_auth = { homeserver: "matrix.org", username: "", password: "" }; + static cw_sharekey = ""; + + constructor(share_option) { + super(); + this.share_option = share_option; + this.element = $el("div.comfy-modal", { + parent: document.body, style: { + 'overflow-y': "auto", + } + }, + [$el("div.comfy-modal-content", + {}, + [...this.createButtons()]), + ]); + this.selectedOutputIndex = 0; + } + + createButtons() { + this.radio_buttons = $el("div", { + id: "selectOutputImages", + }, []); + + this.is_nsfw_checkbox = $el("input", { type: 'checkbox', id: "is_nsfw" }, []) + const is_nsfw_checkbox_text = $el("label", { + }, [" Is this NSFW?"]) + this.is_nsfw_checkbox.style.color = "var(--fg-color)"; + this.is_nsfw_checkbox.checked = false; + + this.matrix_destination_checkbox = $el("input", { type: 'checkbox', id: "matrix_destination" }, []) + const matrix_destination_checkbox_text = $el("label", {}, [" ComfyUI Matrix server"]) + this.matrix_destination_checkbox.style.color = "var(--fg-color)"; + this.matrix_destination_checkbox.checked = this.share_option === 'matrix'; //true; + + this.comfyworkflows_destination_checkbox = $el("input", { type: 'checkbox', id: "comfyworkflows_destination" }, []) + const comfyworkflows_destination_checkbox_text = $el("label", {}, [" ComfyWorkflows.com"]) + this.comfyworkflows_destination_checkbox.style.color = "var(--fg-color)"; + this.comfyworkflows_destination_checkbox.checked = this.share_option !== 'matrix'; + + this.matrix_homeserver_input = $el("input", { type: 'text', id: "matrix_homeserver", placeholder: "matrix.org", value: ShareDialog.matrix_auth.homeserver || 'matrix.org' }, []); + this.matrix_username_input = $el("input", { type: 'text', placeholder: "Username", value: ShareDialog.matrix_auth.username || '' }, []); + this.matrix_password_input = $el("input", { type: 'password', placeholder: "Password", value: ShareDialog.matrix_auth.password || '' }, []); + + this.cw_sharekey_input = $el("input", { type: 'text', placeholder: "Share key (found on your profile page)", value: ShareDialog.cw_sharekey || '' }, []); + this.cw_sharekey_input.style.width = "100%"; + + this.credits_input = $el("input", { + type: "text", + placeholder: "This will be used to give credits", + required: false, + }, []); + + this.title_input = $el("input", { + type: "text", + placeholder: "ex: My awesome art", + required: false + }, []); + + this.description_input = $el("textarea", { + placeholder: "ex: Trying out a new workflow... ", + required: false, + }, []); + + this.share_button = $el("button", { + type: "submit", + textContent: "Share", + style: { + backgroundColor: "blue" + } + }, []); + + this.final_message = $el("div", { + style: { + color: "white", + textAlign: "center", + // marginTop: "10px", + // backgroundColor: "black", + padding: "10px", + } + }, []); + + this.share_finalmessage_container = $el("div.cm-menu-container", { + id: "comfyui-share-finalmessage-container", + style: { + display: "none", + } + }, [ + $el("div.cm-menu-column", [ + this.final_message, + $el("button", { + type: "button", + textContent: "Close", + onclick: () => { + // Reset state + this.matrix_destination_checkbox.checked = this.share_option === 'matrix'; + this.comfyworkflows_destination_checkbox.checked = this.share_option !== 'matrix'; + this.share_button.textContent = "Share"; + this.share_button.style.display = "inline-block"; + this.final_message.innerHTML = ""; + this.final_message.style.color = "white"; + this.credits_input.value = ""; + this.title_input.value = ""; + this.description_input.value = ""; + this.is_nsfw_checkbox.checked = false; + this.selectedOutputIndex = 0; + + // hide the final message + this.share_finalmessage_container.style.display = "none"; + + // show the share container + this.share_container.style.display = "flex"; + + this.close() + } + }), + ]) + ]); + this.share_container = $el("div.cm-menu-container", { + id: "comfyui-share-container" + }, [ + $el("div.cm-menu-column", [ + $el("details", { + style: { + border: "1px solid #999", + padding: "5px", + borderRadius: "5px", + backgroundColor: "#222" + } + }, [ + $el("summary", { + style: { + color: "white", + cursor: "pointer", + } + }, [`Matrix account`]), + $el("div", { + style: { + display: "flex", + flexDirection: "row", + } + }, [ + $el("div", { + textContent: "Homeserver", + style: { + marginRight: "10px", + } + }, []), + this.matrix_homeserver_input, + ]), + + $el("div", { + style: { + display: "flex", + flexDirection: "row", + } + }, [ + $el("div", { + textContent: "Username", + style: { + marginRight: "10px", + } + }, []), + this.matrix_username_input, + ]), + + $el("div", { + style: { + display: "flex", + flexDirection: "row", + } + }, [ + $el("div", { + textContent: "Password", + style: { + marginRight: "10px", + } + }, []), + this.matrix_password_input, + ]), + + ]), + $el("details", { + style: { + border: "1px solid #999", + marginTop: "10px", + padding: "5px", + borderRadius: "5px", + backgroundColor: "#222" + }, + }, [ + $el("summary", { + style: { + color: "white", + cursor: "pointer", + } + }, [`Comfyworkflows.com account`]), + $el("h4", { + textContent: "Share key (found on your profile page)", + }, []), + $el("p", { size: 3, color: "white" }, ["If provided, your art will be saved to your account. Otherwise, it will be shared anonymously."]), + this.cw_sharekey_input, + ]), + + $el("div", {}, [ + $el("p", { + size: 3, color: "white", style: { + color: 'white' + } + }, [`Select where to share your art:`]), + this.matrix_destination_checkbox, + matrix_destination_checkbox_text, + $el("br", {}, []), + this.comfyworkflows_destination_checkbox, + comfyworkflows_destination_checkbox_text, + ]), + + $el("h4", { + textContent: "Credits (optional)", + size: 3, + color: "white", + style: { + color: 'white' + } + }, []), + this.credits_input, + // $el("br", {}, []), + + $el("h4", { + textContent: "Title (optional)", + size: 3, + color: "white", + style: { + color: 'white' + } + }, []), + this.title_input, + // $el("br", {}, []), + + $el("h4", { + textContent: "Description (optional)", + size: 3, + color: "white", + style: { + color: 'white' + } + }, []), + this.description_input, + $el("br", {}, []), + + $el("div", {}, [this.is_nsfw_checkbox, is_nsfw_checkbox_text]), + // $el("br", {}, []), + + // this.final_message, + // $el("br", {}, []), + ]), + $el("div.cm-menu-column", [ + this.radio_buttons, + $el("br", {}, []), + + this.share_button, + + $el("button", { + type: "button", + textContent: "Close", + onclick: () => { + // Reset state + this.matrix_destination_checkbox.checked = this.share_option === 'matrix'; + this.comfyworkflows_destination_checkbox.checked = this.share_option !== 'matrix'; + this.share_button.textContent = "Share"; + this.share_button.style.display = "inline-block"; + this.final_message.innerHTML = ""; + this.final_message.style.color = "white"; + this.credits_input.value = ""; + this.title_input.value = ""; + this.description_input.value = ""; + this.is_nsfw_checkbox.checked = false; + this.selectedOutputIndex = 0; + + // hide the final message + this.share_finalmessage_container.style.display = "none"; + + // show the share container + this.share_container.style.display = "flex"; + + this.close() + } + }), + $el("br", {}, []), + ]), + ]); + + // get the user's existing matrix auth and share key + ShareDialog.matrix_auth = { homeserver: "matrix.org", username: "", password: "" }; + try { + api.fetchApi(`/manager/get_matrix_auth`) + .then(response => response.json()) + .then(data => { + ShareDialog.matrix_auth = data; + this.matrix_homeserver_input.value = ShareDialog.matrix_auth.homeserver; + this.matrix_username_input.value = ShareDialog.matrix_auth.username; + this.matrix_password_input.value = ShareDialog.matrix_auth.password; + }) + .catch(error => { + // console.log(error); + }); + } catch (error) { + // console.log(error); + } + + // get the user's existing comfyworkflows share key + ShareDialog.cw_sharekey = ""; + try { + // console.log("Fetching comfyworkflows share key") + api.fetchApi(`/manager/get_comfyworkflows_auth`) + .then(response => response.json()) + .then(data => { + ShareDialog.cw_sharekey = data.comfyworkflows_sharekey; + this.cw_sharekey_input.value = ShareDialog.cw_sharekey; + }) + .catch(error => { + // console.log(error); + }); + } catch (error) { + // console.log(error); + } + + this.share_button.onclick = async () => { + const prompt = await app.graphToPrompt(); + const nodes = app.graph._nodes; + + // console.log({ prompt, nodes }); + + const destinations = []; + if (this.matrix_destination_checkbox.checked) { + destinations.push("matrix"); + } + if (this.comfyworkflows_destination_checkbox.checked) { + destinations.push("comfyworkflows"); + } + + // if destinations includes matrix, make an api call to /manager/check_matrix to ensure that the user has configured their matrix settings + if (destinations.includes("matrix")) { + let definedMatrixAuth = !!this.matrix_homeserver_input.value && !!this.matrix_username_input.value && !!this.matrix_password_input.value; + if (!definedMatrixAuth) { + alert("Please set your Matrix account details."); + return; + } + } + + if (destinations.includes("comfyworkflows") && !this.cw_sharekey_input.value && false) { //!confirm("You have NOT set your ComfyWorkflows.com share key. Your art will NOT be connected to your account (it will be shared anonymously). Continue?")) { + return; + } + + const { potential_outputs, potential_output_nodes } = getPotentialOutputsAndOutputNodes(nodes); + + // console.log({ potential_outputs, potential_output_nodes }) + + if (potential_outputs.length === 0) { + if (potential_output_nodes.length === 0) { + // todo: add support for other output node types (animatediff combine, etc.) + const supported_nodes_string = SUPPORTED_OUTPUT_NODE_TYPES.join(", "); + alert(`No supported output node found (${supported_nodes_string}). To share this workflow, please add an output node to your graph and re-run your prompt.`); + } else { + alert("To share this, first run a prompt. Once it's done, click 'Share'.\n\nNOTE: Images of the Share target can only be selected in the PreviewImage, SaveImage, and VHS_VideoCombine nodes. In the case of VHS_VideoCombine, only the image/gif and image/webp formats are supported."); + } + this.selectedOutputIndex = 0; + this.close(); + return; + } + + // Change the text of the share button to "Sharing..." to indicate that the share process has started + this.share_button.textContent = "Sharing..."; + + const response = await api.fetchApi(`/manager/share`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + matrix_auth: { + homeserver: this.matrix_homeserver_input.value, + username: this.matrix_username_input.value, + password: this.matrix_password_input.value, + }, + cw_auth: { + cw_sharekey: this.cw_sharekey_input.value, + }, + share_destinations: destinations, + credits: this.credits_input.value, + title: this.title_input.value, + description: this.description_input.value, + is_nsfw: this.is_nsfw_checkbox.checked, + prompt, + potential_outputs, + selected_output_index: this.selectedOutputIndex, + // potential_output_nodes + }) + }); + + if (response.status != 200) { + try { + const response_json = await response.json(); + if (response_json.error) { + alert(response_json.error); + this.close(); + return; + } else { + alert("Failed to share your art. Please try again."); + this.close(); + return; + } + } catch (e) { + alert("Failed to share your art. Please try again."); + this.close(); + return; + } + } + + const response_json = await response.json(); + + if (response_json.comfyworkflows.url) { + this.final_message.innerHTML = "Your art has been shared: " + response_json.comfyworkflows.url + ""; + if (response_json.matrix.success) { + this.final_message.innerHTML += "
Your art has been shared in the ComfyUI Matrix server's #share channel!"; + } + } else { + if (response_json.matrix.success) { + this.final_message.innerHTML = "Your art has been shared in the ComfyUI Matrix server's #share channel!"; + } + } + + this.final_message.style.color = "green"; + + // hide #comfyui-share-container and show #comfyui-share-finalmessage-container + this.share_container.style.display = "none"; + this.share_finalmessage_container.style.display = "block"; + + // hide the share button + this.share_button.textContent = "Shared!"; + this.share_button.style.display = "none"; + // this.close(); + } + + const res = + [ + $el("tr.td", { width: "100%" }, [ + $el("font", { size: 6, color: "white" }, [`Share your art`]), + ]), + $el("br", {}, []), + + this.share_finalmessage_container, + this.share_container, + ]; + + res[0].style.padding = "10px 10px 10px 10px"; + res[0].style.backgroundColor = "black"; //"linear-gradient(90deg, #00C9FF 0%, #92FE9D 100%)"; + res[0].style.textAlign = "center"; + res[0].style.height = "45px"; + return res; + } + + show({potential_outputs, potential_output_nodes, share_option}) { + // Sort `potential_output_nodes` by node ID to make the order always + // consistent, but we should also keep `potential_outputs` in the same + // order as `potential_output_nodes`. + const potential_output_to_order = {}; + potential_output_nodes.forEach((node, index) => { + if (node.id in potential_output_to_order) { + potential_output_to_order[node.id][1].push(potential_outputs[index]); + } else { + potential_output_to_order[node.id] = [node, [potential_outputs[index]]]; + } + }) + // Sort the object `potential_output_to_order` by key (node ID) + const sorted_potential_output_to_order = Object.fromEntries( + Object.entries(potential_output_to_order).sort((a, b) => a[0].id - b[0].id) + ); + const sorted_potential_outputs = [] + const sorted_potential_output_nodes = [] + for (const [key, value] of Object.entries(sorted_potential_output_to_order)) { + sorted_potential_output_nodes.push(value[0]); + sorted_potential_outputs.push(...value[1]); + } + potential_output_nodes = sorted_potential_output_nodes; + potential_outputs = sorted_potential_outputs; + + // console.log({ potential_outputs, potential_output_nodes }) + this.radio_buttons.innerHTML = ""; // clear the radio buttons + let is_radio_button_checked = false; // only check the first radio button if multiple images from the same node + const new_radio_buttons = $el("div", { + id: "selectOutput-Options", + style: { + 'overflow-y': 'scroll', + 'max-height': '400px', + } + }, potential_outputs.map((output, index) => { + const {node_id} = output; + const radio_button = $el("input", { type: 'radio', name: "selectOutputImages", value: index, required: index === 0 }, []) + let radio_button_img; + if (output.type === "image" || output.type === "temp") { + radio_button_img = $el("img", { src: `/view?filename=${output.image.filename}&subfolder=${output.image.subfolder}&type=${output.image.type}`, style: { width: "auto", height: "100px" } }, []); + } else if (output.type === "output") { + radio_button_img = $el("img", { src: output.output.value, style: { width: "auto", height: "100px" } }, []); + } else { + // unsupported output type + // this should never happen + // TODO + radio_button_img = $el("img", { src: "", style: { width: "auto", height: "100px" } }, []); + } + const radio_button_text = $el("label", { + // style: { + // color: 'white' + // } + }, [output.title]) + radio_button.style.color = "var(--fg-color)"; + + // Make the radio button checked if it's the selected node, + // otherwise make the first radio button checked. + if (this.selectedNodeId) { + if (this.selectedNodeId === node_id && !is_radio_button_checked) { + radio_button.checked = true; + is_radio_button_checked = true; + } + } else { + radio_button.checked = index === 0; + } + + if (radio_button.checked) { + this.selectedOutputIndex = index; + } + + radio_button.onchange = () => { + this.selectedOutputIndex = parseInt(radio_button.value); + }; + + return $el("div", { + style: { + display: "flex", + 'align-items': 'center', + 'justify-content': 'space-between', + 'margin-bottom': '10px', + } + }, [radio_button, radio_button_text, radio_button_img]); + })); + const header = $el("h3", { + textContent: "Select an image to share", + size: 3, + color: "white", + style: { + 'text-align': 'center', + color: 'white', + backgroundColor: 'black', + padding: '10px', + 'margin-top': '0px', + } + }, [ + $el("p", { + textContent: "Scroll to see all outputs", + size: 2, + color: "white", + style: { + 'text-align': 'center', + color: 'white', + 'margin-bottom': '5px', + 'font-style': 'italic', + 'font-size': '12px', + }, + }, []) + ]); + this.radio_buttons.appendChild(header); + // this.radio_buttons.appendChild(subheader); + this.radio_buttons.appendChild(new_radio_buttons); + this.element.style.display = "block"; + + share_option = share_option || this.share_option; + if (share_option === 'comfyworkflows') { + this.matrix_destination_checkbox.checked = false; + this.comfyworkflows_destination_checkbox.checked = true; + } else { + this.matrix_destination_checkbox.checked = true; + this.comfyworkflows_destination_checkbox.checked = false; + } + } +} diff --git a/custom_nodes/ComfyUI-Manager/js/comfyui-share-copus.js b/custom_nodes/ComfyUI-Manager/js/comfyui-share-copus.js new file mode 100644 index 000000000..318b1fe5d --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/comfyui-share-copus.js @@ -0,0 +1,892 @@ +import { app } from "../../scripts/app.js"; +import { $el, ComfyDialog } from "../../scripts/ui.js"; +const env = "prod"; + +let DEFAULT_HOMEPAGE_URL = "https://copus.io"; + +let API_ENDPOINT = "https://api.client.prod.copus.io/copus-client"; + +if (env !== "prod") { + API_ENDPOINT = "https://api.dev.copus.io/copus-client"; + DEFAULT_HOMEPAGE_URL = "https://test.copus.io"; +} + +const style = ` + .copus-share-dialog a { + color: #f8f8f8; + } + .copus-share-dialog a:hover { + color: #007bff; + } + .output_label { + border: 5px solid transparent; + } + .output_label:hover { + border: 5px solid #59E8C6; + } + .output_label.checked { + border: 5px solid #59E8C6; + } +`; + +// Shared component styles +const sectionStyle = { + marginBottom: 0, + padding: 0, + borderRadius: "8px", + boxShadow: "0 2px 4px rgba(0, 0, 0, 0.05)", + display: "flex", + flexDirection: "column", + justifyContent: "center", + position: "relative", +}; + +export class CopusShareDialog extends ComfyDialog { + static instance = null; + + constructor() { + super(); + $el("style", { + textContent: style, + parent: document.head, + }); + this.element = $el( + "div.comfy-modal.copus-share-dialog", + { + parent: document.body, + style: { + "overflow-y": "auto", + }, + }, + [$el("div.comfy-modal-content", {}, [...this.createButtons()])] + ); + this.selectedOutputIndex = 0; + this.selectedNodeId = null; + this.uploadedImages = []; + this.allFilesImages = []; + this.selectedFile = null; + this.allFiles = []; + this.titleNum = 0; + } + + createButtons() { + const inputStyle = { + display: "block", + minWidth: "500px", + width: "100%", + padding: "10px", + margin: "10px 0", + borderRadius: "4px", + border: "1px solid #ddd", + boxSizing: "border-box", + }; + + const textAreaStyle = { + display: "block", + minWidth: "500px", + width: "100%", + padding: "10px", + margin: "10px 0", + borderRadius: "4px", + border: "1px solid #ddd", + boxSizing: "border-box", + minHeight: "100px", + background: "#222", + resize: "vertical", + color: "#f2f2f2", + fontFamily: "Arial", + fontWeight: "400", + fontSize: "15px", + }; + + const hyperLinkStyle = { + display: "block", + marginBottom: "15px", + fontWeight: "bold", + fontSize: "14px", + }; + + const labelStyle = { + color: "#f8f8f8", + display: "block", + margin: "10px 0 0 0", + fontWeight: "bold", + textDecoration: "none", + }; + + const buttonStyle = { + padding: "10px 80px", + margin: "10px 5px", + borderRadius: "4px", + border: "none", + cursor: "pointer", + color: "#fff", + backgroundColor: "#007bff", + }; + + // upload images input + this.uploadImagesInput = $el("input", { + type: "file", + multiple: false, + style: inputStyle, + accept: "image/*", + }); + + this.uploadImagesInput.addEventListener("change", async (e) => { + const file = e.target.files[0]; + if (!file) { + this.previewImage.src = ""; + this.previewImage.style.display = "none"; + return; + } + const reader = new FileReader(); + reader.onload = async (e) => { + const imgData = e.target.result; + this.previewImage.src = imgData; + this.previewImage.style.display = "block"; + this.selectedFile = null; + // Once user uploads an image, we uncheck all radio buttons + this.radioButtons.forEach((ele) => { + ele.checked = false; + ele.parentElement.classList.remove("checked"); + }); + + // Add the opacity style toggle here to indicate that they only need + // to upload one image or choose one from the outputs. + this.outputsSection.style.opacity = 0.35; + this.uploadImagesInput.style.opacity = 1; + }; + reader.readAsDataURL(file); + }); + + // preview image + this.previewImage = $el("img", { + src: "", + style: { + width: "100%", + maxHeight: "100px", + objectFit: "contain", + display: "none", + marginTop: "10px", + }, + }); + + this.keyInput = $el("input", { + type: "password", + placeholder: "Copy & paste your API key", + style: inputStyle, + }); + this.TitleInput = $el("input", { + type: "text", + placeholder: "Title (Required)", + style: inputStyle, + maxLength: "70", + oninput: () => { + const titleNum = this.TitleInput.value.length; + titleNumDom.textContent = `${titleNum}/70`; + }, + }); + this.SubTitleInput = $el("input", { + type: "text", + placeholder: "Subtitle (Optional)", + style: inputStyle, + maxLength: "70", + oninput: () => { + const titleNum = this.SubTitleInput.value.length; + subTitleNumDom.textContent = `${titleNum}/70`; + }, + }); + this.descriptionInput = $el("textarea", { + placeholder: "Content (Optional)", + style: { + ...textAreaStyle, + minHeight: "100px", + }, + }); + + // Header Section + const headerSection = $el("h3", { + textContent: "Share your workflow to Copus", + size: 3, + color: "white", + style: { + "text-align": "center", + color: "white", + margin: "0 0 10px 0", + }, + }); + this.getAPIKeyLink = $el( + "a", + { + style: { + ...hyperLinkStyle, + color: "#59E8C6", + }, + href: `${DEFAULT_HOMEPAGE_URL}?fromPage=comfyUI`, + target: "_blank", + }, + ["👉 Get your API key here"] + ); + const linkSection = $el( + "div", + { + style: { + marginTop: "10px", + display: "flex", + flexDirection: "column", + }, + }, + [ + // this.communityLink, + this.getAPIKeyLink, + ] + ); + + // Account Section + const accountSection = $el("div", { style: sectionStyle }, [ + $el("label", { style: labelStyle }, ["1️⃣ Copus API Key"]), + this.keyInput, + ]); + + // Output Upload Section + const outputUploadSection = $el("div", { style: sectionStyle }, [ + $el( + "label", + { + style: { + ...labelStyle, + margin: "10px 0 0 0", + }, + }, + ["2️⃣ Image/Thumbnail (Required)"] + ), + this.previewImage, + this.uploadImagesInput, + ]); + + // Outputs Section + this.outputsSection = $el( + "div", + { + id: "selectOutputs", + }, + [] + ); + + const titleNumDom = $el( + "label", + { + style: { + fontSize: "12px", + position: "absolute", + right: "10px", + bottom: "-10px", + color: "#999", + }, + }, + ["0/70"] + ); + const subTitleNumDom = $el( + "label", + { + style: { + fontSize: "12px", + position: "absolute", + right: "10px", + bottom: "-10px", + color: "#999", + }, + }, + ["0/70"] + ); + const descriptionNumDom = $el( + "label", + { + style: { + fontSize: "12px", + position: "absolute", + right: "10px", + bottom: "-10px", + color: "#999", + }, + }, + ["0/70"] + ); + // Additional Inputs Section + const additionalInputsSection = $el( + "div", + { style: { ...sectionStyle, } }, + [ + $el("label", { style: labelStyle }, ["3️⃣ Title "]), + this.TitleInput, + titleNumDom, + ] + ); + const SubtitleSection = $el("div", { style: sectionStyle }, [ + $el("label", { style: labelStyle }, ["4️⃣ Subtitle "]), + this.SubTitleInput, + subTitleNumDom, + ]); + const DescriptionSection = $el("div", { style: sectionStyle }, [ + $el("label", { style: labelStyle }, ["5️⃣ Description "]), + this.descriptionInput, + // descriptionNumDom, + ]); + // switch between outputs section and additional inputs section + this.radioButtons = []; + + this.radioButtonsCheck = $el("input", { + type: "radio", + name: "output_type", + value: "0", + id: "blockchain1", + checked: true, + }); + this.radioButtonsCheckOff = $el("input", { + type: "radio", + name: "output_type", + value: "1", + id: "blockchain", + }); + + const blockChainSection = $el("div", { style: sectionStyle }, [ + $el("label", { style: labelStyle }, ["6️⃣ Store on blockchain "]), + $el( + "label", + { + style: { + marginTop: "10px", + display: "flex", + alignItems: "center", + cursor: "pointer", + }, + }, + [ + this.radioButtonsCheck, + $el("span", { style: { marginLeft: "5px" } }, ["ON"]), + ] + ), + $el( + "label", + { style: { display: "flex", alignItems: "center", cursor: "pointer" } }, + [ + this.radioButtonsCheckOff, + $el("span", { style: { marginLeft: "5px" } }, ["OFF"]), + ] + ), + $el( + "p", + { style: { fontSize: "16px", color: "#fff", margin: "10px 0 0 0" } }, + ["Secure ownership with a permanent & decentralized storage"] + ), + ]); + // Message Section + this.message = $el( + "div", + { + style: { + color: "#ff3d00", + textAlign: "center", + padding: "10px", + fontSize: "20px", + }, + }, + [] + ); + + this.shareButton = $el("button", { + type: "submit", + textContent: "Share", + style: buttonStyle, + onclick: () => { + this.handleShareButtonClick(); + }, + }); + + // Share and Close Buttons + const buttonsSection = $el( + "div", + { + style: { + textAlign: "right", + marginTop: "20px", + display: "flex", + justifyContent: "space-between", + }, + }, + [ + $el("button", { + type: "button", + textContent: "Close", + style: { + ...buttonStyle, + backgroundColor: undefined, + }, + onclick: () => { + this.close(); + }, + }), + this.shareButton, + ] + ); + + // Composing the full layout + const layout = [ + headerSection, + linkSection, + accountSection, + outputUploadSection, + this.outputsSection, + additionalInputsSection, + SubtitleSection, + DescriptionSection, + // contestSection, + blockChainSection, + this.message, + buttonsSection, + ]; + + return layout; + } + /** + * api + * @param {url} path + * @param {params} options + * @param {statusText} statusText + * @returns + */ + async fetchApi(path, options, statusText) { + if (statusText) { + this.message.textContent = statusText; + } + const fullPath = new URL(API_ENDPOINT + path); + const response = await fetch(fullPath, options); + if (!response.ok) { + throw new Error(response.statusText); + } + if (statusText) { + this.message.textContent = ""; + } + const data = await response.json(); + return { + ok: response.ok, + statusText: response.statusText, + status: response.status, + data, + }; + } + /** + * @param {file} uploadFile + */ + async uploadThumbnail(uploadFile, type) { + const form = new FormData(); + form.append("file", uploadFile); + form.append("apiToken", this.keyInput.value); + try { + const res = await this.fetchApi( + `/client/common/opus/uploadImage`, + { + method: "POST", + body: form, + }, + "Uploading thumbnail..." + ); + if (res.status && res.data.status && res.data) { + const { data } = res.data; + if (type) { + this.allFilesImages.push({ + url: data, + }); + } + this.uploadedImages.push({ + url: data, + }); + } else { + throw new Error("make sure your API key is correct and try again later"); + } + } catch (e) { + if (e?.response?.status === 413) { + throw new Error("File size is too large (max 20MB)"); + } else { + throw new Error("Error uploading thumbnail: " + e.message); + } + } + } + + async handleShareButtonClick() { + this.message.textContent = ""; + try { + this.shareButton.disabled = true; + this.shareButton.textContent = "Sharing..."; + await this.share(); + } catch (e) { + alert(e.message); + } + this.shareButton.disabled = false; + this.shareButton.textContent = "Share"; + } + /** + * share + * @param {string} title + * @param {string} subtitle + * @param {string} content + * @param {boolean} storeOnChain + * @param {string} coverUrl + * @param {string[]} imageUrls + * @param {string} apiToken + */ + async share() { + const prompt = await app.graphToPrompt(); + const workflowJSON = prompt["workflow"]; + const form_values = { + title: this.TitleInput.value, + subTitle: this.SubTitleInput.value, + content: this.descriptionInput.value, + storeOnChain: this.radioButtonsCheck.checked ? true : false, + }; + + if (!this.keyInput.value) { + throw new Error("API key is required"); + } + + if (!this.uploadImagesInput.files[0] && !this.selectedFile) { + throw new Error("Thumbnail is required"); + } + + if (!form_values.title) { + throw new Error("Title is required"); + } + + if (!this.uploadedImages.length) { + if (this.selectedFile) { + await this.uploadThumbnail(this.selectedFile); + } else { + for (const file of this.uploadImagesInput.files) { + try { + await this.uploadThumbnail(file); + } catch (e) { + this.uploadedImages = []; + throw new Error(e.message); + } + } + + if (this.uploadImagesInput.files.length === 0) { + throw new Error("No thumbnail uploaded"); + } + } + } + if (this.allFiles.length > 0) { + for (const file of this.allFiles) { + try { + await this.uploadThumbnail(file, true); + } catch (e) { + this.allFilesImages = []; + throw new Error(e.message); + } + } + } + try { + const res = await this.fetchApi( + "/client/common/opus/shareFromComfyUI", + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + workflowJson: workflowJSON, + apiToken: this.keyInput.value, + coverUrl: this.uploadedImages[0].url, + imageUrls: this.allFilesImages.map((image) => image.url), + ...form_values, + }), + }, + "Uploading workflow..." + ); + + if (res.status && res.data.status && res.data) { + localStorage.setItem("copus_token",this.keyInput.value); + const { data } = res.data; + if (data) { + const url = `${DEFAULT_HOMEPAGE_URL}/work/${data}`; + this.message.innerHTML = `Workflow has been shared successfully. Click here to view it.`; + this.previewImage.src = ""; + this.previewImage.style.display = "none"; + this.uploadedImages = []; + this.allFilesImages = []; + this.allFiles = []; + this.TitleInput.value = ""; + this.SubTitleInput.value = ""; + this.descriptionInput.value = ""; + this.selectedFile = null; + } + } + } catch (e) { + throw new Error("Error sharing workflow: " + e.message); + } + } + + async fetchImageBlob(url) { + const response = await fetch(url); + const blob = await response.blob(); + return blob; + } + + async show({ potential_outputs, potential_output_nodes } = {}) { + // Sort `potential_output_nodes` by node ID to make the order always + // consistent, but we should also keep `potential_outputs` in the same + // order as `potential_output_nodes`. + const potential_output_to_order = {}; + potential_output_nodes.forEach((node, index) => { + if (node.id in potential_output_to_order) { + potential_output_to_order[node.id][1].push(potential_outputs[index]); + } else { + potential_output_to_order[node.id] = [node, [potential_outputs[index]]]; + } + }); + // Sort the object `potential_output_to_order` by key (node ID) + const sorted_potential_output_to_order = Object.fromEntries( + Object.entries(potential_output_to_order).sort( + (a, b) => a[0].id - b[0].id + ) + ); + const sorted_potential_outputs = []; + const sorted_potential_output_nodes = []; + for (const [key, value] of Object.entries( + sorted_potential_output_to_order + )) { + sorted_potential_output_nodes.push(value[0]); + sorted_potential_outputs.push(...value[1]); + } + potential_output_nodes = sorted_potential_output_nodes; + potential_outputs = sorted_potential_outputs; + const apiToken = localStorage.getItem("copus_token"); + this.message.innerHTML = ""; + this.message.textContent = ""; + this.element.style.display = "block"; + this.previewImage.src = ""; + this.previewImage.style.display = "none"; + this.keyInput.value = apiToken!=null?apiToken:""; + this.uploadedImages = []; + this.allFilesImages = []; + this.allFiles = []; + // If `selectedNodeId` is provided, we will select the corresponding radio + // button for the node. In addition, we move the selected radio button to + // the top of the list. + if (this.selectedNodeId) { + const index = potential_output_nodes.findIndex( + (node) => node.id === this.selectedNodeId + ); + if (index >= 0) { + this.selectedOutputIndex = index; + } + } + + this.radioButtons = []; + const new_radio_buttons = $el( + "div", + { + id: "selectOutput-Options", + style: { + "overflow-y": "scroll", + "max-height": "200px", + display: "grid", + "grid-template-columns": "repeat(auto-fit, minmax(100px, 1fr))", + "grid-template-rows": "auto", + "grid-column-gap": "10px", + "grid-row-gap": "10px", + "margin-bottom": "10px", + padding: "10px", + "border-radius": "8px", + "box-shadow": "0 2px 4px rgba(0, 0, 0, 0.05)", + "background-color": "var(--bg-color)", + }, + }, + potential_outputs.map((output, index) => { + const { node_id } = output; + const radio_button = $el( + "input", + { + type: "radio", + name: "selectOutputImages", + value: index, + required: index === 0, + }, + [] + ); + let radio_button_img; + let filename; + if (output.type === "image" || output.type === "temp") { + radio_button_img = $el( + "img", + { + src: `/view?filename=${output.image.filename}&subfolder=${output.image.subfolder}&type=${output.image.type}`, + style: { + width: "100px", + height: "100px", + objectFit: "cover", + borderRadius: "5px", + }, + }, + [] + ); + filename = output.image.filename; + } else if (output.type === "output") { + radio_button_img = $el( + "img", + { + src: output.output.value, + style: { + width: "auto", + height: "100px", + objectFit: "cover", + borderRadius: "5px", + }, + }, + [] + ); + filename = output.filename; + } else { + // unsupported output type + // this should never happen + radio_button_img = $el( + "img", + { + src: "", + style: { width: "auto", height: "100px" }, + }, + [] + ); + } + const radio_button_text = $el( + "span", + { + style: { + color: "gray", + display: "block", + fontSize: "12px", + overflowX: "hidden", + textOverflow: "ellipsis", + textWrap: "nowrap", + maxWidth: "100px", + }, + }, + [output.title] + ); + const node_id_chip = $el( + "span", + { + style: { + color: "#FBFBFD", + display: "block", + backgroundColor: "rgba(0, 0, 0, 0.5)", + fontSize: "12px", + overflowX: "hidden", + padding: "2px 3px", + textOverflow: "ellipsis", + textWrap: "nowrap", + maxWidth: "100px", + position: "absolute", + top: "3px", + left: "3px", + borderRadius: "3px", + }, + }, + [`Node: ${node_id}`] + ); + radio_button.style.color = "var(--fg-color)"; + radio_button.checked = this.selectedOutputIndex === index; + + radio_button.onchange = async () => { + this.selectedOutputIndex = parseInt(radio_button.value); + + // Remove the "checked" class from all radio buttons + this.radioButtons.forEach((ele) => { + ele.parentElement.classList.remove("checked"); + }); + radio_button.parentElement.classList.add("checked"); + + this.fetchImageBlob(radio_button_img.src).then((blob) => { + const file = new File([blob], filename, { + type: blob.type, + }); + this.previewImage.src = radio_button_img.src; + this.previewImage.style.display = "block"; + this.selectedFile = file; + }); + + // Add the opacity style toggle here to indicate that they only need + // to upload one image or choose one from the outputs. + this.outputsSection.style.opacity = 1; + this.uploadImagesInput.style.opacity = 0.35; + }; + + if (radio_button.checked) { + this.fetchImageBlob(radio_button_img.src).then((blob) => { + const file = new File([blob], filename, { + type: blob.type, + }); + this.previewImage.src = radio_button_img.src; + this.previewImage.style.display = "block"; + this.selectedFile = file; + }); + // Add the opacity style toggle here to indicate that they only need + // to upload one image or choose one from the outputs. + this.outputsSection.style.opacity = 1; + this.uploadImagesInput.style.opacity = 0.35; + } + this.radioButtons.push(radio_button); + let src = ""; + if (output.type === "image" || output.type === "temp") { + filename = output.image.filename; + src = `/view?filename=${output.image.filename}&subfolder=${output.image.subfolder}&type=${output.image.type}`; + } else if (output.type === "output") { + src = output.output.value; + filename = output.filename; + } + if (src) { + this.fetchImageBlob(src).then((blob) => { + const file = new File([blob], filename, { + type: blob.type, + }); + this.allFiles.push(file); + }); + } + return $el( + `label.output_label${radio_button.checked ? ".checked" : ""}`, + { + style: { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + marginBottom: "10px", + cursor: "pointer", + position: "relative", + }, + }, + [radio_button_img, radio_button_text, radio_button, node_id_chip] + ); + }) + ); + + const header = $el( + "p", + { + textContent: + this.radioButtons.length === 0 + ? "Queue Prompt to see the outputs" + : "Or choose one from the outputs (scroll to see all)", + size: 2, + color: "white", + style: { + color: "white", + margin: "0 0 5px 0", + fontSize: "12px", + }, + }, + [] + ); + this.outputsSection.innerHTML = ""; + this.outputsSection.appendChild(header); + this.outputsSection.appendChild(new_radio_buttons); + } +} diff --git a/custom_nodes/ComfyUI-Manager/js/comfyui-share-openart.js b/custom_nodes/ComfyUI-Manager/js/comfyui-share-openart.js new file mode 100644 index 000000000..96460fe79 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/comfyui-share-openart.js @@ -0,0 +1,745 @@ +import {app} from "../../scripts/app.js"; +import {api} from "../../scripts/api.js"; +import {ComfyDialog, $el} from "../../scripts/ui.js"; + +const LOCAL_STORAGE_KEY = "openart_comfy_workflow_key"; +const DEFAULT_HOMEPAGE_URL = "https://openart.ai/workflows/dev?developer=true"; +//const DEFAULT_HOMEPAGE_URL = "http://localhost:8080/workflows/dev?developer=true"; + +const API_ENDPOINT = "https://openart.ai/api"; +//const API_ENDPOINT = "http://localhost:8080/api"; + +const style = ` + .openart-share-dialog a { + color: #f8f8f8; + } + .openart-share-dialog a:hover { + color: #007bff; + } + .output_label { + border: 5px solid transparent; + } + .output_label:hover { + border: 5px solid #59E8C6; + } + .output_label.checked { + border: 5px solid #59E8C6; + } +`; + +// Shared component styles +const sectionStyle = { + marginBottom: 0, + padding: 0, + borderRadius: "8px", + boxShadow: "0 2px 4px rgba(0, 0, 0, 0.05)", + display: "flex", + flexDirection: "column", + justifyContent: "center", +}; + +export class OpenArtShareDialog extends ComfyDialog { + static instance = null; + + constructor() { + super(); + $el("style", { + textContent: style, + parent: document.head, + }); + this.element = $el( + "div.comfy-modal.openart-share-dialog", + { + parent: document.body, + style: { + "overflow-y": "auto", + }, + }, + [$el("div.comfy-modal-content", {}, [...this.createButtons()])] + ); + this.selectedOutputIndex = 0; + this.selectedNodeId = null; + this.uploadedImages = []; + this.selectedFile = null; + } + + async readKey() { + let key = "" + try { + key = await api.fetchApi(`/manager/get_openart_auth`) + .then(response => response.json()) + .then(data => { + return data.openart_key; + }) + .catch(error => { + // console.log(error); + }); + } catch (error) { + // console.log(error); + } + return key || ""; + } + + async saveKey(value) { + await api.fetchApi(`/manager/set_openart_auth`, { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ + openart_key: value + }) + }); + } + + createButtons() { + const inputStyle = { + display: "block", + minWidth: "500px", + width: "100%", + padding: "10px", + margin: "10px 0", + borderRadius: "4px", + border: "1px solid #ddd", + boxSizing: "border-box", + }; + + const hyperLinkStyle = { + display: "block", + marginBottom: "15px", + fontWeight: "bold", + fontSize: "14px", + }; + + const labelStyle = { + color: "#f8f8f8", + display: "block", + margin: "10px 0 0 0", + fontWeight: "bold", + textDecoration: "none", + }; + + const buttonStyle = { + padding: "10px 80px", + margin: "10px 5px", + borderRadius: "4px", + border: "none", + cursor: "pointer", + color: "#fff", + backgroundColor: "#007bff", + }; + + // upload images input + this.uploadImagesInput = $el("input", { + type: "file", + multiple: false, + style: inputStyle, + accept: "image/*", + }); + + this.uploadImagesInput.addEventListener("change", async (e) => { + const file = e.target.files[0]; + if (!file) { + this.previewImage.src = ""; + this.previewImage.style.display = "none"; + return; + } + const reader = new FileReader(); + reader.onload = async (e) => { + const imgData = e.target.result; + this.previewImage.src = imgData; + this.previewImage.style.display = "block"; + this.selectedFile = null + // Once user uploads an image, we uncheck all radio buttons + this.radioButtons.forEach((ele) => { + ele.checked = false; + ele.parentElement.classList.remove("checked"); + }); + + // Add the opacity style toggle here to indicate that they only need + // to upload one image or choose one from the outputs. + this.outputsSection.style.opacity = 0.35; + this.uploadImagesInput.style.opacity = 1; + }; + reader.readAsDataURL(file); + }); + + // preview image + this.previewImage = $el("img", { + src: "", + style: { + width: "100%", + maxHeight: "100px", + objectFit: "contain", + display: "none", + marginTop: '10px', + }, + }); + + this.keyInput = $el("input", { + type: "password", + placeholder: "Copy & paste your API key", + style: inputStyle, + }); + this.NameInput = $el("input", { + type: "text", + placeholder: "Title (required)", + style: inputStyle, + }); + this.descriptionInput = $el("textarea", { + placeholder: "Description (optional)", + style: { + ...inputStyle, + minHeight: "100px", + }, + }); + + // Header Section + const headerSection = $el("h3", { + textContent: "Share your workflow to OpenArt", + size: 3, + color: "white", + style: { + 'text-align': 'center', + color: 'white', + margin: '0 0 10px 0', + } + }); + + // LinkSection + this.communityLink = $el("a", { + style: hyperLinkStyle, + href: DEFAULT_HOMEPAGE_URL, + target: "_blank" + }, ["👉 Check out thousands of workflows shared from the community"]) + this.getAPIKeyLink = $el("a", { + style: { + ...hyperLinkStyle, + color: "#59E8C6" + }, + href: DEFAULT_HOMEPAGE_URL, + target: "_blank" + }, ["👉 Get your API key here"]) + const linkSection = $el( + "div", + { + style: { + marginTop: "10px", + display: "flex", + flexDirection: "column", + }, + }, + [ + this.communityLink, + this.getAPIKeyLink, + ] + ); + + // Account Section + const accountSection = $el("div", {style: sectionStyle}, [ + $el("label", {style: labelStyle}, ["1️⃣ OpenArt API Key"]), + this.keyInput, + ]); + + // Output Upload Section + const outputUploadSection = $el("div", {style: sectionStyle}, [ + $el("label", { + style: { + ...labelStyle, + margin: "10px 0 0 0" + } + }, ["2️⃣ Image/Thumbnail (Required)"]), + this.previewImage, + this.uploadImagesInput, + ]); + + // Outputs Section + this.outputsSection = $el("div", { + id: "selectOutputs", + }, []); + + // Additional Inputs Section + const additionalInputsSection = $el("div", {style: sectionStyle}, [ + $el("label", {style: labelStyle}, ["3️⃣ Workflow Information"]), + this.NameInput, + this.descriptionInput, + ]); + + // OpenArt Contest Section + /* + this.joinContestCheckbox = $el("input", { + type: 'checkbox', + id: "join_contest"s + }, []) + this.joinContestDescription = $el("a", { + style: { + ...hyperLinkStyle, + display: 'inline-block', + color: "#59E8C6", + fontSize: '12px', + marginLeft: '10px', + marginBottom: 0, + }, + href: "https://contest.openart.ai/", + target: "_blank" + }, ["🏆 I'm participating in the OpenArt workflow contest"]) + this.joinContestLabel = $el("label", { + style: { + display: 'flex', + alignItems: 'center', + cursor: 'pointer', + } + }, [this.joinContestCheckbox, this.joinContestDescription]) + const contestSection = $el("div", {style: sectionStyle}, [ + this.joinContestLabel, + ]); + */ + + // Message Section + this.message = $el( + "div", + { + style: { + color: "#ff3d00", + textAlign: "center", + padding: "10px", + fontSize: "20px", + }, + }, + [] + ); + + this.shareButton = $el("button", { + type: "submit", + textContent: "Share", + style: buttonStyle, + onclick: () => { + this.handleShareButtonClick(); + }, + }); + + // Share and Close Buttons + const buttonsSection = $el( + "div", + { + style: { + textAlign: "right", + marginTop: "20px", + display: "flex", + justifyContent: "space-between", + }, + }, + [ + $el("button", { + type: "button", + textContent: "Close", + style: { + ...buttonStyle, + backgroundColor: undefined, + }, + onclick: () => { + this.close(); + }, + }), + this.shareButton, + ] + ); + + // Composing the full layout + const layout = [ + headerSection, + linkSection, + accountSection, + outputUploadSection, + this.outputsSection, + additionalInputsSection, + // contestSection, + this.message, + buttonsSection, + ]; + + return layout; + } + + async fetchApi(path, options, statusText) { + if (statusText) { + this.message.textContent = statusText; + } + const addSearchParams = (url, params = {}) => + new URL( + `${url.origin}${url.pathname}?${new URLSearchParams([ + ...Array.from(url.searchParams.entries()), + ...Object.entries(params), + ])}` + ); + + const fullPath = addSearchParams(new URL(API_ENDPOINT + path), { + workflow_api_key: this.keyInput.value, + }); + + const response = await fetch(fullPath, options); + + if (!response.ok) { + throw new Error(response.statusText); + } + + if (statusText) { + this.message.textContent = ""; + } + const data = await response.json(); + return { + ok: response.ok, + statusText: response.statusText, + status: response.status, + data, + }; + } + + async uploadThumbnail(uploadFile) { + const form = new FormData(); + form.append("file", uploadFile); + try { + const res = await this.fetchApi( + `/workflows/upload_thumbnail`, + { + method: "POST", + body: form, + }, + "Uploading thumbnail..." + ); + + if (res.ok && res.data) { + const {image_url, width, height} = res.data; + this.uploadedImages.push({ + url: image_url, + width, + height, + }); + } + } catch (e) { + if (e?.response?.status === 413) { + throw new Error("File size is too large (max 20MB)"); + } else { + throw new Error("Error uploading thumbnail: " + e.message); + } + } + } + + async handleShareButtonClick() { + this.message.textContent = ""; + await this.saveKey(this.keyInput.value); + try { + this.shareButton.disabled = true; + this.shareButton.textContent = "Sharing..."; + await this.share(); + } catch (e) { + alert(e.message); + } + this.shareButton.disabled = false; + this.shareButton.textContent = "Share"; + } + + async share() { + const prompt = await app.graphToPrompt(); + const workflowJSON = prompt["workflow"]; + const workflowAPIJSON = prompt["output"]; + const form_values = { + name: this.NameInput.value, + description: this.descriptionInput.value, + }; + + if (!this.keyInput.value) { + throw new Error("API key is required"); + } + + if (!this.uploadImagesInput.files[0] && !this.selectedFile) { + throw new Error("Thumbnail is required"); + } + + if (!form_values.name) { + throw new Error("Title is required"); + } + + const current_snapshot = await api.fetchApi(`/snapshot/get_current`) + .then(response => response.json()) + .catch(error => { + // console.log(error); + }); + + + if (!this.uploadedImages.length) { + if (this.selectedFile) { + await this.uploadThumbnail(this.selectedFile); + } else { + for (const file of this.uploadImagesInput.files) { + try { + await this.uploadThumbnail(file); + } catch (e) { + this.uploadedImages = []; + throw new Error(e.message); + } + } + + if (this.uploadImagesInput.files.length === 0) { + throw new Error("No thumbnail uploaded"); + } + } + } + + // const join_contest = this.joinContestCheckbox.checked; + + try { + const response = await this.fetchApi( + "/workflows/publish", + { + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({ + workflow_json: workflowJSON, + upload_images: this.uploadedImages, + form_values, + advanced_config: { + workflow_api_json: workflowAPIJSON, + snapshot: current_snapshot, + }, + // join_contest, + }), + }, + "Uploading workflow..." + ); + + if (response.ok) { + const {workflow_id} = response.data; + if (workflow_id) { + const url = `https://openart.ai/workflows/-/-/${workflow_id}`; + this.message.innerHTML = `Workflow has been shared successfully. Click here to view it.`; + this.previewImage.src = ""; + this.previewImage.style.display = "none"; + this.uploadedImages = []; + this.NameInput.value = ""; + this.descriptionInput.value = ""; + this.radioButtons.forEach((ele) => { + ele.checked = false; + ele.parentElement.classList.remove("checked"); + }); + this.selectedOutputIndex = 0; + this.selectedNodeId = null; + this.selectedFile = null; + } + } + } catch (e) { + throw new Error("Error sharing workflow: " + e.message); + } + } + + async fetchImageBlob(url) { + const response = await fetch(url); + const blob = await response.blob(); + return blob; + } + + async show({potential_outputs, potential_output_nodes} = {}) { + // Sort `potential_output_nodes` by node ID to make the order always + // consistent, but we should also keep `potential_outputs` in the same + // order as `potential_output_nodes`. + const potential_output_to_order = {}; + potential_output_nodes.forEach((node, index) => { + if (node.id in potential_output_to_order) { + potential_output_to_order[node.id][1].push(potential_outputs[index]); + } else { + potential_output_to_order[node.id] = [node, [potential_outputs[index]]]; + } + }) + // Sort the object `potential_output_to_order` by key (node ID) + const sorted_potential_output_to_order = Object.fromEntries( + Object.entries(potential_output_to_order).sort((a, b) => a[0].id - b[0].id) + ); + const sorted_potential_outputs = [] + const sorted_potential_output_nodes = [] + for (const [key, value] of Object.entries(sorted_potential_output_to_order)) { + sorted_potential_output_nodes.push(value[0]); + sorted_potential_outputs.push(...value[1]); + } + potential_output_nodes = sorted_potential_output_nodes; + potential_outputs = sorted_potential_outputs; + + this.message.innerHTML = ""; + this.message.textContent = ""; + this.element.style.display = "block"; + this.previewImage.src = ""; + this.previewImage.style.display = "none"; + const key = await this.readKey(); + this.keyInput.value = key; + this.uploadedImages = []; + + // If `selectedNodeId` is provided, we will select the corresponding radio + // button for the node. In addition, we move the selected radio button to + // the top of the list. + if (this.selectedNodeId) { + const index = potential_output_nodes.findIndex(node => node.id === this.selectedNodeId); + if (index >= 0) { + this.selectedOutputIndex = index; + } + } + + this.radioButtons = []; + const new_radio_buttons = $el("div", + { + id: "selectOutput-Options", + style: { + 'overflow-y': 'scroll', + 'max-height': '200px', + + 'display': 'grid', + 'grid-template-columns': 'repeat(auto-fit, minmax(100px, 1fr))', + 'grid-template-rows': 'auto', + 'grid-column-gap': '10px', + 'grid-row-gap': '10px', + 'margin-bottom': '10px', + 'padding': '10px', + 'border-radius': '8px', + 'box-shadow': '0 2px 4px rgba(0, 0, 0, 0.05)', + 'background-color': 'var(--bg-color)', + } + }, + potential_outputs.map((output, index) => { + const {node_id} = output; + const radio_button = $el("input", { + type: 'radio', + name: "selectOutputImages", + value: index, + required: index === 0 + }, []) + let radio_button_img; + let filename; + if (output.type === "image" || output.type === "temp") { + radio_button_img = $el("img", { + src: `/view?filename=${output.image.filename}&subfolder=${output.image.subfolder}&type=${output.image.type}`, + style: { + width: "100px", + height: "100px", + objectFit: "cover", + borderRadius: "5px" + } + }, []); + filename = output.image.filename + } else if (output.type === "output") { + radio_button_img = $el("img", { + src: output.output.value, + style: { + width: "auto", + height: "100px", + objectFit: "cover", + borderRadius: "5px" + } + }, []); + filename = output.filename + } else { + // unsupported output type + // this should never happen + // TODO + radio_button_img = $el("img", { + src: "", + style: {width: "auto", height: "100px"} + }, []); + } + const radio_button_text = $el("span", { + style: { + color: 'gray', + display: 'block', + fontSize: '12px', + overflowX: 'hidden', + textOverflow: 'ellipsis', + textWrap: 'nowrap', + maxWidth: '100px', + } + }, [output.title]) + const node_id_chip = $el("span", { + style: { + color: '#FBFBFD', + display: 'block', + backgroundColor: 'rgba(0, 0, 0, 0.5)', + fontSize: '12px', + overflowX: 'hidden', + padding: '2px 3px', + textOverflow: 'ellipsis', + textWrap: 'nowrap', + maxWidth: '100px', + position: 'absolute', + top: '3px', + left: '3px', + borderRadius: '3px', + } + }, [`Node: ${node_id}`]) + radio_button.style.color = "var(--fg-color)"; + radio_button.checked = this.selectedOutputIndex === index; + + radio_button.onchange = async () => { + this.selectedOutputIndex = parseInt(radio_button.value); + + // Remove the "checked" class from all radio buttons + this.radioButtons.forEach((ele) => { + ele.parentElement.classList.remove("checked"); + }); + radio_button.parentElement.classList.add("checked"); + + this.fetchImageBlob(radio_button_img.src).then((blob) => { + const file = new File([blob], filename, { + type: blob.type, + }); + this.previewImage.src = radio_button_img.src; + this.previewImage.style.display = "block"; + this.selectedFile = file; + }) + + // Add the opacity style toggle here to indicate that they only need + // to upload one image or choose one from the outputs. + this.outputsSection.style.opacity = 1; + this.uploadImagesInput.style.opacity = 0.35; + }; + + if (radio_button.checked) { + this.fetchImageBlob(radio_button_img.src).then((blob) => { + const file = new File([blob], filename, { + type: blob.type, + }); + this.previewImage.src = radio_button_img.src; + this.previewImage.style.display = "block"; + this.selectedFile = file; + }) + // Add the opacity style toggle here to indicate that they only need + // to upload one image or choose one from the outputs. + this.outputsSection.style.opacity = 1; + this.uploadImagesInput.style.opacity = 0.35; + } + + this.radioButtons.push(radio_button); + + return $el(`label.output_label${radio_button.checked ? '.checked' : ''}`, { + style: { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + marginBottom: "10px", + cursor: "pointer", + position: 'relative', + } + }, [radio_button_img, radio_button_text, radio_button, node_id_chip]); + }) + ); + + const header = + $el("p", { + textContent: this.radioButtons.length === 0 ? "Queue Prompt to see the outputs" : "Or choose one from the outputs (scroll to see all)", + size: 2, + color: "white", + style: { + color: 'white', + margin: '0 0 5px 0', + fontSize: '12px', + }, + }, []) + this.outputsSection.innerHTML = ""; + this.outputsSection.appendChild(header); + this.outputsSection.appendChild(new_radio_buttons); + } +} diff --git a/custom_nodes/ComfyUI-Manager/js/comfyui-share-youml.js b/custom_nodes/ComfyUI-Manager/js/comfyui-share-youml.js new file mode 100644 index 000000000..80077b25a --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/comfyui-share-youml.js @@ -0,0 +1,568 @@ +import {app} from "../../scripts/app.js"; +import {api} from "../../scripts/api.js"; +import {ComfyDialog, $el} from "../../scripts/ui.js"; + +const BASE_URL = "https://youml.com"; +//const BASE_URL = "http://localhost:3000"; +const DEFAULT_HOMEPAGE_URL = `${BASE_URL}/?from=comfyui`; +const TOKEN_PAGE_URL = `${BASE_URL}/my-token`; +const API_ENDPOINT = `${BASE_URL}/api`; + +const style = ` + .youml-share-dialog { + overflow-y: auto; + } + .youml-share-dialog .dialog-header { + text-align: center; + color: white; + margin: 0 0 10px 0; + } + .youml-share-dialog .dialog-section { + margin-bottom: 0; + padding: 0; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; + justify-content: center; + } + .youml-share-dialog input, .youml-share-dialog textarea { + display: block; + min-width: 500px; + width: 100%; + padding: 10px; + margin: 10px 0; + border-radius: 4px; + border: 1px solid #ddd; + box-sizing: border-box; + } + .youml-share-dialog textarea { + color: var(--input-text); + background-color: var(--comfy-input-bg); + } + .youml-share-dialog .workflow-description { + min-height: 75px; + } + .youml-share-dialog label { + color: #f8f8f8; + display: block; + margin: 5px 0 0 0; + font-weight: bold; + text-decoration: none; + } + .youml-share-dialog .action-button { + padding: 10px 80px; + margin: 10px 5px; + border-radius: 4px; + border: none; + cursor: pointer; + } + .youml-share-dialog .share-button { + color: #fff; + background-color: #007bff; + } + .youml-share-dialog .close-button { + background-color: none; + } + .youml-share-dialog .action-button-panel { + text-align: right; + display: flex; + justify-content: space-between; + } + .youml-share-dialog .status-message { + color: #fd7909; + text-align: center; + padding: 5px; + font-size: 18px; + } + .youml-share-dialog .status-message a { + color: white; + } + .youml-share-dialog .output-panel { + overflow: auto; + max-height: 180px; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); + grid-template-rows: auto; + grid-column-gap: 10px; + grid-row-gap: 10px; + margin-bottom: 10px; + padding: 10px; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); + background-color: var(--bg-color); + } + .youml-share-dialog .output-panel .output-image { + width: 100px; + height: 100px; + objectFit: cover; + borderRadius: 5px; + } + + .youml-share-dialog .output-panel .radio-button { + color:var(--fg-color); + } + .youml-share-dialog .output-panel .radio-text { + color: gray; + display: block; + font-size: 12px; + overflow-x: hidden; + text-overflow: ellipsis; + text-wrap: nowrap; + max-width: 100px; + } + .youml-share-dialog .output-panel .node-id { + color: #FBFBFD; + display: block; + background-color: rgba(0, 0, 0, 0.5); + font-size: 12px; + overflow-x: hidden; + padding: 2px 3px; + text-overflow: ellipsis; + text-wrap: nowrap; + max-width: 100px; + position: absolute; + top: 3px; + left: 3px; + border-radius: 3px; + } + .youml-share-dialog .output-panel .output-label { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-bottom: 10px; + cursor: pointer; + position: relative; + border: 5px solid transparent; + } + .youml-share-dialog .output-panel .output-label:hover { + border: 5px solid #007bff; + } + .youml-share-dialog .output-panel .output-label.checked { + border: 5px solid #007bff; + } + .youml-share-dialog .missing-output-message{ + color: #fd7909; + font-size: 16px; + margin-bottom:10px + } + .youml-share-dialog .select-output-message{ + color: white; + margin-bottom:5px + } +`; + +export class YouMLShareDialog extends ComfyDialog { + static instance = null; + + constructor() { + super(); + $el("style", { + textContent: style, + parent: document.head, + }); + this.element = $el( + "div.comfy-modal.youml-share-dialog", + { + parent: document.body, + }, + [$el("div.comfy-modal-content", {}, [...this.createLayout()])] + ); + this.selectedOutputIndex = 0; + this.selectedNodeId = null; + this.uploadedImages = []; + this.selectedFile = null; + } + + async loadToken() { + let key = "" + try { + const response = await api.fetchApi(`/manager/youml/settings`) + const settings = await response.json() + return settings.token + } catch (error) { + } + return key || ""; + } + + async saveToken(value) { + await api.fetchApi(`/manager/youml/settings`, { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ + token: value + }) + }); + } + + createLayout() { + // Header Section + const headerSection = $el("h3.dialog-header", { + textContent: "Share your workflow to YouML.com", + size: 3, + }); + + // Workflow Info Section + this.nameInput = $el("input", { + type: "text", + placeholder: "Name (required)", + }); + this.descriptionInput = $el("textarea.workflow-description", { + placeholder: "Description (optional, markdown supported)", + }); + const workflowMetadata = $el("div.dialog-section", {}, [ + $el("label", {}, ["Workflow info"]), + this.nameInput, + this.descriptionInput, + ]); + + // Outputs Section + this.outputsSection = $el("div.dialog-section", { + id: "selectOutputs", + }, []); + + const outputUploadSection = $el("div.dialog-section", {}, [ + $el("label", {}, ["Thumbnail"]), + this.outputsSection, + ]); + + // API Token Section + this.apiTokenInput = $el("input", { + type: "password", + placeholder: "Copy & paste your API token", + }); + const getAPITokenButton = $el("button", { + href: DEFAULT_HOMEPAGE_URL, + target: "_blank", + onclick: () => window.open(TOKEN_PAGE_URL, "_blank"), + }, ["Get your API Token"]) + + const apiTokenSection = $el("div.dialog-section", {}, [ + $el("label", {}, ["YouML API Token"]), + this.apiTokenInput, + getAPITokenButton, + ]); + + // Message Section + this.message = $el("div.status-message", {}, []); + + // Share and Close Buttons + this.shareButton = $el("button.action-button.share-button", { + type: "submit", + textContent: "Share", + onclick: () => { + this.handleShareButtonClick(); + }, + }); + + const buttonsSection = $el( + "div.action-button-panel", + {}, + [ + $el("button.action-button.close-button", { + type: "button", + textContent: "Close", + onclick: () => { + this.close(); + }, + }), + this.shareButton, + ] + ); + + // Composing the full layout + const layout = [ + headerSection, + workflowMetadata, + outputUploadSection, + apiTokenSection, + this.message, + buttonsSection, + ]; + + return layout; + } + + async fetchYoumlApi(path, options, statusText) { + if (statusText) { + this.message.textContent = statusText; + } + + const fullPath = new URL(API_ENDPOINT + path) + + const fetchOptions = Object.assign({}, options) + + fetchOptions.headers = { + ...fetchOptions.headers, + "Authorization": `Bearer ${this.apiTokenInput.value}`, + "User-Agent": "ComfyUI-Manager-Youml/1.0.0", + } + + const response = await fetch(fullPath, fetchOptions); + + if (!response.ok) { + throw new Error(response.statusText + " " + (await response.text())); + } + + if (statusText) { + this.message.textContent = ""; + } + const data = await response.json(); + return { + ok: response.ok, + statusText: response.statusText, + status: response.status, + data, + }; + } + + async uploadThumbnail(uploadFile, recipeId) { + const form = new FormData(); + form.append("file", uploadFile, uploadFile.name); + try { + const res = await this.fetchYoumlApi( + `/v1/comfy/recipes/${recipeId}/thumbnail`, + { + method: "POST", + body: form, + }, + "Uploading thumbnail..." + ); + + } catch (e) { + if (e?.response?.status === 413) { + throw new Error("File size is too large (max 20MB)"); + } else { + throw new Error("Error uploading thumbnail: " + e.message); + } + } + } + + async handleShareButtonClick() { + this.message.textContent = ""; + await this.saveToken(this.apiTokenInput.value); + try { + this.shareButton.disabled = true; + this.shareButton.textContent = "Sharing..."; + await this.share(); + } catch (e) { + alert(e.message); + } finally { + this.shareButton.disabled = false; + this.shareButton.textContent = "Share"; + } + } + + async share() { + const prompt = await app.graphToPrompt(); + const workflowJSON = prompt["workflow"]; + const workflowAPIJSON = prompt["output"]; + const form_values = { + name: this.nameInput.value, + description: this.descriptionInput.value, + }; + + if (!this.apiTokenInput.value) { + throw new Error("API token is required"); + } + + if (!this.selectedFile) { + throw new Error("Thumbnail is required"); + } + + if (!form_values.name) { + throw new Error("Title is required"); + } + + + try { + let snapshotData = null; + try { + const snapshot = await api.fetchApi(`/snapshot/get_current`) + snapshotData = await snapshot.json() + } catch (e) { + console.error("Failed to get snapshot", e) + } + + const request = { + name: this.nameInput.value, + description: this.descriptionInput.value, + workflowUiJson: JSON.stringify(workflowJSON), + workflowApiJson: JSON.stringify(workflowAPIJSON), + } + + if (snapshotData) { + request.snapshotJson = JSON.stringify(snapshotData) + } + + const response = await this.fetchYoumlApi( + "/v1/comfy/recipes", + { + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify(request), + }, + "Uploading workflow..." + ); + + if (response.ok) { + const {id, recipePageUrl, editorPageUrl} = response.data; + if (id) { + let messagePrefix = "Workflow has been shared." + if (this.selectedFile) { + try { + await this.uploadThumbnail(this.selectedFile, id); + } catch (e) { + console.error("Thumbnail upload failed: ", e); + messagePrefix = "Workflow has been shared, but thumbnail upload failed. You can create a thumbnail on YouML later." + } + } + this.message.innerHTML = `${messagePrefix} To turn your workflow into an interactive app, ` + + `visit it on YouML`; + + this.uploadedImages = []; + this.nameInput.value = ""; + this.descriptionInput.value = ""; + this.radioButtons.forEach((ele) => { + ele.checked = false; + ele.parentElement.classList.remove("checked"); + }); + this.selectedOutputIndex = 0; + this.selectedNodeId = null; + this.selectedFile = null; + } + } + } catch (e) { + throw new Error("Error sharing workflow: " + e.message); + } + } + + async fetchImageBlob(url) { + const response = await fetch(url); + const blob = await response.blob(); + return blob; + } + + async show(potentialOutputs, potentialOutputNodes) { + const potentialOutputsToOrder = {}; + potentialOutputNodes.forEach((node, index) => { + if (node.id in potentialOutputsToOrder) { + potentialOutputsToOrder[node.id][1].push(potentialOutputs[index]); + } else { + potentialOutputsToOrder[node.id] = [node, [potentialOutputs[index]]]; + } + }) + const sortedPotentialOutputsToOrder = Object.fromEntries( + Object.entries(potentialOutputsToOrder).sort((a, b) => a[0].id - b[0].id) + ); + const sortedPotentialOutputs = [] + const sortedPotentiaOutputNodes = [] + for (const [key, value] of Object.entries(sortedPotentialOutputsToOrder)) { + sortedPotentiaOutputNodes.push(value[0]); + sortedPotentialOutputs.push(...value[1]); + } + potentialOutputNodes = sortedPotentiaOutputNodes; + potentialOutputs = sortedPotentialOutputs; + + + // If `selectedNodeId` is provided, we will select the corresponding radio + // button for the node. In addition, we move the selected radio button to + // the top of the list. + if (this.selectedNodeId) { + const index = potentialOutputNodes.findIndex(node => node.id === this.selectedNodeId); + if (index >= 0) { + this.selectedOutputIndex = index; + } + } + + this.radioButtons = []; + const newRadioButtons = $el("div.output-panel", + { + id: "selectOutput-Options", + }, + potentialOutputs.map((output, index) => { + const {node_id: nodeId} = output; + const radioButton = $el("input.radio-button", { + type: "radio", + name: "selectOutputImages", + value: index, + required: index === 0 + }, []) + let radioButtonImage; + let filename; + if (output.type === "image" || output.type === "temp") { + radioButtonImage = $el("img.output-image", { + src: `/view?filename=${output.image.filename}&subfolder=${output.image.subfolder}&type=${output.image.type}`, + }, []); + filename = output.image.filename + } else if (output.type === "output") { + radioButtonImage = $el("img.output-image", { + src: output.output.value, + }, []); + filename = output.output.filename + } else { + radioButtonImage = $el("img.output-image", { + src: "", + }, []); + } + const radioButtonText = $el("span.radio-text", {}, [output.title]) + const nodeIdChip = $el("span.node-id", {}, [`Node: ${nodeId}`]) + radioButton.checked = this.selectedOutputIndex === index; + + radioButton.onchange = async () => { + this.selectedOutputIndex = parseInt(radioButton.value); + + // Remove the "checked" class from all radio buttons + this.radioButtons.forEach((ele) => { + ele.parentElement.classList.remove("checked"); + }); + radioButton.parentElement.classList.add("checked"); + + this.fetchImageBlob(radioButtonImage.src).then((blob) => { + const file = new File([blob], filename, { + type: blob.type, + }); + this.selectedFile = file; + }) + }; + + if (radioButton.checked) { + this.fetchImageBlob(radioButtonImage.src).then((blob) => { + const file = new File([blob], filename, { + type: blob.type, + }); + this.selectedFile = file; + }) + } + + this.radioButtons.push(radioButton); + + return $el(`label.output-label${radioButton.checked ? '.checked' : ''}`, {}, + [radioButtonImage, radioButtonText, radioButton, nodeIdChip]); + }) + ); + + let header; + if (this.radioButtons.length === 0) { + header = $el("div.missing-output-message", {textContent: "Queue Prompt to see the outputs and select a thumbnail"}, []) + } else { + header = $el("div.select-output-message", {textContent: "Choose one from the outputs (scroll to see all)"}, []) + } + + this.outputsSection.innerHTML = ""; + this.outputsSection.appendChild(header); + if (this.radioButtons.length > 0) { + this.outputsSection.appendChild(newRadioButtons); + } + + this.message.innerHTML = ""; + this.message.textContent = ""; + + const token = await this.loadToken(); + this.apiTokenInput.value = token; + this.uploadedImages = []; + + this.element.style.display = "block"; + } +} diff --git a/custom_nodes/ComfyUI-Manager/js/common.js b/custom_nodes/ComfyUI-Manager/js/common.js new file mode 100644 index 000000000..49a47d6f5 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/common.js @@ -0,0 +1,240 @@ +import { app } from "../../scripts/app.js"; +import { api } from "../../scripts/api.js"; +import { $el, ComfyDialog } from "../../scripts/ui.js"; + +export function show_message(msg) { + app.ui.dialog.show(msg); + app.ui.dialog.element.style.zIndex = 10010; +} + +export async function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export function rebootAPI() { + if (confirm("Are you sure you'd like to reboot the server?")) { + try { + api.fetchApi("/manager/reboot"); + } + catch(exception) { + + } + return true; + } + + return false; +} + +export var manager_instance = null; + +export function setManagerInstance(obj) { + manager_instance = obj; +} + +export function showToast(message, duration = 3000) { + const toast = $el("div.comfy-toast", {textContent: message}); + document.body.appendChild(toast); + setTimeout(() => { + toast.classList.add("comfy-toast-fadeout"); + setTimeout(() => toast.remove(), 500); + }, duration); +} + +function isValidURL(url) { + if(url.includes('&')) + return false; + + const http_pattern = /^(https?|ftp):\/\/[^\s$?#]+$/; + const ssh_pattern = /^(.+@|ssh:\/\/).+:.+$/; + return http_pattern.test(url) || ssh_pattern.test(url); +} + +export async function install_pip(packages) { + if(packages.includes('&')) + app.ui.dialog.show(`Invalid PIP package enumeration: '${packages}'`); + + const res = await api.fetchApi("/customnode/install/pip", { + method: "POST", + body: packages, + }); + + if(res.status == 403) { + show_message('This action is not allowed with this security level configuration.'); + return; + } + + if(res.status == 200) { + show_message(`PIP package installation is processed.
To apply the pip packages, please click the button in ComfyUI.`); + + const rebootButton = document.getElementById('cm-reboot-button3'); + const self = this; + + rebootButton.addEventListener("click", rebootAPI); + } + else { + show_message(`Failed to install '${packages}'
See terminal log.`); + } +} + +export async function install_via_git_url(url, manager_dialog) { + if(!url) { + return; + } + + if(!isValidURL(url)) { + show_message(`Invalid Git url '${url}'`); + return; + } + + show_message(`Wait...

Installing '${url}'`); + + const res = await api.fetchApi("/customnode/install/git_url", { + method: "POST", + body: url, + }); + + if(res.status == 403) { + show_message('This action is not allowed with this security level configuration.'); + return; + } + + if(res.status == 200) { + show_message(`'${url}' is installed
To apply the installed custom node, please ComfyUI.`); + + const rebootButton = document.getElementById('cm-reboot-button4'); + const self = this; + + rebootButton.addEventListener("click", + function() { + if(rebootAPI()) { + manager_dialog.close(); + } + }); + } + else { + show_message(`Failed to install '${url}'
See terminal log.`); + } +} + +export async function free_models(free_execution_cache) { + try { + let mode = ""; + if(free_execution_cache) { + mode = '{"unload_models": true, "free_memory": true}'; + } + else { + mode = '{"unload_models": true}'; + } + + let res = await api.fetchApi(`/free`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: mode + }); + + if (res.status == 200) { + if(free_execution_cache) { + showToast("'Models' and 'Execution Cache' have been cleared.", 3000); + } + else { + showToast("Models' have been unloaded.", 3000); + } + } else { + showToast('Unloading of models failed. Installed ComfyUI may be an outdated version.', 5000); + } + } catch (error) { + showToast('An error occurred while trying to unload models.', 5000); + } +} + +export function md5(inputString) { + const hc = '0123456789abcdef'; + const rh = n => {let j,s='';for(j=0;j<=3;j++) s+=hc.charAt((n>>(j*8+4))&0x0F)+hc.charAt((n>>(j*8))&0x0F);return s;} + const ad = (x,y) => {let l=(x&0xFFFF)+(y&0xFFFF);let m=(x>>16)+(y>>16)+(l>>16);return (m<<16)|(l&0xFFFF);} + const rl = (n,c) => (n<>>(32-c)); + const cm = (q,a,b,x,s,t) => ad(rl(ad(ad(a,q),ad(x,t)),s),b); + const ff = (a,b,c,d,x,s,t) => cm((b&c)|((~b)&d),a,b,x,s,t); + const gg = (a,b,c,d,x,s,t) => cm((b&d)|(c&(~d)),a,b,x,s,t); + const hh = (a,b,c,d,x,s,t) => cm(b^c^d,a,b,x,s,t); + const ii = (a,b,c,d,x,s,t) => cm(c^(b|(~d)),a,b,x,s,t); + const sb = x => { + let i;const nblk=((x.length+8)>>6)+1;const blks=[];for(i=0;i>2]|=x.charCodeAt(i)<<((i%4)*8);} + blks[i>>2]|=0x80<<((i%4)*8);blks[nblk*16-2]=x.length*8;return blks; + } + let i,x=sb(inputString),a=1732584193,b=-271733879,c=-1732584194,d=271733878,olda,oldb,oldc,oldd; + for(i=0;i { + err = e; + }); + + if (!res) { + return { + status: 400, + error: new Error("Unknown Error") + } + } + + const { status, statusText } = res; + if (err) { + return { + status, + error: err + } + } + + if (status !== 200) { + return { + status, + error: new Error(statusText || "Unknown Error") + } + } + + const data = await res.json(); + if (!data) { + return { + status, + error: new Error(`Failed to load data: ${route}`) + } + } + return { + status, + data + } +} + +export const icons = { + search: '', + extensions: '', + conflicts: '', + passed: '', + download: '' +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/js/components-manager.js b/custom_nodes/ComfyUI-Manager/js/components-manager.js new file mode 100644 index 000000000..248a74d25 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/components-manager.js @@ -0,0 +1,809 @@ +import { app } from "../../scripts/app.js"; +import { api } from "../../scripts/api.js" +import { sleep, show_message } from "./common.js"; +import { GroupNodeConfig, GroupNodeHandler } from "../../extensions/core/groupNode.js"; +import { ComfyDialog, $el } from "../../scripts/ui.js"; + +let pack_map = {}; +let rpack_map = {}; + +export function getPureName(node) { + // group nodes/ + let category = null; + if(node.category) { + category = node.category.substring(12); + } + else { + category = node.constructor.category?.substring(12); + } + if(category) { + let purename = node.comfyClass.substring(category.length+1); + return purename; + } + else if(node.comfyClass.startsWith('workflow/')) { + return node.comfyClass.substring(9); + } + else { + return node.comfyClass; + } +} + +function isValidVersionString(version) { + const versionPattern = /^(\d+)\.(\d+)(\.(\d+))?$/; + + const match = version.match(versionPattern); + + return match !== null && + parseInt(match[1], 10) >= 0 && + parseInt(match[2], 10) >= 0 && + (!match[3] || parseInt(match[4], 10) >= 0); +} + +function register_pack_map(name, data) { + if(data.packname) { + pack_map[data.packname] = name; + rpack_map[name] = data; + } + else { + rpack_map[name] = data; + } +} + +function storeGroupNode(name, data, register=true) { + let extra = app.graph.extra; + if (!extra) app.graph.extra = extra = {}; + let groupNodes = extra.groupNodes; + if (!groupNodes) extra.groupNodes = groupNodes = {}; + groupNodes[name] = data; + + if(register) { + register_pack_map(name, data); + } +} + +export async function load_components() { + let data = await api.fetchApi('/manager/component/loads', {method: "POST"}); + let components = await data.json(); + + let start_time = Date.now(); + let failed = []; + let failed2 = []; + + for(let name in components) { + if(app.graph.extra?.groupNodes?.[name]) { + if(data) { + let data = components[name]; + + let category = data.packname; + if(data.category) { + category += "/" + data.category; + } + if(category == '') { + category = 'components'; + } + + const config = new GroupNodeConfig(name, data); + await config.registerType(category); + + register_pack_map(name, data); + continue; + } + } + + let nodeData = components[name]; + + storeGroupNode(name, nodeData); + + const config = new GroupNodeConfig(name, nodeData); + + while(true) { + try { + let category = nodeData.packname; + if(nodeData.category) { + category += "/" + nodeData.category; + } + if(category == '') { + category = 'components'; + } + + await config.registerType(category); + register_pack_map(name, nodeData); + break; + } + catch { + let elapsed_time = Date.now() - start_time; + if (elapsed_time > 5000) { + failed.push(name); + break; + } else { + await sleep(100); + } + } + } + } + + // fallback1 + for(let i in failed) { + let name = failed[i]; + + if(app.graph.extra?.groupNodes?.[name]) { + continue; + } + + let nodeData = components[name]; + + storeGroupNode(name, nodeData); + + const config = new GroupNodeConfig(name, nodeData); + while(true) { + try { + let category = nodeData.packname; + if(nodeData.workflow.category) { + category += "/" + nodeData.category; + } + if(category == '') { + category = 'components'; + } + + await config.registerType(category); + register_pack_map(name, nodeData); + break; + } + catch { + let elapsed_time = Date.now() - start_time; + if (elapsed_time > 10000) { + failed2.push(name); + break; + } else { + await sleep(100); + } + } + } + } + + // fallback2 + for(let name in failed2) { + let name = failed2[i]; + + let nodeData = components[name]; + + storeGroupNode(name, nodeData); + + const config = new GroupNodeConfig(name, nodeData); + while(true) { + try { + let category = nodeData.workflow.packname; + if(nodeData.workflow.category) { + category += "/" + nodeData.category; + } + if(category == '') { + category = 'components'; + } + + await config.registerType(category); + register_pack_map(name, nodeData); + break; + } + catch { + let elapsed_time = Date.now() - start_time; + if (elapsed_time > 30000) { + failed.push(name); + break; + } else { + await sleep(100); + } + } + } + } +} + +async function save_as_component(node, version, author, prefix, nodename, packname, category) { + let component_name = `${prefix}::${nodename}`; + + let subgraph = app.graph.extra?.groupNodes?.[component_name]; + if(!subgraph) { + subgraph = app.graph.extra?.groupNodes?.[getPureName(node)]; + } + + subgraph.version = version; + subgraph.author = author; + subgraph.datetime = Date.now(); + subgraph.packname = packname; + subgraph.category = category; + + let body = + { + name: component_name, + workflow: subgraph + }; + + pack_map[packname] = component_name; + rpack_map[component_name] = subgraph; + + const res = await api.fetchApi('/manager/component/save', { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + }); + + if(res.status == 200) { + storeGroupNode(component_name, subgraph); + const config = new GroupNodeConfig(component_name, subgraph); + + let category = body.workflow.packname; + if(body.workflow.category) { + category += "/" + body.workflow.category; + } + if(category == '') { + category = 'components'; + } + + await config.registerType(category); + + let path = await res.text(); + show_message(`Component '${component_name}' is saved into:\n${path}`); + } + else + show_message(`Failed to save component.`); +} + +async function import_component(component_name, component, mode) { + if(mode) { + let body = + { + name: component_name, + workflow: component + }; + + const res = await api.fetchApi('/manager/component/save', { + method: "POST", + headers: { "Content-Type": "application/json", }, + body: JSON.stringify(body) + }); + } + + let category = component.packname; + if(component.category) { + category += "/" + component.category; + } + if(category == '') { + category = 'components'; + } + + storeGroupNode(component_name, component); + const config = new GroupNodeConfig(component_name, component); + await config.registerType(category); +} + +function restore_to_loaded_component(component_name) { + if(rpack_map[component_name]) { + let component = rpack_map[component_name]; + storeGroupNode(component_name, component, false); + const config = new GroupNodeConfig(component_name, component); + config.registerType(component.category); + } +} + +// Using a timestamp prevents duplicate pastes and ensures the prevention of re-deletion of litegrapheditor_clipboard. +let last_paste_timestamp = null; + +function versionCompare(v1, v2) { + let ver1; + let ver2; + if(v1 && v1 != '') { + ver1 = v1.split('.'); + ver1[0] = parseInt(ver1[0]); + ver1[1] = parseInt(ver1[1]); + if(ver1.length == 2) + ver1.push(0); + else + ver1[2] = parseInt(ver2[2]); + } + else { + ver1 = [0,0,0]; + } + + if(v2 && v2 != '') { + ver2 = v2.split('.'); + ver2[0] = parseInt(ver2[0]); + ver2[1] = parseInt(ver2[1]); + if(ver2.length == 2) + ver2.push(0); + else + ver2[2] = parseInt(ver2[2]); + } + else { + ver2 = [0,0,0]; + } + + if(ver1[0] > ver2[0]) + return -1; + else if(ver1[0] < ver2[0]) + return 1; + + if(ver1[1] > ver2[1]) + return -1; + else if(ver1[1] < ver2[1]) + return 1; + + if(ver1[2] > ver2[2]) + return -1; + else if(ver1[2] < ver2[2]) + return 1; + + return 0; +} + +function checkVersion(name, component) { + let msg = ''; + if(rpack_map[name]) { + let old_version = rpack_map[name].version; + if(!old_version || old_version == '') { + msg = ` '${name}' Upgrade (V0.0 -> V${component.version})`; + } + else { + let c = versionCompare(old_version, component.version); + if(c < 0) { + msg = ` '${name}' Downgrade (V${old_version} -> V${component.version})`; + } + else if(c > 0) { + msg = ` '${name}' Upgrade (V${old_version} -> V${component.version})`; + } + else { + msg = ` '${name}' Same version (V${component.version})`; + } + } + } + else { + msg = `'${name}' NEW (V${component.version})`; + } + + return msg; +} + +function handle_import_components(components) { + let msg = 'Components:\n'; + let cnt = 0; + for(let name in components) { + let component = components[name]; + let v = checkVersion(name, component); + + if(cnt < 10) { + msg += v + '\n'; + } + else if (cnt == 10) { + msg += '...\n'; + } + else { + // do nothing + } + + cnt++; + } + + let last_name = null; + msg += '\nWill you load components?\n'; + if(confirm(msg)) { + let mode = confirm('\nWill you save components?\n(cancel=load without save)'); + + for(let name in components) { + let component = components[name]; + import_component(name, component, mode); + last_name = name; + } + + if(mode) { + show_message('Components are saved.'); + } + else { + show_message('Components are loaded.'); + } + } + + if(cnt == 1 && last_name) { + const node = LiteGraph.createNode(`workflow/${last_name}`); + node.pos = [app.canvas.graph_mouse[0], app.canvas.graph_mouse[1]]; + app.canvas.graph.add(node, false); + } +} + +function handlePaste(e) { + let data = (e.clipboardData || window.clipboardData); + const items = data.items; + for(const item of items) { + if(item.kind == 'string' && item.type == 'text/plain') { + data = data.getData("text/plain"); + try { + let json_data = JSON.parse(data); + if(json_data.kind == 'ComfyUI Components' && last_paste_timestamp != json_data.timestamp) { + last_paste_timestamp = json_data.timestamp; + handle_import_components(json_data.components); + + // disable paste node + localStorage.removeItem("litegrapheditor_clipboard", null); + } + else { + console.log('This components are already pasted: ignored'); + } + } + catch { + // nothing to do + } + } + } +} + +document.addEventListener("paste", handlePaste); + + +export class ComponentBuilderDialog extends ComfyDialog { + constructor() { + super(); + } + + clear() { + while (this.element.children.length) { + this.element.removeChild(this.element.children[0]); + } + } + + show() { + this.invalidateControl(); + + this.element.style.display = "block"; + this.element.style.zIndex = 10001; + this.element.style.width = "500px"; + this.element.style.height = "480px"; + } + + invalidateControl() { + this.clear(); + + let self = this; + + const close_button = $el("button", { id: "cm-close-button", type: "button", textContent: "Close", onclick: () => self.close() }); + this.save_button = $el("button", + { id: "cm-save-button", type: "button", textContent: "Save", onclick: () => + { + save_as_component(self.target_node, self.version_string.value.trim(), self.author.value.trim(), self.node_prefix.value.trim(), + self.getNodeName(), self.getPackName(), self.category.value.trim()); + } + }); + + let default_nodename = getPureName(this.target_node).trim(); + + let groupNode = app.graph.extra.groupNodes[default_nodename]; + let default_packname = groupNode.packname; + if(!default_packname) { + default_packname = ''; + } + + let default_category = groupNode.category; + if(!default_category) { + default_category = ''; + } + + this.default_ver = groupNode.version; + if(!this.default_ver) { + this.default_ver = '0.0'; + } + + let default_author = groupNode.author; + if(!default_author) { + default_author = ''; + } + + let delimiterIndex = default_nodename.indexOf('::'); + let default_prefix = ""; + if(delimiterIndex != -1) { + default_prefix = default_nodename.substring(0, delimiterIndex); + default_nodename = default_nodename.substring(delimiterIndex + 2); + } + + if(!default_prefix) { + this.save_button.disabled = true; + } + + this.pack_list = this.createPackListCombo(); + + let version_string = this.createLabeledInput('input version (e.g. 1.0)', '*Version : ', this.default_ver); + this.version_string = version_string[1]; + this.version_string.disabled = true; + + let author = this.createLabeledInput('input author (e.g. Dr.Lt.Data)', 'Author : ', default_author); + this.author = author[1]; + + let node_prefix = this.createLabeledInput('input node prefix (e.g. mypack)', '*Prefix : ', default_prefix); + this.node_prefix = node_prefix[1]; + + let manual_nodename = this.createLabeledInput('input node name (e.g. MAKE_BASIC_PIPE)', 'Nodename : ', default_nodename); + this.manual_nodename = manual_nodename[1]; + + let manual_packname = this.createLabeledInput('input pack name (e.g. mypack)', 'Packname : ', default_packname); + this.manual_packname = manual_packname[1]; + + let category = this.createLabeledInput('input category (e.g. util/pipe)', 'Category : ', default_category); + this.category = category[1]; + + this.node_label = this.createNodeLabel(); + + let author_mode = this.createAuthorModeCheck(); + this.author_mode = author_mode[0]; + + const content = + $el("div.comfy-modal-content", + [ + $el("tr.cm-title", {}, [ + $el("font", {size:6, color:"white"}, [`ComfyUI-Manager: Component Builder`])] + ), + $el("br", {}, []), + $el("div.cm-menu-container", + [ + author_mode[0], + author_mode[1], + category[0], + author[0], + node_prefix[0], + manual_nodename[0], + manual_packname[0], + version_string[0], + this.pack_list, + $el("br", {}, []), + this.node_label + ]), + + $el("br", {}, []), + this.save_button, + close_button, + ] + ); + + content.style.width = '100%'; + content.style.height = '100%'; + + this.element = $el("div.comfy-modal", { id:'cm-manager-dialog', parent: document.body }, [ content ]); + } + + validateInput() { + let msg = ""; + + if(!isValidVersionString(this.version_string.value)) { + msg += 'Invalid version string: '+event.value+"\n"; + } + + if(this.node_prefix.value.trim() == '') { + msg += 'Node prefix cannot be empty\n'; + } + + if(this.manual_nodename.value.trim() == '') { + msg += 'Node name cannot be empty\n'; + } + + if(msg != '') { +// alert(msg); + } + + this.save_button.disabled = msg != ""; + } + + getPackName() { + if(this.pack_list.selectedIndex == 0) { + return this.manual_packname.value.trim(); + } + + return this.pack_list.value.trim(); + } + + getNodeName() { + if(this.manual_nodename.value.trim() != '') { + return this.manual_nodename.value.trim(); + } + + return getPureName(this.target_node); + } + + createAuthorModeCheck() { + let check = $el("input",{type:'checkbox', id:"author-mode"},[]) + const check_label = $el("label",{for:"author-mode"},["Enable author mode"]); + check_label.style.color = "var(--fg-color)"; + check_label.style.cursor = "pointer"; + check.checked = false; + + let self = this; + check.onchange = () => { + self.version_string.disabled = !check.checked; + + if(!check.checked) { + self.version_string.value = self.default_ver; + } + else { + alert('If you are not the author, it is not recommended to change the version, as it may cause component update issues.'); + } + }; + + return [check, check_label]; + } + + createNodeLabel() { + let label = $el('p'); + label.className = 'cb-node-label'; + if(this.target_node.comfyClass.includes('::')) + label.textContent = getPureName(this.target_node); + else + label.textContent = " _::" + getPureName(this.target_node); + return label; + } + + createLabeledInput(placeholder, label, value) { + let textbox = $el('input.cb-widget-input', {type:'text', placeholder:placeholder, value:value}, []); + + let self = this; + textbox.onchange = () => { + this.validateInput.call(self); + this.node_label.textContent = this.node_prefix.value + "::" + this.manual_nodename.value; + } + let row = $el('span.cb-widget', {}, [ $el('span.cb-widget-input-label', label), textbox]); + + return [row, textbox]; + } + + createPackListCombo() { + let combo = document.createElement("select"); + combo.className = "cb-widget"; + let default_packname_option = { value: '##manual', text: 'Packname: Manual' }; + + combo.appendChild($el('option', default_packname_option, [])); + for(let name in pack_map) { + combo.appendChild($el('option', { value: name, text: 'Packname: '+ name }, [])); + } + + let self = this; + combo.onchange = function () { + if(combo.selectedIndex == 0) { + self.manual_packname.disabled = false; + } + else { + self.manual_packname.disabled = true; + } + }; + + return combo; + } +} + +let orig_handleFile = app.handleFile; + +function handleFile(file) { + if (file.name?.endsWith(".json") || file.name?.endsWith(".pack")) { + const reader = new FileReader(); + reader.onload = async () => { + let is_component = false; + const jsonContent = JSON.parse(reader.result); + for(let name in jsonContent) { + let cand = jsonContent[name]; + is_component = cand.datetime && cand.version; + break; + } + + if(is_component) { + handle_import_components(jsonContent); + } + else { + orig_handleFile.call(app, file); + } + }; + reader.readAsText(file); + + return; + } + + orig_handleFile.call(app, file); +} + +app.handleFile = handleFile; + +let current_component_policy = 'workflow'; +try { + api.fetchApi('/manager/component/policy') + .then(response => response.text()) + .then(data => { current_component_policy = data; }); +} +catch {} + +function getChangedVersion(groupNodes) { + if(!Object.keys(pack_map).length || !groupNodes) + return null; + + let res = {}; + for(let component_name in groupNodes) { + let data = groupNodes[component_name]; + + if(rpack_map[component_name]) { + let v = versionCompare(data.version, rpack_map[component_name].version); + res[component_name] = v; + } + } + + return res; +} + +const loadGraphData = app.loadGraphData; +app.loadGraphData = async function () { + if(arguments.length == 0) + return await loadGraphData.apply(this, arguments); + + let graphData = arguments[0]; + let groupNodes = graphData.extra?.groupNodes; + let res = getChangedVersion(groupNodes); + + if(res) { + let target_components = null; + switch(current_component_policy) { + case 'higher': + target_components = Object.keys(res).filter(key => res[key] == 1); + break; + + case 'mine': + target_components = Object.keys(res); + break; + + default: + // do nothing + } + + if(target_components) { + for(let i in target_components) { + let component_name = target_components[i]; + let component = rpack_map[component_name]; + if(component && graphData.extra?.groupNodes) { + graphData.extra.groupNodes[component_name] = component; + } + } + } + } + else { + console.log('Empty components: policy ignored'); + } + + arguments[0] = graphData; + return await loadGraphData.apply(this, arguments); +}; + +export function set_component_policy(v) { + current_component_policy = v; +} + +let graphToPrompt = app.graphToPrompt; +app.graphToPrompt = async function () { + let p = await graphToPrompt.call(app); + try { + let groupNodes = p.workflow.extra?.groupNodes; + if(groupNodes) { + p.workflow.extra = { ... p.workflow.extra}; + + // get used group nodes + let used_group_nodes = new Set(); + for(let node of p.workflow.nodes) { + if(node.type.startsWith('workflow/')) { + used_group_nodes.add(node.type.substring(9)); + } + } + + // remove unused group nodes + let new_groupNodes = {}; + for (let key in p.workflow.extra.groupNodes) { + if (used_group_nodes.has(key)) { + new_groupNodes[key] = p.workflow.extra.groupNodes[key]; + } + } + p.workflow.extra.groupNodes = new_groupNodes; + } + } + catch(e) { + console.log(`Failed to filtering group nodes: ${e}`); + } + + return p; +} diff --git a/custom_nodes/ComfyUI-Manager/js/custom-nodes-manager.js b/custom_nodes/ComfyUI-Manager/js/custom-nodes-manager.js new file mode 100644 index 000000000..eccdd6839 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/custom-nodes-manager.js @@ -0,0 +1,1381 @@ +import { app } from "../../scripts/app.js"; +import { $el } from "../../scripts/ui.js"; +import { + manager_instance, rebootAPI, install_via_git_url, + fetchData, md5, icons +} from "./common.js"; + +// https://cenfun.github.io/turbogrid/api.html +import TG from "./turbogrid.esm.js"; + +const pageCss = ` +.cn-manager { + --grid-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; + z-index: 10001; + width: 80%; + height: 80%; + display: flex; + flex-direction: column; + gap: 10px; + color: var(--fg-color); + font-family: arial, sans-serif; +} + +.cn-manager .cn-flex-auto { + flex: auto; +} + +.cn-manager button { + font-size: 16px; + color: var(--input-text); + background-color: var(--comfy-input-bg); + border-radius: 8px; + border-color: var(--border-color); + border-style: solid; + margin: 0; + padding: 4px 8px; + min-width: 100px; +} + +.cn-manager button:disabled, +.cn-manager input:disabled, +.cn-manager select:disabled { + color: gray; +} + +.cn-manager button:disabled { + background-color: var(--comfy-input-bg); +} + +.cn-manager .cn-manager-restart { + display: none; + background-color: #500000; + color: white; +} + +.cn-manager-header { + display: flex; + flex-wrap: wrap; + gap: 5px; + align-items: center; + padding: 0 5px; +} + +.cn-manager-header label { + display: flex; + gap: 5px; + align-items: center; +} + +.cn-manager-filter { + height: 28px; + line-height: 28px; +} + +.cn-manager-keywords { + height: 28px; + line-height: 28px; + padding: 0 5px 0 26px; + background-size: 16px; + background-position: 5px center; + background-repeat: no-repeat; + background-image: url("data:image/svg+xml;charset=utf8,${encodeURIComponent(icons.search.replace("currentColor", "#888"))}"); +} + +.cn-manager-status { + padding-left: 10px; +} + +.cn-manager-grid { + flex: auto; + border: 1px solid var(--border-color); + overflow: hidden; +} + +.cn-manager-selection { + display: flex; + flex-wrap: wrap; + gap: 10px; + align-items: center; +} + +.cn-manager-message { + +} + +.cn-manager-footer { + display: flex; + flex-wrap: wrap; + gap: 10px; + align-items: center; +} + +.cn-manager-grid .tg-turbogrid { + font-family: var(--grid-font); + font-size: 15px; + background: var(--bg-color); +} + +.cn-manager-grid .cn-node-name a { + color: skyblue; + text-decoration: none; + word-break: break-word; +} + +.cn-manager-grid .cn-node-desc a { + color: #5555FF; + font-weight: bold; + text-decoration: none; +} + +.cn-manager-grid .tg-cell a:hover { + text-decoration: underline; +} + +.cn-manager-grid .cn-extensions-button, +.cn-manager-grid .cn-conflicts-button { + display: inline-block; + width: 20px; + height: 20px; + color: green; + border: none; + padding: 0; + margin: 0; + background: none; + min-width: 20px; +} + +.cn-manager-grid .cn-conflicts-button { + color: orange; +} + +.cn-manager-grid .cn-extensions-list, +.cn-manager-grid .cn-conflicts-list { + line-height: normal; + text-align: left; + max-height: 80%; + min-height: 200px; + min-width: 300px; + overflow-y: auto; + font-size: 12px; + border-radius: 5px; + padding: 10px; + filter: drop-shadow(2px 5px 5px rgb(0 0 0 / 30%)); + white-space: normal; +} + +.cn-manager-grid .cn-extensions-list { + border-color: var(--bg-color); +} + +.cn-manager-grid .cn-conflicts-list { + background-color: #CCCC55; + color: #AA3333; +} + +.cn-manager-grid .cn-extensions-list h3, +.cn-manager-grid .cn-conflicts-list h3 { + margin: 0; + padding: 5px 0; + color: #000; +} + +.cn-tag-list { + display: flex; + flex-wrap: wrap; + gap: 5px; + align-items: center; + margin-bottom: 5px; +} + +.cn-tag-list > div { + background-color: var(--border-color); + border-radius: 5px; + padding: 0 5px; +} + +.cn-install-buttons { + display: flex; + flex-direction: column; + gap: 3px; + padding: 3px; + align-items: center; + justify-content: center; + height: 100%; +} + +.cn-selected-buttons { + display: flex; + gap: 5px; + align-items: center; + padding-right: 20px; +} + +.cn-manager .cn-btn-enable { + background-color: blue; + color: white; +} + +.cn-manager .cn-btn-disable { + background-color: MediumSlateBlue; + color: white; +} + +.cn-manager .cn-btn-update { + background-color: blue; + color: white; +} + +.cn-manager .cn-btn-try-update { + background-color: Gray; + color: white; +} + +.cn-manager .cn-btn-try-fix { + background-color: #6495ED; + color: white; +} + +.cn-manager .cn-btn-install { + background-color: black; + color: white; +} + +.cn-manager .cn-btn-try-install { + background-color: Gray; + color: white; +} + +.cn-manager .cn-btn-uninstall { + background-color: red; + color: white; +} + +@keyframes cn-btn-loading-bg { + 0% { + left: 0; + } + 100% { + left: -105px; + } +} + +.cn-manager button.cn-btn-loading { + position: relative; + overflow: hidden; + border-color: rgb(0 119 207 / 80%); + background-color: var(--comfy-input-bg); +} + +.cn-manager button.cn-btn-loading::after { + position: absolute; + top: 0; + left: 0; + content: ""; + width: 500px; + height: 100%; + background-image: repeating-linear-gradient( + -45deg, + rgb(0 119 207 / 30%), + rgb(0 119 207 / 30%) 10px, + transparent 10px, + transparent 15px + ); + animation: cn-btn-loading-bg 2s linear infinite; +} + +.cn-manager-light .cn-node-name a { + color: blue; +} + +.cn-manager-light .cm-warn-note { + background-color: #ccc !important; +} + +.cn-manager-light .cn-btn-install { + background-color: #333; +} + +`; + +const pageHtml = ` +
+ + +
+
+
+
+
+
+
+ +`; + +const ShowMode = { + NORMAL: "Normal", + UPDATE: "Update", + MISSING: "Missing", + ALTERNATIVES: "Alternatives" +}; + +export class CustomNodesManager { + static instance = null; + static ShowMode = ShowMode; + + constructor(app, manager_dialog) { + this.app = app; + this.manager_dialog = manager_dialog; + this.id = "cn-manager"; + + app.registerExtension({ + name: "Comfy.CustomNodesManager", + afterConfigureGraph: (missingNodeTypes) => { + const item = this.getFilterItem(ShowMode.MISSING); + if (item) { + item.hasData = false; + item.hashMap = null; + } + } + }); + + this.filter = ''; + this.keywords = ''; + this.restartMap = {}; + + this.init(); + } + + init() { + + if (!document.querySelector(`style[context="${this.id}"]`)) { + const $style = document.createElement("style"); + $style.setAttribute("context", this.id); + $style.innerHTML = pageCss; + document.head.appendChild($style); + } + + this.element = $el("div", { + parent: document.body, + className: "comfy-modal cn-manager" + }); + this.element.innerHTML = pageHtml; + this.initFilter(); + this.bindEvents(); + this.initGrid(); + } + + initFilter() { + const $filter = this.element.querySelector(".cn-manager-filter"); + const filterList = [{ + label: "All", + value: "", + hasData: true + }, { + label: "Installed", + value: "True", + hasData: true + }, { + label: "Disabled", + value: "Disabled", + hasData: true + }, { + label: "Import Failed", + value: "Fail", + hasData: true + }, { + label: "Not Installed", + value: "False", + hasData: true + }, { + label: "Unknown", + value: "None", + hasData: true + }, { + label: "Update", + value: ShowMode.UPDATE, + hasData: false + }, { + label: "Missing", + value: ShowMode.MISSING, + hasData: false + }, { + label: "Alternatives of A1111", + value: ShowMode.ALTERNATIVES, + hasData: false + }]; + this.filterList = filterList; + $filter.innerHTML = filterList.map(item => { + return `` + }).join(""); + } + + getFilterItem(filter) { + return this.filterList.find(it => it.value === filter) + } + + getInstallButtons(installed, title) { + + const buttons = { + "enable": { + label: "Enable", + mode: "toggle_active" + }, + "disable": { + label: "Disable", + mode: "toggle_active" + }, + + "update": { + label: "Update", + mode: "update" + }, + "try-update": { + label: "Try update", + mode: "update" + }, + + "try-fix": { + label: "Try fix", + mode: "fix" + }, + + "install": { + label: "Install", + mode: "install" + }, + "try-install": { + label: "Try install", + mode: "install" + }, + "uninstall": { + label: "Uninstall", + mode: "uninstall" + } + } + + const installGroups = { + "Disabled": ["enable", "uninstall"], + "Update": ["update", "disable", "uninstall"], + "Fail": ["try-fix", "uninstall"], + "True": ["try-update", "disable", "uninstall"], + "False": ["install"], + 'None': ["try-install"] + } + + if (!manager_instance.update_check_checkbox.checked) { + installGroups.True = installGroups.True.filter(it => it !== "try-update"); + } + + if (title === "ComfyUI-Manager") { + installGroups.True = installGroups.True.filter(it => it !== "disable"); + } + + const list = installGroups[installed]; + if (!list) { + return ""; + } + + return list.map(id => { + const bt = buttons[id]; + return ``; + }).join(""); + } + + getButton(target) { + if(!target) { + return; + } + const mode = target.getAttribute("mode"); + if (!mode) { + return; + } + const group = target.getAttribute("group"); + if (!group) { + return; + } + return { + group, + mode, + target, + label: target.innerText + } + } + + bindEvents() { + const eventsMap = { + ".cn-manager-filter": { + change: (e) => { + + if (this.grid) { + this.grid.selectAll(false); + } + + const value = e.target.value + this.filter = value; + const item = this.getFilterItem(value); + if (item && !item.hasData) { + this.loadData(value); + return; + } + this.updateGrid(); + } + }, + + ".cn-manager-keywords": { + input: (e) => { + const keywords = `${e.target.value}`.trim(); + if (keywords !== this.keywords) { + this.keywords = keywords; + this.updateGrid(); + } + }, + focus: (e) => e.target.select() + }, + + ".cn-manager-selection": { + click: (e) => { + const btn = this.getButton(e.target); + if (btn) { + const nodes = this.selectedMap[btn.group]; + if (nodes) { + this.installNodes(nodes, btn); + } + } + } + }, + + ".cn-manager-close": { + click: (e) => this.close() + }, + + ".cn-manager-restart": { + click: () => { + if(rebootAPI()) { + this.close(); + this.manager_dialog.close(); + } + } + }, + + ".cn-manager-check-update": { + click: (e) => { + e.target.classList.add("cn-btn-loading"); + this.setFilter(ShowMode.UPDATE); + this.loadData(ShowMode.UPDATE); + } + }, + + ".cn-manager-check-missing": { + click: (e) => { + e.target.classList.add("cn-btn-loading"); + this.setFilter(ShowMode.MISSING); + this.loadData(ShowMode.MISSING); + } + }, + + ".cn-manager-install-url": { + click: (e) => { + const url = prompt("Please enter the URL of the Git repository to install", ""); + if (url !== null) { + install_via_git_url(url, this.manager_dialog); + } + } + } + }; + Object.keys(eventsMap).forEach(selector => { + const target = this.element.querySelector(selector); + if (target) { + const events = eventsMap[selector]; + if (events) { + Object.keys(events).forEach(type => { + target.addEventListener(type, events[type]); + }); + } + } + }); + } + + // =========================================================================================== + + initGrid() { + const container = this.element.querySelector(".cn-manager-grid"); + const grid = new TG.Grid(container); + this.grid = grid; + + let prevViewRowsLength = -1; + grid.bind('onUpdated', (e, d) => { + + const viewRows = grid.viewRows; + if (viewRows.length !== prevViewRowsLength) { + prevViewRowsLength = viewRows.length; + this.showStatus(`${prevViewRowsLength.toLocaleString()} custom nodes`); + } + + }); + + grid.bind('onSelectChanged', (e, changes) => { + this.renderSelected(); + }); + + grid.bind('onClick', (e, d) => { + const btn = this.getButton(d.e.target); + if (btn) { + this.installNodes([d.rowItem.hash], btn, d.rowItem.title); + } + }); + + grid.setOption({ + theme: 'dark', + selectVisible: true, + selectMultiple: true, + selectAllVisible: true, + + textSelectable: true, + scrollbarRound: true, + + frozenColumn: 1, + rowNotFound: "No Results", + + rowHeight: 40, + bindWindowResize: true, + bindContainerResize: true, + + cellResizeObserver: (rowItem, columnItem) => { + const autoHeightColumns = ['title', 'installed', 'description', "alternatives"]; + return autoHeightColumns.includes(columnItem.id) + }, + + // updateGrid handler for filter and keywords + rowFilter: (rowItem) => { + + const searchableColumns = ["title", "author", "description"]; + if (this.hasAlternatives()) { + searchableColumns.push("alternatives"); + } + + let shouldShown = grid.highlightKeywordsFilter(rowItem, searchableColumns, this.keywords); + + if (shouldShown) { + if(this.filter && rowItem.filterTypes) { + shouldShown = rowItem.filterTypes.includes(this.filter); + } + } + + return shouldShown; + } + }); + + } + + hasAlternatives() { + return this.filter === ShowMode.ALTERNATIVES + } + + renderGrid() { + + // update theme + const colorPalette = this.app.ui.settings.settingsValues['Comfy.ColorPalette']; + Array.from(this.element.classList).forEach(cn => { + if (cn.startsWith("cn-manager-")) { + this.element.classList.remove(cn); + } + }); + this.element.classList.add(`cn-manager-${colorPalette}`); + + const options = { + theme: colorPalette === "light" ? "" : "dark" + }; + + const rows = this.custom_nodes || []; + rows.forEach((item, i) => { + item.id = i + 1; + const nodeKey = item.files[0]; + const extensionInfo = this.extension_mappings[nodeKey]; + if(extensionInfo) { + const { extensions, conflicts } = extensionInfo; + if (extensions.length) { + item.extensions = extensions.length; + item.extensionsList = extensions; + } + if (conflicts) { + item.conflicts = conflicts.length; + item.conflictsList = conflicts; + } + } + }); + + const columns = [{ + id: 'id', + name: 'ID', + width: 50, + align: 'center' + }, { + id: 'title', + name: 'Title', + width: 200, + minWidth: 100, + maxWidth: 500, + classMap: 'cn-node-name', + formatter: (title, rowItem, columnItem) => { + return `${rowItem.installed === 'Fail' ? '(IMPORT FAILED)' : ''} + ${title}`; + } + }, { + id: 'installed', + name: 'Install', + width: 130, + minWidth: 110, + maxWidth: 200, + sortable: false, + align: 'center', + formatter: (installed, rowItem, columnItem) => { + if (rowItem.restart) { + return `Restart Required`; + } + const buttons = this.getInstallButtons(installed, rowItem.title); + return `
${buttons}
`; + } + }, { + id: "alternatives", + name: "Alternatives", + width: 400, + maxWidth: 5000, + invisible: !this.hasAlternatives(), + classMap: 'cn-node-desc' + }, { + id: 'description', + name: 'Description', + width: 400, + maxWidth: 5000, + classMap: 'cn-node-desc' + }, { + id: "extensions", + name: "Extensions", + width: 80, + align: 'center', + formatter: (extensions, rowItem, columnItem) => { + const extensionsList = rowItem.extensionsList; + if (!extensionsList) { + return; + } + const list = []; + const eId = `popover_extensions_${columnItem.id}_${rowItem.tg_index}`; + list.push(``) + list.push(`
`) + list.push(`

【${rowItem.title}】Extension Nodes (${extensionsList.length})

`); + extensionsList.forEach(en => { + list.push(`
  • ${en}
  • `); + }) + list.push("
    "); + return list.join(""); + } + }, { + id: "conflicts", + name: "Conflicts", + width: 80, + align: 'center', + formatter: (conflicts, rowItem, columnItem) => { + const conflictsList = rowItem.conflictsList; + if (!conflictsList) { + return; + } + const list = []; + const cId = `popover_conflicts_${columnItem.id}_${rowItem.tg_index}`; + list.push(``) + list.push(`
    `) + list.push(`

    【${rowItem.title}】Conflicted Nodes (${conflictsList.length})

    `); + conflictsList.forEach(en => { + let [node_name, extension_name] = en; + extension_name = extension_name.split('/').filter(it => it).pop(); + if(extension_name.endsWith('.git')) { + extension_name = extension_name.slice(0, -4); + } + list.push(`
  • ${node_name} [${extension_name}]
  • `); + }) + list.push("
    "); + return list.join(""); + } + }, { + id: 'author', + name: 'Author', + width: 120, + classMap: "cn-node-author", + formatter: (author, rowItem, columnItem) => { + if (rowItem.trust) { + return `✅ ${author}`; + } + return author; + } + }, { + id: 'stars', + name: '★', + align: 'center', + classMap: "cn-node-stars", + formatter: (stars) => { + if (stars < 0) { + return 'N/A'; + } + if (typeof stars === 'number') { + return stars.toLocaleString(); + } + return stars; + } + }, { + id: 'last_update', + name: 'Last Update', + align: 'center', + type: 'date', + width: 100, + classMap: "cn-node-last-update", + formatter: (last_update) => { + if (last_update < 0) { + return 'N/A'; + } + return `${last_update}`.split(' ')[0]; + } + }]; + + this.grid.setData({ + options, + rows, + columns + }); + + this.grid.render(); + + } + + updateGrid() { + if (this.grid) { + this.grid.update(); + if (this.hasAlternatives()) { + this.grid.showColumn("alternatives"); + } else { + this.grid.hideColumn("alternatives"); + } + } + } + + // =========================================================================================== + + renderSelected() { + const selectedList = this.grid.getSelectedRows(); + if (!selectedList.length) { + this.showSelection(""); + return; + } + + const selectedMap = {}; + selectedList.forEach(item => { + let type = item.installed; + if (item.restart) { + type = "Restart Required"; + } + if (selectedMap[type]) { + selectedMap[type].push(item.hash); + } else { + selectedMap[type] = [item.hash]; + } + }); + + this.selectedMap = selectedMap; + + const list = []; + Object.keys(selectedMap).forEach(v => { + const filterItem = this.getFilterItem(v); + list.push(`
    + Selected ${selectedMap[v].length} ${filterItem ? filterItem.label : v} + ${this.grid.hasMask ? "" : this.getInstallButtons(v)} +
    `); + }); + + this.showSelection(list.join("")); + } + + focusInstall(item, mode) { + const cellNode = this.grid.getCellNode(item, "installed"); + if (cellNode) { + const cellBtn = cellNode.querySelector(`button[mode="${mode}"]`); + if (cellBtn) { + cellBtn.classList.add("cn-btn-loading"); + return true + } + } + } + + async installNodes(list, btn, title) { + + const { target, label, mode} = btn; + + if(mode === "uninstall") { + title = title || `${list.length} custom nodes`; + if (!confirm(`Are you sure uninstall ${title}?`)) { + return; + } + } + + target.classList.add("cn-btn-loading"); + this.showLoading(); + this.showError(""); + + let needRestart = false; + let errorMsg = ""; + for (const hash of list) { + + const item = this.grid.getRowItemBy("hash", hash); + if (!item) { + errorMsg = `Not found custom node: ${hash}`; + break; + } + + this.grid.scrollRowIntoView(item); + + if (!this.focusInstall(item, mode)) { + this.grid.onNextUpdated(() => { + this.focusInstall(item, mode); + }); + } + + this.showStatus(`${label} ${item.title} ...`); + + const data = item.originalData; + const res = await fetchData(`/customnode/${mode}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data) + }); + + if (res.error) { + + errorMsg = `${item.title} ${mode} failed: `; + if(res.status == 403) { + errorMsg += `This action is not allowed with this security level configuration.`; + } else if(res.status == 404) { + errorMsg += `With the current security level configuration, only custom nodes from the "default channel" can be installed.`; + } else { + errorMsg += res.error.message; + } + + break; + } + + needRestart = true; + + this.grid.setRowSelected(item, false); + item.restart = true; + this.restartMap[item.hash] = true; + this.grid.updateCell(item, "installed"); + + //console.log(res.data); + + } + + this.hideLoading(); + target.classList.remove("cn-btn-loading"); + + if (errorMsg) { + this.showError(errorMsg); + } else { + this.showStatus(`${label} ${list.length} custom node(s) successfully`); + } + + if (needRestart) { + this.showRestart(); + this.showMessage(`To apply the installed/updated/disabled/enabled custom node, please restart ComfyUI. And refresh browser.`, "red") + } + + } + + // =========================================================================================== + + async getExtensionMappings() { + const mode = manager_instance.datasrc_combo.value; + this.showStatus(`Loading extension mappings (${mode}) ...`); + const res = await fetchData(`/customnode/getmappings?mode=${mode}`); + if (res.error) { + console.log(res.error); + return {} + } + + const data = res.data; + + const extension_mappings = {}; + const conflicts_map = {}; + Object.keys(data).forEach(k => { + const [extensions, metadata] = data[k]; + extension_mappings[k] = { + extensions, + metadata + } + extensions.forEach(node => { + let l = conflicts_map[node]; + if(!l) { + l = []; + conflicts_map[node] = l; + } + l.push(k); + }) + }) + + Object.keys(conflicts_map).forEach(node => { + const list = conflicts_map[node]; + if(list.length > 1) { + list.forEach(k => { + const item = extension_mappings[k]; + if(!item) { + console.log(`not found ${k}`) + return; + } + + if (!item.conflicts) { + item.conflicts = []; + } + list.forEach(key => { + if(k !== key) { + item.conflicts.push([node, key]) + } + }) + }) + } + }) + + return extension_mappings; + } + + async getMissingNodes() { + const mode = manager_instance.datasrc_combo.value; + this.showStatus(`Loading missing nodes (${mode}) ...`); + const res = await fetchData(`/customnode/getmappings?mode=${mode}`); + if (res.error) { + this.showError(`Failed to get custom node mappings: ${res.error}`); + return; + } + + const mappings = res.data; + + // build regex->url map + const regex_to_url = []; + this.custom_nodes.forEach(node => { + if(node.nodename_pattern) { + regex_to_url.push({ + regex: new RegExp(node.nodename_pattern), + url: node.files[0] + }); + } + }); + + // build name->url map + const name_to_urls = {}; + for (const url in mappings) { + const names = mappings[url]; + + for(const name in names[0]) { + let v = name_to_urls[names[0][name]]; + if(v == undefined) { + v = []; + name_to_urls[names[0][name]] = v; + } + v.push(url); + } + } + + const registered_nodes = new Set(); + for (let i in LiteGraph.registered_node_types) { + registered_nodes.add(LiteGraph.registered_node_types[i].type); + } + + const missing_nodes = new Set(); + const workflow = app.graph.serialize(); + const group_nodes = workflow.extra && workflow.extra.groupNodes ? workflow.extra.groupNodes : []; + let nodes = workflow.nodes; + + for (let i in group_nodes) { + let group_node = group_nodes[i]; + nodes = nodes.concat(group_node.nodes); + } + + for (let i in nodes) { + const node_type = nodes[i].type; + if(node_type.startsWith('workflow/')) + continue; + + if (!registered_nodes.has(node_type)) { + const urls = name_to_urls[node_type.trim()]; + if(urls) + urls.forEach(url => { + missing_nodes.add(url); + }); + else { + for(let j in regex_to_url) { + if(regex_to_url[j].regex.test(node_type)) { + missing_nodes.add(regex_to_url[j].url); + } + } + } + } + } + + const resUnresolved = await fetchData(`/component/get_unresolved`); + const unresolved = resUnresolved.data; + if (unresolved && unresolved.nodes) { + unresolved.nodes.forEach(node_type => { + const url = name_to_urls[node_type]; + if(url) { + missing_nodes.add(url); + } + }); + } + + const hashMap = {}; + this.custom_nodes.forEach(item => { + if (item.files.some(file => missing_nodes.has(file))) { + hashMap[item.hash] = true; + } + }); + return hashMap; + } + + async getAlternatives() { + + const mode = manager_instance.datasrc_combo.value; + this.showStatus(`Loading alternatives (${mode}) ...`); + const res = await fetchData(`/customnode/alternatives?mode=${mode}`); + if (res.error) { + this.showError(`Failed to get alternatives: ${res.error}`); + return []; + } + + const hashMap = {}; + const { items } = res.data; + + items.forEach(item => { + + const custom_node = this.custom_nodes.find(node => node.files.find(file => file === item.id)); + if (!custom_node) { + console.log(`Not found custom node: ${item.id}`); + return; + } + + const tags = `${item.tags}`.split(",").map(tag => { + return `
    ${tag.trim()}
    `; + }).join("") + + hashMap[custom_node.hash] = { + alternatives: `
    ${tags}
    ${item.description}` + } + + }); + + return hashMap + } + + async loadData(show_mode = ShowMode.NORMAL) { + this.show_mode = show_mode; + console.log("Show mode:", show_mode); + + this.showLoading(); + + this.extension_mappings = await this.getExtensionMappings(); + + const mode = manager_instance.datasrc_combo.value; + this.showStatus(`Loading custom nodes (${mode}) ...`); + + const skip_update = this.show_mode === ShowMode.UPDATE ? "" : "&skip_update=true"; + const res = await fetchData(`/customnode/getlist?mode=${mode}${skip_update}`); + if (res.error) { + this.showError("Failed to get custom node list."); + this.hideLoading(); + return + } + + const { channel, custom_nodes} = res.data; + this.channel = channel; + this.custom_nodes = custom_nodes; + + if(this.channel !== 'default') { + this.element.querySelector(".cn-manager-channel").innerHTML = `Channel: ${this.channel} (Incomplete list)`; + } + + for (const item of custom_nodes) { + item.originalData = JSON.parse(JSON.stringify(item)); + const message = item.title + item.files[0]; + item.hash = md5(message); + } + + const filterItem = this.getFilterItem(this.show_mode); + if(filterItem) { + let hashMap; + if(this.show_mode == ShowMode.UPDATE) { + hashMap = {}; + custom_nodes.forEach(it => { + if (it.installed === "Update") { + hashMap[it.hash] = true; + } + }); + } else if(this.show_mode == ShowMode.MISSING) { + hashMap = await this.getMissingNodes(); + } else if(this.show_mode == ShowMode.ALTERNATIVES) { + hashMap = await this.getAlternatives(); + } + filterItem.hashMap = hashMap; + filterItem.hasData = true; + } + + custom_nodes.forEach(nodeItem => { + if (this.restartMap[nodeItem.hash]) { + nodeItem.restart = true; + } + const filterTypes = new Set(); + this.filterList.forEach(filterItem => { + const { value, hashMap } = filterItem; + if (hashMap) { + const hashData = hashMap[nodeItem.hash] + if (hashData) { + filterTypes.add(value); + if (value === ShowMode.UPDATE) { + nodeItem.installed = "Update"; + } + if (typeof hashData === "object") { + Object.assign(nodeItem, hashData); + } + } + } else { + if (nodeItem.installed === value) { + filterTypes.add(value); + } + const map = { + "Update": "True", + "Disabled": "True", + "Fail": "True", + "None": "False" + } + if (map[nodeItem.installed]) { + filterTypes.add(map[nodeItem.installed]); + } + } + }); + nodeItem.filterTypes = Array.from(filterTypes); + }); + + this.renderGrid(); + + this.hideLoading(); + + } + + // =========================================================================================== + + showSelection(msg) { + this.element.querySelector(".cn-manager-selection").innerHTML = msg; + } + + showError(err) { + this.showMessage(err, "red"); + } + + showMessage(msg, color) { + if (color) { + msg = `${msg}`; + } + this.element.querySelector(".cn-manager-message").innerHTML = msg; + } + + showStatus(msg, color) { + if (color) { + msg = `${msg}`; + } + this.element.querySelector(".cn-manager-status").innerHTML = msg; + } + + showLoading() { + this.setDisabled(true); + if (this.grid) { + this.grid.showLoading(); + this.grid.showMask({ + opacity: 0.05 + }); + } + } + + hideLoading() { + this.setDisabled(false); + if (this.grid) { + this.grid.hideLoading(); + this.grid.hideMask(); + } + } + + setDisabled(disabled) { + + const $close = this.element.querySelector(".cn-manager-close"); + const $restart = this.element.querySelector(".cn-manager-restart"); + + const list = [ + ".cn-manager-header input", + ".cn-manager-header select", + ".cn-manager-footer button", + ".cn-manager-selection button" + ].map(s => { + return Array.from(this.element.querySelectorAll(s)); + }) + .flat() + .filter(it => { + return it !== $close && it !== $restart; + }); + + list.forEach($elem => { + if (disabled) { + $elem.setAttribute("disabled", "disabled"); + } else { + $elem.removeAttribute("disabled"); + } + }); + + Array.from(this.element.querySelectorAll(".cn-btn-loading")).forEach($elem => { + $elem.classList.remove("cn-btn-loading"); + }); + + } + + showRestart() { + this.element.querySelector(".cn-manager-restart").style.display = "block"; + } + + setFilter(filterValue) { + let filter = ""; + const filterItem = this.getFilterItem(filterValue); + if(filterItem) { + filter = filterItem.value; + } + this.filter = filter; + this.element.querySelector(".cn-manager-filter").value = filter; + } + + setKeywords(keywords = "") { + this.keywords = keywords; + this.element.querySelector(".cn-manager-keywords").value = keywords; + } + + show(show_mode) { + this.element.style.display = "flex"; + this.setFilter(show_mode); + this.setKeywords(""); + this.showSelection(""); + this.showMessage(""); + this.loadData(show_mode); + } + + close() { + this.element.style.display = "none"; + } +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/js/model-manager.js b/custom_nodes/ComfyUI-Manager/js/model-manager.js new file mode 100644 index 000000000..d92b46d05 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/model-manager.js @@ -0,0 +1,891 @@ +import { $el } from "../../scripts/ui.js"; +import { + manager_instance, rebootAPI, + fetchData, md5, icons +} from "./common.js"; + +// https://cenfun.github.io/turbogrid/api.html +import TG from "./turbogrid.esm.js"; + +const pageCss = ` +.cmm-manager { + --grid-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; + z-index: 10001; + width: 80%; + height: 80%; + display: flex; + flex-direction: column; + gap: 10px; + color: var(--fg-color); + font-family: arial, sans-serif; +} + +.cmm-manager .cmm-flex-auto { + flex: auto; +} + +.cmm-manager button { + font-size: 16px; + color: var(--input-text); + background-color: var(--comfy-input-bg); + border-radius: 8px; + border-color: var(--border-color); + border-style: solid; + margin: 0; + padding: 4px 8px; + min-width: 100px; +} + +.cmm-manager button:disabled, +.cmm-manager input:disabled, +.cmm-manager select:disabled { + color: gray; +} + +.cmm-manager button:disabled { + background-color: var(--comfy-input-bg); +} + +.cmm-manager-header { + display: flex; + flex-wrap: wrap; + gap: 5px; + align-items: center; + padding: 0 5px; +} + +.cmm-manager-header label { + display: flex; + gap: 5px; + align-items: center; +} + +.cmm-manager-type, +.cmm-manager-base, +.cmm-manager-filter { + height: 28px; + line-height: 28px; +} + +.cmm-manager-keywords { + height: 28px; + line-height: 28px; + padding: 0 5px 0 26px; + background-size: 16px; + background-position: 5px center; + background-repeat: no-repeat; + background-image: url("data:image/svg+xml;charset=utf8,${encodeURIComponent(icons.search.replace("currentColor", "#888"))}"); +} + +.cmm-manager-status { + padding-left: 10px; +} + +.cmm-manager-grid { + flex: auto; + border: 1px solid var(--border-color); + overflow: hidden; +} + +.cmm-manager-selection { + display: flex; + flex-wrap: wrap; + gap: 10px; + align-items: center; +} + +.cmm-manager-message { + +} + +.cmm-manager-footer { + display: flex; + flex-wrap: wrap; + gap: 10px; + align-items: center; +} + +.cmm-manager-grid .tg-turbogrid { + font-family: var(--grid-font); + font-size: 15px; + background: var(--bg-color); +} + +.cmm-manager-grid .cmm-node-name a { + color: skyblue; + text-decoration: none; + word-break: break-word; +} + +.cmm-manager-grid .cmm-node-desc a { + color: #5555FF; + font-weight: bold; + text-decoration: none; +} + +.cmm-manager-grid .tg-cell a:hover { + text-decoration: underline; +} + +.cmm-icon-passed { + width: 20px; + height: 20px; + position: absolute; + left: calc(50% - 10px); + top: calc(50% - 10px); +} + +.cmm-manager .cmm-btn-enable { + background-color: blue; + color: white; +} + +.cmm-manager .cmm-btn-disable { + background-color: MediumSlateBlue; + color: white; +} + +.cmm-manager .cmm-btn-install { + background-color: black; + color: white; +} + +.cmm-btn-download { + width: 18px; + height: 18px; + position: absolute; + left: calc(50% - 10px); + top: calc(50% - 10px); + cursor: pointer; + opacity: 0.8; + color: #fff; +} + +.cmm-btn-download:hover { + opacity: 1; +} + +.cmm-manager-light .cmm-btn-download { + color: #000; +} + +@keyframes cmm-btn-loading-bg { + 0% { + left: 0; + } + 100% { + left: -105px; + } +} + +.cmm-manager button.cmm-btn-loading { + position: relative; + overflow: hidden; + border-color: rgb(0 119 207 / 80%); + background-color: var(--comfy-input-bg); +} + +.cmm-manager button.cmm-btn-loading::after { + position: absolute; + top: 0; + left: 0; + content: ""; + width: 500px; + height: 100%; + background-image: repeating-linear-gradient( + -45deg, + rgb(0 119 207 / 30%), + rgb(0 119 207 / 30%) 10px, + transparent 10px, + transparent 15px + ); + animation: cmm-btn-loading-bg 2s linear infinite; +} + +.cmm-manager-light .cmm-node-name a { + color: blue; +} + +.cmm-manager-light .cm-warn-note { + background-color: #ccc !important; +} + +.cmm-manager-light .cmm-btn-install { + background-color: #333; +} + +`; + +const pageHtml = ` +
    + + + + +
    +
    +
    +
    +
    +
    + +`; + +export class ModelManager { + static instance = null; + + constructor(app, manager_dialog) { + this.app = app; + this.manager_dialog = manager_dialog; + this.id = "cmm-manager"; + + this.filter = ''; + this.type = ''; + this.base = ''; + this.keywords = ''; + + this.init(); + } + + init() { + + if (!document.querySelector(`style[context="${this.id}"]`)) { + const $style = document.createElement("style"); + $style.setAttribute("context", this.id); + $style.innerHTML = pageCss; + document.head.appendChild($style); + } + + this.element = $el("div", { + parent: document.body, + className: "comfy-modal cmm-manager" + }); + this.element.innerHTML = pageHtml; + this.initFilter(); + this.bindEvents(); + this.initGrid(); + } + + initFilter() { + + this.filterList = [{ + label: "All", + value: "" + }, { + label: "Installed", + value: "True" + }, { + label: "Not Installed", + value: "False" + }]; + + this.typeList = [{ + label: "All", + value: "" + }]; + + this.baseList = [{ + label: "All", + value: "" + }]; + + this.updateFilter(); + + } + + updateFilter() { + const $filter = this.element.querySelector(".cmm-manager-filter"); + $filter.innerHTML = this.filterList.map(item => { + const selected = item.value === this.filter ? " selected" : ""; + return `` + }).join(""); + + const $type = this.element.querySelector(".cmm-manager-type"); + $type.innerHTML = this.typeList.map(item => { + const selected = item.value === this.type ? " selected" : ""; + return `` + }).join(""); + + const $base = this.element.querySelector(".cmm-manager-base"); + $base.innerHTML = this.baseList.map(item => { + const selected = item.value === this.base ? " selected" : ""; + return `` + }).join(""); + + } + + bindEvents() { + const eventsMap = { + ".cmm-manager-filter": { + change: (e) => { + this.filter = e.target.value; + this.updateGrid(); + } + }, + ".cmm-manager-type": { + change: (e) => { + this.type = e.target.value; + this.updateGrid(); + } + }, + ".cmm-manager-base": { + change: (e) => { + this.base = e.target.value; + this.updateGrid(); + } + }, + + ".cmm-manager-keywords": { + input: (e) => { + const keywords = `${e.target.value}`.trim(); + if (keywords !== this.keywords) { + this.keywords = keywords; + this.updateGrid(); + } + }, + focus: (e) => e.target.select() + }, + + ".cmm-manager-selection": { + click: (e) => { + const target = e.target; + const mode = target.getAttribute("mode"); + if (mode === "install") { + this.installModels(this.selectedModels, target); + } + } + }, + + ".cmm-manager-close": { + click: (e) => this.close() + }, + + }; + Object.keys(eventsMap).forEach(selector => { + const target = this.element.querySelector(selector); + if (target) { + const events = eventsMap[selector]; + if (events) { + Object.keys(events).forEach(type => { + target.addEventListener(type, events[type]); + }); + } + } + }); + } + + // =========================================================================================== + + initGrid() { + const container = this.element.querySelector(".cmm-manager-grid"); + const grid = new TG.Grid(container); + this.grid = grid; + + grid.bind('onUpdated', (e, d) => { + + this.showStatus(`${grid.viewRows.length.toLocaleString()} external models`); + + }); + + grid.bind('onSelectChanged', (e, changes) => { + this.renderSelected(); + }); + + grid.bind('onClick', (e, d) => { + const { rowItem } = d; + const target = d.e.target; + const mode = target.getAttribute("mode"); + if (mode === "install") { + this.installModels([rowItem], target); + } + + }); + + grid.setOption({ + theme: 'dark', + + selectVisible: true, + selectMultiple: true, + selectAllVisible: true, + + textSelectable: true, + scrollbarRound: true, + + frozenColumn: 1, + rowNotFound: "No Results", + + rowHeight: 40, + bindWindowResize: true, + bindContainerResize: true, + + cellResizeObserver: (rowItem, columnItem) => { + const autoHeightColumns = ['name', 'description']; + return autoHeightColumns.includes(columnItem.id) + }, + + // updateGrid handler for filter and keywords + rowFilter: (rowItem) => { + + const searchableColumns = ["name", "type", "base", "description", "filename", "save_path"]; + + let shouldShown = grid.highlightKeywordsFilter(rowItem, searchableColumns, this.keywords); + + if (shouldShown) { + if(this.filter && rowItem.installed !== this.filter) { + return false; + } + + if(this.type && rowItem.type !== this.type) { + return false; + } + + if(this.base && rowItem.base !== this.base) { + return false; + } + + } + + return shouldShown; + } + }); + + } + + renderGrid() { + + // update theme + const colorPalette = this.app.ui.settings.settingsValues['Comfy.ColorPalette']; + Array.from(this.element.classList).forEach(cn => { + if (cn.startsWith("cmm-manager-")) { + this.element.classList.remove(cn); + } + }); + this.element.classList.add(`cmm-manager-${colorPalette}`); + + const options = { + theme: colorPalette === "light" ? "" : "dark" + }; + + const rows = this.modelList || []; + + const columns = [{ + id: 'id', + name: 'ID', + width: 50, + align: 'center' + }, { + id: 'name', + name: 'Name', + width: 200, + minWidth: 100, + maxWidth: 500, + classMap: 'cmm-node-name', + formatter: function(name, rowItem, columnItem, cellNode) { + return `${name}`; + } + }, { + id: 'installed', + name: 'Install', + width: 130, + minWidth: 110, + maxWidth: 200, + sortable: false, + align: 'center', + formatter: (installed, rowItem, columnItem) => { + if (rowItem.refresh) { + return `Refresh Required`; + } + if (installed === "True") { + return `
    ${icons.passed}
    `; + } + return ``; + } + }, { + id: 'url', + name: '', + width: 50, + sortable: false, + align: 'center', + formatter: (url, rowItem, columnItem) => { + return `${icons.download}`; + } + }, { + id: 'size', + name: 'Size', + width: 100, + formatter: (size) => { + if (typeof size === "number") { + return this.formatSize(size); + } + return size; + } + }, { + id: 'type', + name: 'Type', + width: 100 + }, { + id: 'base', + name: 'Base' + }, { + id: 'description', + name: 'Description', + width: 400, + maxWidth: 5000, + classMap: 'cmm-node-desc' + }, { + id: "save_path", + name: 'Save Path', + width: 200 + }, { + id: 'filename', + name: 'Filename', + width: 200 + }]; + + this.grid.setData({ + options, + rows, + columns + }); + + this.grid.render(); + + } + + updateGrid() { + if (this.grid) { + this.grid.update(); + } + } + + // =========================================================================================== + + renderSelected() { + const selectedList = this.grid.getSelectedRows(); + if (!selectedList.length) { + this.showSelection(""); + this.selectedModels = []; + return; + } + + this.selectedModels = selectedList; + this.showSelection(`Selected ${selectedList.length} models `); + } + + focusInstall(item) { + const cellNode = this.grid.getCellNode(item, "installed"); + if (cellNode) { + const cellBtn = cellNode.querySelector(`button[mode="install"]`); + if (cellBtn) { + cellBtn.classList.add("cmm-btn-loading"); + return true + } + } + } + + async installModels(list, btn) { + + btn.classList.add("cmm-btn-loading"); + this.showLoading(); + this.showError(""); + + let needRestart = false; + let errorMsg = ""; + + for (const item of list) { + + this.grid.scrollRowIntoView(item); + + if (!this.focusInstall(item)) { + this.grid.onNextUpdated(() => { + this.focusInstall(item); + }); + } + + this.showStatus(`Install ${item.name} ...`); + + const data = item.originalData; + const res = await fetchData('/model/install', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data) + }); + + + if (res.error) { + errorMsg = `Install failed: ${item.name} ${res.error.message}`; + break;; + } + + needRestart = true; + + this.grid.setRowSelected(item, false); + + item.refresh = true; + item.selectable = false; + this.grid.updateCell(item, "installed"); + this.grid.updateCell(item, "tg-column-select"); + + this.showStatus(`Install ${item.name} successfully`); + + } + + this.hideLoading(); + btn.classList.remove("cmm-btn-loading"); + + if (errorMsg) { + this.showError(errorMsg); + } else { + this.showStatus(`Install ${list.length} models successfully`); + } + + if (needRestart) { + this.showMessage(`To apply the installed model, please click the 'Refresh' button on the main menu.`, "red") + } + + } + + getModelList(models) { + + const typeMap = new Map(); + const baseMap = new Map(); + + models.forEach((item, i) => { + const { type, base, name, reference, installed } = item; + item.originalData = JSON.parse(JSON.stringify(item)); + item.size = this.sizeToBytes(item.size); + item.hash = md5(name + reference); + item.id = i + 1; + + if (installed === "True") { + item.selectable = false; + } + + typeMap.set(type, type); + baseMap.set(base, base); + + }); + + const typeList = []; + typeMap.forEach(type => { + typeList.push({ + label: type, + value: type + }); + }); + typeList.sort((a,b)=> { + const au = a.label.toUpperCase(); + const bu = b.label.toUpperCase(); + if (au !== bu) { + return au > bu ? 1 : -1; + } + return 0; + }); + this.typeList = [{ + label: "All", + value: "" + }].concat(typeList); + + + const baseList = []; + baseMap.forEach(base => { + baseList.push({ + label: base, + value: base + }); + }); + baseList.sort((a,b)=> { + const au = a.label.toUpperCase(); + const bu = b.label.toUpperCase(); + if (au !== bu) { + return au > bu ? 1 : -1; + } + return 0; + }); + this.baseList = [{ + label: "All", + value: "" + }].concat(baseList); + + return models; + } + + // =========================================================================================== + + async loadData() { + + this.showLoading(); + + this.showStatus(`Loading external model list ...`); + + const mode = manager_instance.datasrc_combo.value; + + const res = await fetchData(`/externalmodel/getlist?mode=${mode}`); + if (res.error) { + this.showError("Failed to get external model list."); + this.hideLoading(); + return + } + + const { models } = res.data; + + this.modelList = this.getModelList(models); + // console.log("models", this.modelList); + + this.updateFilter(); + + this.renderGrid(); + + this.hideLoading(); + + } + + // =========================================================================================== + + formatSize(v) { + const base = 1000; + const units = ['', 'K', 'M', 'G', 'T', 'P']; + const space = ''; + const postfix = 'B'; + if (v <= 0) { + return `0${space}${postfix}`; + } + for (let i = 0, l = units.length; i < l; i++) { + const min = Math.pow(base, i); + const max = Math.pow(base, i + 1); + if (v > min && v <= max) { + const unit = units[i]; + if (unit) { + const n = v / min; + const nl = n.toString().split('.')[0].length; + const fl = Math.max(3 - nl, 1); + v = n.toFixed(fl); + } + v = v + space + unit + postfix; + break; + } + } + return v; + } + + // for size sort + sizeToBytes(v) { + if (typeof v === "number") { + return v; + } + if (typeof v === "string") { + const n = parseFloat(v); + const unit = v.replace(/[0-9.B]+/g, "").trim().toUpperCase(); + if (unit === "K") { + return n * 1000; + } + if (unit === "M") { + return n * 1000 * 1000; + } + if (unit === "G") { + return n * 1000 * 1000 * 1000; + } + if (unit === "T") { + return n * 1000 * 1000 * 1000 * 1000; + } + } + return v; + } + + showSelection(msg) { + this.element.querySelector(".cmm-manager-selection").innerHTML = msg; + } + + showError(err) { + this.showMessage(err, "red"); + } + + showMessage(msg, color) { + if (color) { + msg = `${msg}`; + } + this.element.querySelector(".cmm-manager-message").innerHTML = msg; + } + + showStatus(msg, color) { + if (color) { + msg = `${msg}`; + } + this.element.querySelector(".cmm-manager-status").innerHTML = msg; + } + + showLoading() { + this.setDisabled(true); + if (this.grid) { + this.grid.showLoading(); + this.grid.showMask({ + opacity: 0.05 + }); + } + } + + hideLoading() { + this.setDisabled(false); + if (this.grid) { + this.grid.hideLoading(); + this.grid.hideMask(); + } + } + + setDisabled(disabled) { + + const $close = this.element.querySelector(".cmm-manager-close"); + + const list = [ + ".cmm-manager-header input", + ".cmm-manager-header select", + ".cmm-manager-footer button", + ".cmm-manager-selection button" + ].map(s => { + return Array.from(this.element.querySelectorAll(s)); + }) + .flat() + .filter(it => { + return it !== $close; + }); + + list.forEach($elem => { + if (disabled) { + $elem.setAttribute("disabled", "disabled"); + } else { + $elem.removeAttribute("disabled"); + } + }); + + Array.from(this.element.querySelectorAll(".cmm-btn-loading")).forEach($elem => { + $elem.classList.remove("cmm-btn-loading"); + }); + + } + + setKeywords(keywords = "") { + this.keywords = keywords; + this.element.querySelector(".cmm-manager-keywords").value = keywords; + } + + show() { + this.element.style.display = "flex"; + this.setKeywords(""); + this.showSelection(""); + this.showMessage(""); + this.loadData(); + } + + close() { + this.element.style.display = "none"; + } +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/js/node_fixer.js b/custom_nodes/ComfyUI-Manager/js/node_fixer.js new file mode 100644 index 000000000..94b4c7477 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/node_fixer.js @@ -0,0 +1,211 @@ +import { app } from "../../scripts/app.js"; +import { api } from "../../scripts/api.js"; + +let double_click_policy = "copy-all"; + +api.fetchApi('/manager/dbl_click/policy') + .then(response => response.text()) + .then(data => set_double_click_policy(data)); + +export function set_double_click_policy(mode) { + double_click_policy = mode; +} + +function addMenuHandler(nodeType, cb) { + const getOpts = nodeType.prototype.getExtraMenuOptions; + nodeType.prototype.getExtraMenuOptions = function () { + const r = getOpts.apply(this, arguments); + cb.apply(this, arguments); + return r; + }; +} + +function distance(node1, node2) { + let dx = (node1.pos[0] + node1.size[0]/2) - (node2.pos[0] + node2.size[0]/2); + let dy = (node1.pos[1] + node1.size[1]/2) - (node2.pos[1] + node2.size[1]/2); + return Math.sqrt(dx * dx + dy * dy); +} + +function lookup_nearest_nodes(node) { + let nearest_distance = Infinity; + let nearest_node = null; + for(let other of app.graph._nodes) { + if(other === node) + continue; + + let dist = distance(node, other); + if (dist < nearest_distance && dist < 1000) { + nearest_distance = dist; + nearest_node = other; + } + } + + return nearest_node; +} + +function lookup_nearest_inputs(node) { + let input_map = {}; + + for(let i in node.inputs) { + let input = node.inputs[i]; + + if(input.link || input_map[input.type]) + continue; + + input_map[input.type] = {distance: Infinity, input_name: input.name, node: null, slot: null}; + } + + let x = node.pos[0]; + let y = node.pos[1] + node.size[1]/2; + + for(let other of app.graph._nodes) { + if(other === node || !other.outputs) + continue; + + let dx = x - (other.pos[0] + other.size[0]); + let dy = y - (other.pos[1] + other.size[1]/2); + + if(dx < 0) + continue; + + let dist = Math.sqrt(dx * dx + dy * dy); + + for(let input_type in input_map) { + for(let j in other.outputs) { + let output = other.outputs[j]; + if(output.type == input_type) { + if(input_map[input_type].distance > dist) { + input_map[input_type].distance = dist; + input_map[input_type].node = other; + input_map[input_type].slot = parseInt(j); + } + } + } + } + } + + let res = {}; + for (let i in input_map) { + if (input_map[i].node) { + res[i] = input_map[i]; + } + } + + return res; +} + +function connect_inputs(nearest_inputs, node) { + for(let i in nearest_inputs) { + let info = nearest_inputs[i]; + info.node.connect(info.slot, node.id, info.input_name); + } +} + +function node_info_copy(src, dest, connect_both) { + // copy input connections + for(let i in src.inputs) { + let input = src.inputs[i]; + if(input.link) { + let link = app.graph.links[input.link]; + let src_node = app.graph.getNodeById(link.origin_id); + src_node.connect(link.origin_slot, dest.id, input.name); + } + } + + // copy output connections + if(connect_both) { + let output_links = {}; + for(let i in src.outputs) { + let output = src.outputs[i]; + if(output.links) { + let links = []; + for(let j in output.links) { + links.push(app.graph.links[output.links[j]]); + } + output_links[output.name] = links; + } + } + + for(let i in dest.outputs) { + let links = output_links[dest.outputs[i].name]; + if(links) { + for(let j in links) { + let link = links[j]; + let target_node = app.graph.getNodeById(link.target_id); + dest.connect(parseInt(i), target_node, link.target_slot); + } + } + } + } + + app.graph.afterChange(); +} + +app.registerExtension({ + name: "Comfy.Manager.NodeFixer", + + async nodeCreated(node, app) { + let orig_dblClick = node.onDblClick; + node.onDblClick = function (e, pos, self) { + orig_dblClick?.apply?.(this, arguments); + + if((!node.inputs && !node.outputs) || pos[1] > 0) + return; + + switch(double_click_policy) { + case "copy-all": + case "copy-input": + { + if(node.inputs?.some(x => x.link != null) || node.outputs?.some(x => x.links != null && x.links.length > 0) ) + return; + + let src_node = lookup_nearest_nodes(node); + if(src_node) + node_info_copy(src_node, node, double_click_policy == "copy-all"); + } + break; + case "possible-input": + { + let nearest_inputs = lookup_nearest_inputs(node); + if(nearest_inputs) + connect_inputs(nearest_inputs, node); + } + break; + case "dual": + { + if(pos[0] < node.size[0]/2) { + // left: possible-input + let nearest_inputs = lookup_nearest_inputs(node); + if(nearest_inputs) + connect_inputs(nearest_inputs, node); + } + else { + // right: copy-all + if(node.inputs?.some(x => x.link != null) || node.outputs?.some(x => x.links != null && x.links.length > 0) ) + return; + + let src_node = lookup_nearest_nodes(node); + if(src_node) + node_info_copy(src_node, node, true); + } + } + break; + } + } + }, + + beforeRegisterNodeDef(nodeType, nodeData, app) { + addMenuHandler(nodeType, function (_, options) { + options.push({ + content: "Fix node (recreate)", + callback: () => { + let new_node = LiteGraph.createNode(nodeType.comfyClass); + new_node.pos = [this.pos[0], this.pos[1]]; + app.canvas.graph.add(new_node, false); + node_info_copy(this, new_node); + app.canvas.graph.remove(this); + }, + }); + }); + } +}); diff --git a/custom_nodes/ComfyUI-Manager/js/snapshot.js b/custom_nodes/ComfyUI-Manager/js/snapshot.js new file mode 100644 index 000000000..01e544f7e --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/snapshot.js @@ -0,0 +1,300 @@ +import { app } from "../../scripts/app.js"; +import { api } from "../../scripts/api.js" +import { ComfyDialog, $el } from "../../scripts/ui.js"; +import { manager_instance, rebootAPI, show_message } from "./common.js"; + + +async function restore_snapshot(target) { + if(SnapshotManager.instance) { + try { + const response = await api.fetchApi(`/snapshot/restore?target=${target}`, { cache: "no-store" }); + + if(response.status == 403) { + show_message('This action is not allowed with this security level configuration.'); + return false; + } + + if(response.status == 400) { + show_message(`Restore snapshot failed: ${target.title} / ${exception}`); + } + + app.ui.dialog.close(); + return true; + } + catch(exception) { + show_message(`Restore snapshot failed: ${target.title} / ${exception}`); + return false; + } + finally { + await SnapshotManager.instance.invalidateControl(); + SnapshotManager.instance.updateMessage("
    To apply the snapshot, please ComfyUI. And refresh browser.", 'cm-reboot-button2'); + } + } +} + +async function remove_snapshot(target) { + if(SnapshotManager.instance) { + try { + const response = await api.fetchApi(`/snapshot/remove?target=${target}`, { cache: "no-store" }); + + if(response.status == 403) { + show_message('This action is not allowed with this security level configuration.'); + return false; + } + + if(response.status == 400) { + show_message(`Remove snapshot failed: ${target.title} / ${exception}`); + } + + app.ui.dialog.close(); + return true; + } + catch(exception) { + show_message(`Restore snapshot failed: ${target.title} / ${exception}`); + return false; + } + finally { + await SnapshotManager.instance.invalidateControl(); + } + } +} + +async function save_current_snapshot() { + try { + const response = await api.fetchApi('/snapshot/save', { cache: "no-store" }); + app.ui.dialog.close(); + return true; + } + catch(exception) { + show_message(`Backup snapshot failed: ${exception}`); + return false; + } + finally { + await SnapshotManager.instance.invalidateControl(); + SnapshotManager.instance.updateMessage("
    Current snapshot saved."); + } +} + +async function getSnapshotList() { + const response = await api.fetchApi(`/snapshot/getlist`); + const data = await response.json(); + return data; +} + +export class SnapshotManager extends ComfyDialog { + static instance = null; + + restore_buttons = []; + message_box = null; + data = null; + + clear() { + this.restore_buttons = []; + this.message_box = null; + this.data = null; + } + + constructor(app, manager_dialog) { + super(); + this.manager_dialog = manager_dialog; + this.search_keyword = ''; + this.element = $el("div.comfy-modal", { parent: document.body }, []); + } + + async remove_item() { + caller.disableButtons(); + + await caller.invalidateControl(); + } + + createControls() { + return [ + $el("button.cm-small-button", { + type: "button", + textContent: "Close", + onclick: () => { this.close(); } + }) + ]; + } + + startRestore(target) { + const self = SnapshotManager.instance; + + self.updateMessage(`
    Restore snapshot '${target.name}'`); + + for(let i in self.restore_buttons) { + self.restore_buttons[i].disabled = true; + self.restore_buttons[i].style.backgroundColor = 'gray'; + } + } + + async invalidateControl() { + this.clear(); + this.data = (await getSnapshotList()).items; + + while (this.element.children.length) { + this.element.removeChild(this.element.children[0]); + } + + await this.createGrid(); + await this.createBottomControls(); + } + + updateMessage(msg, btn_id) { + this.message_box.innerHTML = msg; + if(btn_id) { + const rebootButton = document.getElementById(btn_id); + const self = this; + rebootButton.onclick = function() { + if(rebootAPI()) { + self.close(); + self.manager_dialog.close(); + } + }; + } + } + + async createGrid(models_json) { + var grid = document.createElement('table'); + grid.setAttribute('id', 'snapshot-list-grid'); + + var thead = document.createElement('thead'); + var tbody = document.createElement('tbody'); + + var headerRow = document.createElement('tr'); + thead.style.position = "sticky"; + thead.style.top = "0px"; + thead.style.borderCollapse = "collapse"; + thead.style.tableLayout = "fixed"; + + var header1 = document.createElement('th'); + header1.innerHTML = '  ID  '; + header1.style.width = "20px"; + var header2 = document.createElement('th'); + header2.innerHTML = 'Datetime'; + header2.style.width = "100%"; + var header_button = document.createElement('th'); + header_button.innerHTML = 'Action'; + header_button.style.width = "100px"; + + thead.appendChild(headerRow); + headerRow.appendChild(header1); + headerRow.appendChild(header2); + headerRow.appendChild(header_button); + + headerRow.style.backgroundColor = "Black"; + headerRow.style.color = "White"; + headerRow.style.textAlign = "center"; + headerRow.style.width = "100%"; + headerRow.style.padding = "0"; + + grid.appendChild(thead); + grid.appendChild(tbody); + + this.grid_rows = {}; + + if(this.data) + for (var i = 0; i < this.data.length; i++) { + const data = this.data[i]; + var dataRow = document.createElement('tr'); + var data1 = document.createElement('td'); + data1.style.textAlign = "center"; + data1.innerHTML = i+1; + var data2 = document.createElement('td'); + data2.innerHTML = ` ${data}`; + var data_button = document.createElement('td'); + data_button.style.textAlign = "center"; + + var restoreBtn = document.createElement('button'); + restoreBtn.innerHTML = 'Restore'; + restoreBtn.style.width = "100px"; + restoreBtn.style.backgroundColor = 'blue'; + + restoreBtn.addEventListener('click', function() { + restore_snapshot(data); + }); + + var removeBtn = document.createElement('button'); + removeBtn.innerHTML = 'Remove'; + removeBtn.style.width = "100px"; + removeBtn.style.backgroundColor = 'red'; + + removeBtn.addEventListener('click', function() { + remove_snapshot(data); + }); + + data_button.appendChild(restoreBtn); + data_button.appendChild(removeBtn); + + dataRow.style.backgroundColor = "var(--bg-color)"; + dataRow.style.color = "var(--fg-color)"; + dataRow.style.textAlign = "left"; + + dataRow.appendChild(data1); + dataRow.appendChild(data2); + dataRow.appendChild(data_button); + tbody.appendChild(dataRow); + + this.grid_rows[i] = {data:data, control:dataRow}; + } + + let self = this; + const panel = document.createElement('div'); + panel.style.width = "100%"; + panel.appendChild(grid); + + function handleResize() { + const parentHeight = self.element.clientHeight; + const gridHeight = parentHeight - 200; + + grid.style.height = gridHeight + "px"; + } + window.addEventListener("resize", handleResize); + + grid.style.position = "relative"; + grid.style.display = "inline-block"; + grid.style.width = "100%"; + grid.style.height = "100%"; + grid.style.overflowY = "scroll"; + this.element.style.height = "85%"; + this.element.style.width = "80%"; + this.element.appendChild(panel); + + handleResize(); + } + + async createBottomControls() { + var close_button = document.createElement("button"); + close_button.className = "cm-small-button"; + close_button.innerHTML = "Close"; + close_button.onclick = () => { this.close(); } + close_button.style.display = "inline-block"; + + var save_button = document.createElement("button"); + save_button.className = "cm-small-button"; + save_button.innerHTML = "Save snapshot"; + save_button.onclick = () => { save_current_snapshot(); } + save_button.style.display = "inline-block"; + save_button.style.horizontalAlign = "right"; + save_button.style.width = "170px"; + + this.message_box = $el('div', {id:'custom-download-message'}, [$el('br'), '']); + this.message_box.style.height = '60px'; + this.message_box.style.verticalAlign = 'middle'; + + this.element.appendChild(this.message_box); + this.element.appendChild(close_button); + this.element.appendChild(save_button); + } + + async show() { + try { + this.invalidateControl(); + this.element.style.display = "block"; + this.element.style.zIndex = 10001; + } + catch(exception) { + app.ui.dialog.show(`Failed to get external model list. / ${exception}`); + } + } +} diff --git a/custom_nodes/ComfyUI-Manager/js/terminal.js b/custom_nodes/ComfyUI-Manager/js/terminal.js new file mode 100644 index 000000000..091959fa5 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/terminal.js @@ -0,0 +1,81 @@ +import {app} from "../../scripts/app.js"; +import {ComfyWidgets} from "../../scripts/widgets.js"; +// Node that add notes to your project + +let terminal_node; +let log_mode = false; + +app.registerExtension({ + name: "Comfy.Manager.Terminal", + + registerCustomNodes() { + class TerminalNode { + color = "#222222"; + bgcolor = "#000000"; + groupcolor = LGraphCanvas.node_colors.black.groupcolor; + constructor() { + this.logs = []; + + if (!this.properties) { + this.properties = {}; + this.properties.text=""; + } + + ComfyWidgets.STRING(this, "", ["", {default:this.properties.text, multiline: true}], app) + ComfyWidgets.BOOLEAN(this, "mode", ["", {default:true, label_on:'Logging', label_off:'Stop'}], app) + ComfyWidgets.INT(this, "lines", ["", {default:500, min:10, max:10000, steps:1}], app) + + let self = this; + Object.defineProperty(this.widgets[1], 'value', { + set: (v) => { + api.fetchApi(`/manager/terminal?mode=${v}`, {}); + log_mode = v; + }, + get: () => { + return log_mode; + } + }); + + this.serialize_widgets = false; + this.isVirtualNode = true; + + if(terminal_node) { + try { + terminal_node.widgets[0].value = 'The output of this node is disabled because another terminal node has appeared.'; + } + catch {} + } + terminal_node = this; + } + } + + // Load default visibility + LiteGraph.registerNodeType( + "Terminal Log //CM", + Object.assign(TerminalNode, { + title_mode: LiteGraph.NORMAL_TITLE, + title: "Terminal Log (Manager)", + collapsable: true, + }) + ); + + TerminalNode.category = "utils"; + }, +}); + + +import { api } from "../../scripts/api.js"; + +function terminalFeedback(event) { + if(terminal_node) { + terminal_node.logs.push(event.detail.data); + if(terminal_node.logs.length > terminal_node.widgets[2].value) { + terminal_node.logs.shift(); + if(terminal_node.logs[0] == '' || terminal_node.logs[0] == '\n') + terminal_node.logs.shift(); + } + terminal_node.widgets[0].value = [...terminal_node.logs].reverse().join('').trim(); + } +} + +api.addEventListener("manager-terminal-feedback", terminalFeedback); diff --git a/custom_nodes/ComfyUI-Manager/js/turbogrid.esm.js b/custom_nodes/ComfyUI-Manager/js/turbogrid.esm.js new file mode 100644 index 000000000..fd0bfb57d --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/js/turbogrid.esm.js @@ -0,0 +1 @@ +var t={915:(t,e,i)=>{i.d(e,{A:()=>l});var o=i(256),n=i.n(o),s=i(505),r=i.n(s)()(n());r.push([t.id,'.tg-turbogrid{position:relative;z-index:0;width:100%;height:100%;margin:0;padding:0;box-sizing:border-box;font-size:14px;font-family:arial,sans-serif;outline:0;cursor:default;overflow:hidden}.tg-turbogrid *,.tg-turbogrid *::before,.tg-turbogrid *::after{box-sizing:border-box}.tg-text-unselectable.tg-turbogrid{user-select:none}.tg-turbogrid svg{display:block;pointer-events:none}.tg-turbogrid .tg-symbols{font-family:webdings,sans-serif}.tg-turbogrid .tg-nowrap{white-space:nowrap}.tg-turbogrid .tg-align-left{text-align:left}.tg-turbogrid .tg-align-center{text-align:center}.tg-turbogrid .tg-align-right{text-align:right}@keyframes tg-fade-in{from{opacity:0}to{opacity:1}}@keyframes tg-fade-out{from{opacity:1}to{opacity:0}}.tg-turbogrid .tg-fade-in{animation-name:tg-fade-in;animation-duration:.2s;animation-fill-mode:both}.tg-turbogrid .tg-fade-in .tg-scrollbar-track{display:none}.tg-turbogrid .tg-fade-out{animation-name:tg-fade-out;animation-duration:.2s;animation-fill-mode:both}.tg-turbogrid .tg-fade-out .tg-scrollbar-track{display:none}.tg-turbogrid .tg-mask{position:absolute;top:0;left:0;z-index:200;display:none;width:100%;height:100%;background-color:#000;opacity:.1}@keyframes tg-loading-animation{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.tg-turbogrid .tg-loading{position:absolute;top:50%;left:50%;z-index:300;display:none;transform:translate(-50%, -50%);pointer-events:none}.tg-turbogrid .tg-loading-default{width:35px;height:35px;color:#0077cf;animation:1s tg-loading-animation linear infinite}.tg-turbogrid .tg-loading-fast{animation:.382s tg-loading-animation linear infinite}.tg-turbogrid .tg-checkbox{width:100%;height:100%;cursor:pointer;overflow:hidden}.tg-turbogrid .tg-checkbox:hover .tg-checkbox-item{fill:#005ba1}.tg-turbogrid .tg-checkbox.tg-select-icon-all{height:18px}.tg-turbogrid .tg-checkbox .tg-icon-checkbox{position:absolute;top:50%;left:50%;display:block;width:16px;height:16px;transform:translate(-50%, -50%)}.tg-turbogrid .tg-checkbox .tg-checkbox-item{display:none;fill:gray}.tg-turbogrid .tg-checkbox .tg-checkbox-none{display:block}.tg-turbogrid .tg-checkbox.tg-selected .tg-checkbox-selected{display:block;fill:#0077cf}.tg-turbogrid .tg-checkbox.tg-mixed .tg-checkbox-mixed{display:block;fill:#0077cf}.tg-turbogrid .tg-radio{cursor:pointer;overflow:hidden}.tg-turbogrid .tg-radio:hover .tg-icon-radio::before{border-color:#005ba1}.tg-turbogrid .tg-radio .tg-icon-radio{position:absolute;top:50%;left:50%;width:16px;height:16px;transform:translate(-50%, -50%)}.tg-turbogrid .tg-radio .tg-icon-radio::before{position:absolute;top:50%;left:50%;content:"";display:block;width:16px;height:16px;border:thin solid gray;border-radius:50%;background:#fff;transform:translate(-50%, -50%)}.tg-turbogrid .tg-radio .tg-icon-radio::after{position:absolute;top:50%;left:50%;content:"";display:none;width:10px;height:10px;border-radius:50%;background:#0077cf;transform:translate(-50%, -50%)}.tg-turbogrid .tg-radio.tg-selected .tg-icon-radio::after{display:block;border-color:#0077cf}.tg-turbogrid .tg-scrollbar{position:absolute;z-index:100;overflow:hidden;user-select:none}.tg-turbogrid .tg-scrollbar-v{top:0;right:0}.tg-turbogrid .tg-scrollbar-h{left:0;bottom:0}.tg-turbogrid .tg-scrollbar-track{position:relative;width:100%;height:100%;background:#f9f9f9;overflow:hidden;user-select:none}.tg-turbogrid .tg-scrollbar-thumb{position:absolute;top:0;left:0;border-radius:1px;background:#999;overflow:hidden;user-select:none}.tg-turbogrid .tg-scrollbar-thumb:hover{background:#888}.tg-turbogrid .tg-scrollbar-thumb-hold{background:#666}.tg-turbogrid .tg-scrollbar-thumb-hold:hover{background:#666}.tg-turbogrid .tg-scrollbar-round .tg-scrollbar-track{border-radius:10px}.tg-turbogrid .tg-scrollbar-round .tg-scrollbar-thumb{border-radius:10px}.tg-turbogrid .tg-scroll-pane{position:relative;margin:0;padding:0;border:none;outline:none;overflow:hidden}.tg-turbogrid .tg-scroll-view{position:relative;width:100%;height:100%;margin:0;padding:0;border:none;overflow:hidden}.tg-turbogrid .tg-scroll-body{position:absolute}.tg-turbogrid .tg-header{position:relative;width:10000px;border-left:0;overflow:hidden}.tg-turbogrid .tg-header-table{position:relative;color:#5e5e5e;font-weight:bold;font-size:14px;line-height:16px;border-bottom:thin solid #e5e5e5;overflow:hidden}.tg-turbogrid .tg-header-item{position:absolute;bottom:0}.tg-turbogrid .tg-header-group-item{overflow:hidden}.tg-turbogrid .tg-header-group-item::after{position:absolute;left:5px;bottom:0;content:"";display:block;width:calc(100% - 10px);height:1px;border-bottom:thin solid #ccc}.tg-turbogrid .tg-column-header{position:absolute;bottom:0;overflow:hidden}.tg-turbogrid .tg-column-header .tg-column-name{padding:10px 5px;text-overflow:ellipsis;overflow:hidden}.tg-turbogrid .tg-column-header .tg-column-name.tg-header-group-name{margin:0 5px;padding:5px 0}.tg-turbogrid .tg-column-resizing{position:absolute;top:0;right:-5px;z-index:100;width:10px;height:100%;background:#ccc;cursor:ew-resize;opacity:0}.tg-turbogrid .tg-header-column-last .tg-column-resizing{right:0}.tg-turbogrid .tg-column-sortable .tg-column-name{cursor:pointer}.tg-turbogrid .tg-column-sortable .tg-sort-indicator{cursor:pointer}.tg-turbogrid .tg-column-sorted{color:#000}.tg-turbogrid .tg-header-sort-h .tg-column-name{padding:12px 5px 15px}.tg-turbogrid .tg-header-sort-h .tg-column-sort{width:100%;height:15px;margin-top:-15px;padding:0 5px;overflow:hidden}.tg-turbogrid .tg-header-sort-h .tg-sort-indicator{position:relative;display:none;width:100%;height:100%}.tg-turbogrid .tg-header-sort-h .tg-column-sorted .tg-column-sort .tg-sort-indicator{display:block}.tg-turbogrid .tg-header-sort-h .tg-sort-indicator-line{position:absolute;top:1px;width:100%;height:0;border-top:thin solid #1e1e1e;overflow:hidden}.tg-turbogrid .tg-header-sort-h .tg-sort-indicator-icon{position:absolute;top:5px;left:0;right:inherit}.tg-turbogrid .tg-header-sort-h .tg-align-right .tg-sort-indicator-icon{left:inherit;right:0}.tg-turbogrid .tg-header-sort-h .tg-align-center .tg-sort-indicator-icon{left:50%;transform:translateX(-50%)}.tg-turbogrid .tg-header-sort-h .tg-sort-indicator-icon .tg-icon-sort-h{display:block;width:19px;height:6px}.tg-turbogrid .tg-header-sort-h .tg-sort-indicator-icon .tg-icon-item{display:none;fill:#1e1e1e}.tg-turbogrid .tg-header-sort-h .tg-sort-indicator-icon .tg-icon-item-light{fill:#ababab}.tg-turbogrid .tg-column-sort-v{display:flex;flex-direction:row;align-items:center}.tg-turbogrid .tg-column-sort-v .tg-column-name{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.tg-turbogrid .tg-column-sort-v.tg-align-right{justify-content:right}.tg-turbogrid .tg-column-sort-v .tg-sort-indicator{position:relative;width:16px;height:16px}.tg-turbogrid .tg-column-sort-v .tg-sort-indicator-icon{position:absolute}.tg-turbogrid .tg-column-sort-v .tg-sort-indicator-icon .tg-icon-sort-v{display:block;width:10px;height:16px}.tg-turbogrid .tg-column-sort-v .tg-sort-indicator-icon .tg-icon-item{fill:#ababab}.tg-turbogrid .tg-column-sort-v .tg-sort-indicator-icon .tg-icon-item-light{fill:#ababab}.tg-turbogrid .tg-column-sort-v.tg-column-sorted .tg-sort-indicator-icon .tg-icon-item{fill:#1e1e1e}.tg-turbogrid .tg-column-sort-v.tg-column-sorted .tg-sort-indicator-icon .tg-icon-item-light{fill:#ababab}.tg-turbogrid .tg-sort-desc .tg-sort-indicator .tg-sort-indicator-icon .tg-desc{display:block}.tg-turbogrid .tg-sort-desc .tg-sort-indicator .tg-sort-indicator-icon .tg-asc{display:none}.tg-turbogrid .tg-sort-asc .tg-sort-indicator .tg-sort-indicator-icon .tg-desc{display:none}.tg-turbogrid .tg-sort-asc .tg-sort-indicator .tg-sort-indicator-icon .tg-asc{display:block}.tg-turbogrid .tg-column-line{position:absolute;top:0;left:0;z-index:100;display:none;height:100%;pointer-events:none}.tg-turbogrid .tg-column-line-item{position:absolute;top:0;bottom:0;display:block;width:0;height:100%;border-left:thin solid #ccc}.tg-turbogrid .tg-column-line-item.tg-active{border-left:thin solid #0077cf}.tg-turbogrid .tg-column-dragging{cursor:ew-resize}.tg-turbogrid .tg-column-dragging .tg-column-name{cursor:ew-resize}.tg-turbogrid .tg-column-dragging .tg-column-resizing:not(.tg-resizing-active){display:none}.tg-turbogrid .tg-tree{position:relative;display:flex;flex-direction:row;place-items:center left;width:100%;height:100%;overflow:hidden}.tg-turbogrid .tg-tree-icon{position:relative;width:15px;height:100%;min-height:9px;text-align:left;cursor:pointer;overflow:hidden}.tg-turbogrid .tg-tree-icon .tg-icon-tree{position:absolute;top:50%;left:0;display:block;width:9px;height:9px;transform:translate(0, -50%);overflow:hidden}.tg-turbogrid .tg-tree-icon .tg-tree-item{display:none}.tg-turbogrid .tg-tree-icon-collapsed .tg-tree-collapsed{display:block}.tg-turbogrid .tg-tree-icon-empty .tg-tree-collapsed{opacity:.5}.tg-turbogrid .tg-tree-icon-expanded .tg-tree-expanded{display:block}.tg-turbogrid .tg-tree-name{flex:1;text-overflow:ellipsis;overflow:hidden}.tg-turbogrid .tg-tree-header .tg-tree .tg-tree-icon{display:none}.tg-turbogrid .tg-tree-icon-all{position:relative;height:17px}.tg-turbogrid .tg-tree-header-indent .tg-tree{padding-left:5px}.tg-turbogrid .tg-tree-header-indent .tg-tree .tg-tree-icon{display:block}.tg-turbogrid .tg-tree-header-indent.tg-column-sort-h .tg-column-sort{width:calc(100% - 20px);margin-left:20px}.tg-turbogrid .tg-pane{position:absolute;width:100%;outline:0;overflow:hidden}.tg-turbogrid .tg-header-frame{position:relative;display:block;outline:0;overflow:hidden}.tg-turbogrid .tg-header-frame .tg-pane{height:100%}.tg-turbogrid .tg-body-frame{position:relative;width:100%;outline:0}.tg-turbogrid .tg-body-message{position:absolute;display:none;width:100%;height:100%;padding:10px;overflow:hidden}.tg-turbogrid .tg-body-message img,.tg-turbogrid .tg-body-message div{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%)}.tg-turbogrid .tg-body{position:absolute;outline:0}.tg-turbogrid .tg-cell-hover-icon{display:none}.tg-touch-device.tg-turbogrid .tg-cell-hover-icon{display:inherit}.tg-turbogrid .tg-cell-row-number{font-weight:normal}.tg-turbogrid .tg-cell-row-drag .tg-row-drag-icon{position:absolute;top:50%;left:50%;width:24px;height:24px;cursor:move;opacity:.8;transform:translate(-50%, -50%)}.tg-turbogrid .tg-cell-row-drag .tg-row-drag-icon:hover{opacity:1}.tg-turbogrid .tg-cell{position:absolute;z-index:1;height:100%;margin:0;padding:0 5px;color:#1e1e1e;white-space:nowrap;text-overflow:ellipsis;vertical-align:middle;overflow:hidden}.tg-turbogrid .tg-cell:focus{outline:none}.tg-turbogrid .tg-cell.tg-flashing{border:1px solid red !important}.tg-turbogrid .tg-cell.tg-selected{background-color:beige}.tg-turbogrid .tg-cell.tg-align-left.tg-cell-negative{padding-left:1px}.tg-turbogrid .tg-cell.tg-align-right.tg-cell-negative{padding-right:1px}.tg-turbogrid .tg-cell.tg-cell-observer{display:flex;flex-direction:column;justify-content:center;padding:5px;line-height:normal;white-space:normal;text-overflow:ellipsis;overflow:hidden}.tg-turbogrid .tg-cell.tg-cell-observer .tg-observer{position:relative;margin:0;padding:0;border:none}.tg-turbogrid .tg-row{position:absolute;width:100%;border:0;border-bottom:thin solid #e5e5e5}.tg-turbogrid .tg-row.tg-group-line{border-bottom:thin solid #999}.tg-turbogrid .tg-row.tg-none-line{border-bottom:none}.tg-turbogrid .tg-row.tg-top-line{border-top:thin solid #e5e5e5}.tg-turbogrid .tg-row.tg-group{font-weight:bold;overflow:hidden}.tg-turbogrid .tg-row.tg-group .tg-cell.tg-align-left.tg-cell-negative{padding-left:0}.tg-turbogrid .tg-row.tg-group .tg-cell.tg-align-right.tg-cell-negative{padding-right:0}.tg-turbogrid .tg-row.tg-hover .tg-cell .tg-cell-hover-icon{display:inherit}.tg-turbogrid .tg-row.tg-dragging{opacity:.3}.tg-turbogrid .tg-row.tg-clone{z-index:1000;border:1px dashed #ccc;border-right:none;border-left:none;background:#fff;cursor:move;opacity:.5}.tg-turbogrid .tg-row.tg-clone *{cursor:move}.tg-turbogrid .tg-row-placeholder{position:absolute;z-index:9999;width:100%;border-top:2px solid #00a8e1;pointer-events:none}.tg-turbogrid .tg-row::before,.tg-turbogrid .tg-row::after{position:absolute;top:0;left:0;content:"";z-index:100;display:none;width:100%;height:100%;pointer-events:none}.tg-turbogrid .tg-hover.tg-row::before{display:block;background:rgba(0,0,0,.08)}.tg-turbogrid .tg-selected.tg-row::after{display:block;background:rgba(0,0,0,.13)}.tg-lightblue .tg-header-item{border-top:thin solid #e8eaf0;border-right:thin solid #e8eaf0}.tg-lightblue .tg-column-name{padding:5px;color:#304265}.tg-lightblue .tg-header-group-item::after{display:none}.tg-lightblue .tg-checkbox .tg-icon-item{fill:#d4d7e0}.tg-lightblue .tg-checkbox:hover .tg-icon-item{fill:#107fff}.tg-lightblue .tg-checkbox.tg-selected .tg-select-checkbox{fill:#107fff}.tg-lightblue .tg-checkbox.tg-mixed .tg-select-mixed{fill:#107fff}.tg-lightblue .tg-cell{color:#304265;border-right:thin solid #e8eaf0}.tg-lightblue .tg-row{border-bottom:thin solid #e8eaf0}.tg-lightblue .tg-row.tg-group-line{border-bottom:thin solid #c9ccd8}.tg-lightblue .tg-row.tg-selected{background:rgba(58,116,213,.05)}.tg-lightblue .tg-row.tg-hover{background:rgba(58,116,213,.05)}.tg-lightblue .tg-row.tg-even{background:#fbfcfe}.tg-lightblue .tg-row.tg-odd{background:#fff}.tg-lightblue .tg-hover.tg-row::before{background:rgba(58,116,213,.05)}.tg-lightblue .tg-selected.tg-row::after{background:rgba(58,116,213,.1)}.tg-lightblue .tg-header-frame{border-bottom:thin solid #e8eaf0}.tg-lightblue .tg-row-not-found .tg-frozen-line-v{border-right:none}.tg-lightblue .tg-scrollbar-track{background:#fff}.tg-lightblue .tg-scrollbar-thumb{background:rgba(48,66,101,.35)}.tg-lightblue .tg-scrollbar-thumb:hover{background-color:#a8a8a8}.tg-lightblue .tg-scrollbar-thumb:active{background-color:#787878}.tg-dark{background:#1e1e1e}.tg-dark .tg-checkbox .tg-icon-item{fill:#ababab}.tg-dark .tg-header-table{color:#ccc;border-bottom:thin solid #333}.tg-dark .tg-header-group-item::after{border-bottom:1px solid #999}.tg-dark .tg-column-sorted{color:#fff}.tg-dark .tg-column-sorted .tg-tree-icon-all .tg-icon-item{fill:#fff}.tg-dark .tg-header-sort-h .tg-sort-indicator-line{border-top:thin solid #eee}.tg-dark .tg-header-sort-h .tg-sort-indicator-icon .tg-icon-item{fill:#eee}.tg-dark .tg-header-sort-h .tg-sort-indicator-icon .tg-icon-item-light{fill:#666}.tg-dark .tg-column-sort-v .tg-sort-indicator-icon .tg-icon-item{fill:#666}.tg-dark .tg-column-sort-v .tg-sort-indicator-icon .tg-icon-item-light{fill:#666}.tg-dark .tg-column-sort-v.tg-column-sorted .tg-sort-indicator-icon .tg-icon-item{fill:#fff}.tg-dark .tg-column-sort-v.tg-column-sorted .tg-sort-indicator-icon .tg-icon-item-light{fill:#666}.tg-dark .tg-tree-icon .tg-icon-item{fill:#fff}.tg-dark .tg-tree-icon-all .tg-icon-item{fill:#999}.tg-dark .tg-header-item .tg-tree-icon .tg-icon-item{fill:#999}.tg-dark .tg-header-item .tg-column-sorted .tg-tree-icon .tg-icon-item{fill:#fff}.tg-dark .tg-row{border-bottom:thin solid #333}.tg-dark .tg-row.tg-group-line{border-bottom:thin solid #666}.tg-dark .tg-row.tg-clone{border:1px dashed #1e1e1e;opacity:.1}.tg-dark .tg-cell{color:#eee}.tg-dark .tg-body-message{color:#eee}.tg-dark .tg-hover.tg-row::before{background:rgba(255,255,255,.1)}.tg-dark .tg-selected.tg-row::after{background:rgba(255,255,255,.2)}.tg-dark .tg-mask{background-color:#fff}.tg-dark .tg-scrollbar-track{background:#333}.tg-dark .tg-scrollbar-thumb{background:#bbb}.tg-dark .tg-scrollbar-thumb:hover{background:#ddd}.tg-dark .tg-scrollbar-thumb-hold{background:#eee}.tg-dark .tg-scrollbar-thumb-hold:hover{background:#eee}.tg-pointer-events-none{pointer-events:none}',""]);const l=r},505:t=>{t.exports=function(t){var e=[];return e.toString=function(){return this.map((function(e){var i="",o=void 0!==e[5];return e[4]&&(i+="@supports (".concat(e[4],") {")),e[2]&&(i+="@media ".concat(e[2]," {")),o&&(i+="@layer".concat(e[5].length>0?" ".concat(e[5]):""," {")),i+=t(e),o&&(i+="}"),e[2]&&(i+="}"),e[4]&&(i+="}"),i})).join("")},e.i=function(t,i,o,n,s){"string"==typeof t&&(t=[[null,t,void 0]]);var r={};if(o)for(var l=0;l0?" ".concat(c[5]):""," {").concat(c[1],"}")),c[5]=s),i&&(c[2]?(c[1]="@media ".concat(c[2]," {").concat(c[1],"}"),c[2]=i):c[2]=i),n&&(c[4]?(c[1]="@supports (".concat(c[4],") {").concat(c[1],"}"),c[4]=n):c[4]="".concat(n)),e.push(c))}},e}},256:t=>{t.exports=function(t){return t[1]}}},e={};function i(o){var n=e[o];if(void 0!==n)return n.exports;var s=e[o]={id:o,exports:{}};return t[o](s,s.exports,i),s.exports}i.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return i.d(e,{a:e}),e},i.d=(t,e)=>{for(var o in e)i.o(e,o)&&!i.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var o={};(()=>{i.d(o,{$:()=>w,MP:()=>e,_d:()=>k,xA:()=>Xt,In:()=>X,T8:()=>B,Gr:()=>kt,ht:()=>Kt,J0:()=>d,xv:()=>Yt,Ay:()=>qt});const t="turbogrid",e={ID:t,NS:`tg-${t}`,VERSION:"3.2.0",TIMESTAMP:"2024-06-20T10:33:49.165Z",UP:"up",DOWN:"down",LEFT:"left",RIGHT:"right",TREE_INDENT:15},n=function(t){if(!t||"object"!=typeof t)return!1;const e=Object.prototype.toString.call(t);return!!["[object Object]","[object Array]"].includes(e)&&(!t.constructor||!![Object,Array].includes(t.constructor))},s=function(t,e){let i;return t.forEach((t=>{n(t)&&(i||(i=t instanceof Array?[]:{}),t instanceof Array?function(t,e,i){const o=e.length;for(let s=0;s{this.execute()})):Promise.resolve().then((()=>{this.execute()}))}execute(){if(!this.started)return;this.started=!1;const t=this.callback;this.callback=null,"function"==typeof t&&t.call(this)}cancel(){this.started=!1,this.callback=null}}const a=new WeakMap,c={isObject:n,merge:l,hasOwn:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},uid:function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:8;const e="0123456789abcdefghijklmnopqrstuvwxyz";let i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";for(;t--;)i+=e[36*Math.random()|0];return i},isNum:function(t){if("number"!=typeof t||isNaN(t))return!1;return(e=t)!==Number.MAX_VALUE&&e!==Number.MIN_VALUE&&e!==Number.NEGATIVE_INFINITY&&e!==Number.POSITIVE_INFINITY;var e},toNum:function(t,e){return"number"!=typeof t&&(t=parseFloat(t)),isNaN(t)&&(t=0),e&&!Number.isInteger(t)&&(t=Math.round(t)),t},convertNum:function(t){if("string"==typeof t){if(/^[-+]?\d+(\.\d+)?$/gi.test(t))return parseFloat(t)}return t},clamp:function(t,e,i){return Math.max(Math.min(t,i),e)},per:function(t){return t=c.toNum(t),t=c.clamp(t,0,1)},replace:function(t,e){return t=`${t}`,e?t=t.replace(/\{([^}]+)\}/g,(function(t,i){return c.hasOwn(e,i)?e[i]:t})):t},isArray:function(t){return!!(t&&t instanceof Array)},toList:function(t){return t instanceof Array?t:void 0===t?[]:"string"==typeof t?[t]:t&&c.hasOwn(t,"length")?Array.from(t):[t]},isList:function(t){return!!(c.isArray(t)&&t.length>0)},inList:function(t,e){if(!c.isList(e))return!1;for(let i=0,o=e.length;i{if(!c.isList(t))return;let n=0;const s=t.length;for(;nt.startsWith(e))).forEach((e=>{t[e]=null}))},hasShiftKey:function(t){let e=!1;return t&&(e=t.shiftKey),e},isTouchDevice:function(){return"ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0},contains:function(t,e){if(!t||!e)return!1;if(t===e)return!0;if("function"==typeof t.contains)return t.contains(e);let i=e.parentNode;for(;i;){if(i===t)return!0;i=i.parentNode}return!1},isNarrowCharacter:function(t){const e=t.codePointAt(0);return e>=32&&e<=126||162===e||163===e||165===e||166===e||172===e||175===e||8361===e||e>=10214&&e<=10221||10629===e||10630===e||e>=65377&&e<=65470||e>=65474&&e<=65479||e>=65482&&e<=65487||e>=65490&&e<=65495||e>=65498&&e<=65500||e>=65512&&e<=65518},getCharLen:function(t){let e=0;if(!t)return e;for(const i of String(t))e+=c.isNarrowCharacter(i)?1:2;return e},pascalToKebabCase:function(t){return`${t}`.trim().replace(/([a-z])([A-Z])/g,"$1-$2").replace(/\W/g,(t=>/[À-ž]/.test(t)?t:"-")).replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-").toLowerCase()},classMap:function(t){if("string"==typeof t)return t.trim();if(Array.isArray(t)){let e=t.filter((t=>t));return e=e.map((t=>t&&"object"==typeof t?c.classMap(t):String(t).trim())),e=e.filter((t=>t)),e=Array.from(new Set(e)),e.join(" ")}if(t&&"object"==typeof t){const e=[];return Object.keys(t).forEach((i=>{t[i]&&e.push(i)})),e.join(" ")}return""},styleMap:function(t){if("string"==typeof t)return t.trim();if(Array.isArray(t)){let e=t.filter((t=>t));return e=e.map((t=>{const e=String(t).trim();return e?-1===e.indexOf(":")?"":e.endsWith(";")?e:`${e};`:""})),e=e.filter((t=>t)),e=Array.from(new Set(e)),e.join(" ")}if(t&&"object"==typeof t){const e=[];return Object.keys(t).forEach((i=>{const o=t[i];if(o||0===o){const t=String(o).trim();t&&e.push(`${c.pascalToKebabCase(i)}: ${t};`)}})),e.join(" ")}return""},getInstance:function(t){if(t){const e=document.getElementById(t);if(e)return a.get(e)}},setInstance:function(t,e){t&&a.set(t,e)},bindEvents:function(t,e){t&&(c.unbindEvents(t),Object.keys(t).forEach((i=>{const o=t[i];o.target=o.target||e,o.target.addEventListener(i,o.handler,o.options)})))},unbindEvents:function(t){t&&Object.keys(t).forEach((e=>{const i=t[e];i.target&&i.target.removeEventListener(e,i.handler,i.options)}))},preventDefault:function(t){t&&"function"==typeof t.preventDefault&&t.cancelable&&t.preventDefault()},debounce:function(t){let e,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:100;const o=function(){clearTimeout(e),e=setTimeout((()=>{t.apply(this,arguments)}),i)};return o.cancel=()=>{clearTimeout(e)},o},throttle:function(t){let e,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:100,o=0;const n=function(){const n=Date.now();if(n>o+i)return clearTimeout(e),o=n,void t.apply(this,arguments);clearTimeout(e),e=setTimeout((()=>{o=n,t.apply(this,arguments)}),i)};return n.cancel=()=>{clearTimeout(e),o=0},n},microtask:function(t){const e=new h,i=function(){e.start((()=>{t.apply(this,arguments)}))};return i.cancel=()=>{e.cancel()},i},nextTick:function(t){"function"==typeof window.queueMicrotask?window.queueMicrotask((()=>{t()})):Promise.resolve().then((()=>{t()}))},cancelAsync:function(t){t&&(Object.keys(t).filter((e=>e.startsWith("async")&&"function"==typeof t[e])).forEach((e=>{const i=t[e];"function"==typeof i.cancel&&(i.cancel(),t[e]=null)})),Object.keys(t).filter((t=>t.startsWith("timeout"))).forEach((e=>{clearTimeout(t[e])})))}},d=c,u={animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},g=function(t){return null!==t&&1===t.nodeType},f=function(t){let e=t.ownerDocument.defaultView;return e&&e.opener||(e=window),e.getComputedStyle(t)},p={},m=function(t,e){return null!=(i=t)&&i===i.window?t[`inner${e}`]:(function(t){return null!==t&&9===t.nodeType}(t)&&(t=t.body),t[`client${e}`]);var i},b=function(t){return this.list=[],t?this.create(t):this};function w(t){return new b(t)}b.prototype={constructor:b,Query:"Query",list:[],create:function(t){return t instanceof b?t:"string"==typeof t?this.createFromString(t):((t.nodeType||t===window)&&(this.list=[t]),this)},createFromString:function(t){if("<"===(t=t.trim())[0]&&">"===t[t.length-1]&&t.length>=3)this.parseHTML(t);else{const e=document.querySelectorAll(t);for(let t=0,i=e.length;t{this.css(e,t[e])}))}var i;return this.each((function(i){let o=e;"number"!=typeof o||u[t]||(o+="px"),i.style[t]=o})),this},attr:function(t,e){if(!t)return this;if(1===arguments.length){if("object"==typeof t)return Object.keys(t).forEach((e=>{this.attr(e,t[e])})),this;const e=this.get(0);return e?e.getAttribute(t):void 0}return this.each((function(i){i.setAttribute(t,e)})),this},removeAttr:function(t){return t?(this.each((function(e){e.hasAttribute(t)&&e.removeAttribute(t)})),this):this},removeClass:function(t){if(!arguments.length)return this.each((function(t){t.className=""})),this;if(!t||"string"!=typeof t)return this;const e=t.split(" ");return this.each((function(t){e.forEach((function(e){e&&t.classList.remove(e)}))})),this},addClass:function(t){if(!t||"string"!=typeof t)return this;const e=t.split(" ");return this.each((function(t){e.forEach((function(e){e&&t.classList.add(e)}))})),this},hasClass:function(t){if(!t||"string"!=typeof t)return!1;let e=!1;return this.each((function(i){if(i.classList.contains(t))return e=!0,!1})),e},show:function(){return this.each((function(t){if(!g(t))return;const e=function(t){if(!p[t]){const e=document.createElement(t);document.body.appendChild(e);const i=f(e).display;e.parentNode.removeChild(e),p[t]=i}return p[t]}(t.nodeName);t.style.display=e})),this},hide:function(){return this.each((function(t){if(!g(t))return;"none"!==t.style.display&&(t.style.display="none")})),this},click:function(){const t=this.get(0);return t&&"function"==typeof t.click&&t.click(),this},offset:function(){const t={left:0,top:0},e=this.get(0);if(e){const i=e.getBoundingClientRect();t.left=i.left+window.scrollX,t.top=i.top+window.scrollY}return t},clone:function(){const t=new b;return this.each((function(e){if(e&&e.cloneNode){const i=e.cloneNode(!0);t.add(i)}})),t},children:function(){const t=new b;return this.each((function(e){let i=e.firstChild;for(;i;)t.add(i),i=i.nextSibling})),t},parent:function(){const t=this.get(0);return t?new b(t.parentNode):new b},is:function(t){if(!t)return!1;const e=t.split(",");let i=!0;return this.each((function(t){if(!t.nodeName)return i=!1,!1;const o=t.nodeName.toLowerCase();return d.inList(o,e)?void 0:(i=!1,!1)})),i}},Object.defineProperty(b.prototype,"length",{get:function(){return this.list.length}});const v={createCache:function(){this.headerCache=new Map,this.rowsCache=new Map,this.dataCache=new WeakMap,this.cellResizeObserver=this.createResizeObserver((t=>{this.cellResizeHandler(t)}))},setHeaderCache:function(t,e){this.headerCache.set(t,e)},getHeaderCache:function(t){return this.headerCache.get(t)},clearHeaderCache:function(){this.headerCache.clear()},setRowCache:function(t,e){this.rowsCache.set(t,{rowNodes:e,cellNodes:new Map,observerNodes:new Map})},getRowCache:function(t){return this.rowsCache.get(t)},deleteRowCache:function(t){const e=this.getRowCache(t);if(!e)return;this.rowsCache.delete(t);const i=e.observerNodes;i&&i.forEach((t=>{t&&this.cellResizeObserver.unobserve(t)}));const o=e.rowNodes;o&&o.each((t=>{this.removeNode(t)}))},deleteCellCache:function(t,e,i){if(i){const e=i.get(t);e&&this.cellResizeObserver.unobserve(e),i.delete(t)}e&&(this.removeNode(e.get(t)),e.delete(t))},getRowNodesByIndex:function(t){const e=this.getRowCache(t);if(e)return e.rowNodes},getCellNodeByIndex:function(t,e){const i=this.getRowCache(t);if(i)return i.cellNodes.get(e)},forEachRowsCache:function(t){this.rowsCache.forEach(((e,i)=>{t.call(this,i,e.rowNodes,e.cellNodes,e.observerNodes)}))},updateRowCacheTopOffset:function(){const t=this.frozenInfo.row;this.forEachRowsCache(((e,i)=>{if(!(e<=t)&&i){const t=this.getViewRowItem(e),o=this.getViewRowTop(t);i.css("top",o)}}))},updateRowCacheTopAndHeight:function(){this.forEachRowsCache(((t,e)=>{if(e){const i=this.getViewRowItem(t),o=this.getViewRowTop(i),n=this.getRowHeight(i);e.css({top:o,height:n,"line-height":n})}}))},setNodeDataCache:function(t,e){if(t)return this.dataCache.set(t,e)},getNodeDataCache:function(t){if(t)return this.dataCache.get(t)},removeCache:function(){this.headerCache=null,this.rowsCache=null,this.dataCache=null,this.cellResizeObserver&&(this.cellResizeObserver.disconnect(),this.cellResizeObserver=null)}},H=["onUpdated","onFirstUpdated","onHeaderUpdated","onSort","onColumnAdded","onColumnRemoved","onColumnWidthChanged","onRowAdded","onRowRemoved","onRowExpanded","onRowCollapsed","onRowSubsRequest","onRowDragged","onRowDropped","onRowMoved","onRowMouseEnter","onRowMouseLeave","onSelectChanged","onCellUpdated","onCellMouseEnter","onCellMouseLeave","onClick","onDblClick","onContextMenu","onMouseOver","onMouseOut","onTouchStart","onTouchMove","onTouchEnd","onScroll","onScrollStateChanged","onMouseWheel","onResize","onLayout","onKeyDown","onDestroy"],C={};H.forEach((t=>{C[t]=t}));const y=C,R={renderCells:function(t,e){t.forEach((t=>{this.drawRowCells(t,e)}))},getCellValue:function(t,e){return t[e.id]},renderCell:function(t){const{rowItem:e,columnItem:i,cellNode:o,observerNode:n}=t,s=this.getCellValue(e,i);let r=s;this.nullFormatter&&(r=this.nullFormatter.call(this,r,e,i,o,n));const l=e.tg_formatter||i.tg_formatter;"function"==typeof l&&(r=l.call(this,r,e,i,o,n));const h=n||o;this.renderNodeContent(h,r);const{highlightKey:a}=this.options.highlightKeywords;e[a+i.id]&&this.renderSettings.highlightCells.push(o),this.trigger(y.onCellUpdated,{value:s,rowItem:e,columnItem:i,node:o})},getPreRenderColumnList:function(t,e){const i=[];if(!e.length)return i;for(let o=0,n=e.length;o{this.createCellNode(t,e)}))},getCellClass:function(t,e,i){const o=e.tg_view_index,n=["tg-cell"];return i&&n.push("tg-cell-observer"),n.push(`tg-c-${o}`),e.align&&n.push(`tg-align-${e.align}`),0===e.tg_list_index&&n.push("tg-list-first"),e.tg_list_last&&n.push("tg-list-last"),n.push(d.classMap(e.classMap)),n.push(d.classMap(t[`${e.id}ClassMap`])),d.classMap(n)},cellResizeObserverHandler:function(t,e){const i=this.options.cellResizeObserver;if("function"==typeof i)return i.apply(this,[t,e])},cellResizeHandler:function(t){const e=new Map;t.forEach((t=>{const{target:i}=t,o=this.getNodeDataCache(i.parentNode);if(!o)return;const{row:n,rowItem:s}=o;e.set(n,s)}));let i=!1;e.forEach(((t,e)=>{const o=this.getRowCache(e);if(!o)return;const n=o.observerNodes;if(!n)return;const{rowHeight:s,rowMinHeight:r}=this.options;let l=Math.max(r||s,1);n.forEach((t=>{if(t){const e=t.clientHeight+11;e>l&&(l=e)}}));this.getRowHeight(t)!==l&&(t.tg_height=l,i=!0)})),i&&this.render("rows_cache")},createCellNode:function(t,e){const i=this.getRowCache(t);if(!i)return;const o=this.getViewRowItem(t),n=this.getViewColumnItem(e);if(!o||!n)return;const s=this.cellResizeObserverHandler(o,n),r=document.createElement("div");r.setAttribute("column",e);const l=this.getCellClass(o,n,s);r.className=l;const h=d.styleMap(n.styleMap)+d.styleMap(o[`${n.id}StyleMap`]);h&&(r.style.cssText=h);const a=i.rowNodes,c=n.tg_frozen,u=this.getCellRowNode(a,c);let g;this.appendNode(u,r),s&&(g=document.createElement("div"),g.className="tg-observer",r.appendChild(g),this.cellResizeObserver.observe(g),i.observerNodes.set(e,g));const f={row:t,rowItem:o,rowNode:u,column:e,columnItem:n,cellNode:r,observerNode:g};this.setNodeDataCache(r,f),i.cellNodes.set(e,r),this.renderCell(f)},getCellRowNode:function(t,e){const i=t.get(0);if(this.frozenInfo.columns){const o=t.get(1);return this.frozenInfo.right?e?o:i:e?i:o}return i}},S={addColumn:function(t,e,i){let o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];const n=this.getToBeAddedItemList(t);if(!n.length)return!1;let s;if(null!=e&&(s=this.getColumnItem(e),!s))return!1;const r=this.getToBeAddedParentSubs(s,this.columns),l=[this.getToBeAddedPositionIndex(i,r),0].concat(n);r.splice.apply(r,l),this.onNextUpdated((function(){this.trigger(y.onColumnAdded,n)}));const h={type:"columns"};return o&&(h.scrollColumn=n[n.length-1]),this.render(h),!0},deleteColumn:function(t){const e=this.toColumnItemList(t,(t=>!t.private));return!!e.length&&(this.removeColumnsHandler(e),this.onNextUpdated((function(){this.trigger(y.onColumnRemoved,e)})),this.render("columns"),!0)},removeColumnsHandler:function(t){const e=[].concat(t);e.sort((function(t,e){return e.tg_index-t.tg_index})),e.forEach((t=>{let e;if(t===this.sortColumn&&this.removeSortColumn(),t.tg_parent)e=t.tg_parent.subs,e.splice(t.tg_sub_index,1);else{e=this.columns;const i=e.findIndex((e=>e===t));-1!==i&&e.splice(i,1)}!e.length&&t.tg_parent&&(t.tg_parent.subs=null)}))}},T={setColumnWidth:function(t,e){return this.updateColumnWidth(t,e)?(this.resize(),this):this},updateColumnWidth:function(t,e){const i=this.getColumnItem(t);return!!i&&(!!d.isNum(e)&&(e=Math.round(e),e=Math.max(0,e),i.tg_width!==e&&(i.width=e,i.minWidth=Math.min(i.minWidth,e),i.maxWidth=Math.max(i.maxWidth,e),this.updateViewColumnWidth(i),!0)))},showColumn:function(t){return this.updateColumnsInvisible(this.toColumnItemList(t),!1)},hideColumn:function(t){return this.updateColumnsInvisible(this.toColumnItemList(t),!0)},updateColumnsInvisible:function(t,e){if(!t.length)return!1;const i=[];return t.forEach((t=>{t.invisible!==e&&(t.invisible=e,t.tg_invisible=e,i.push(t))})),!!i.length&&(this.render("columns"),!0)}},E={showColumnLine:function(t){t&&(this.$columnLineContainer.show(),this.renderColumnLine(t))},hideColumnLine:function(){this.previousColumnLineActive||this.$columnLineContainer.hide()},setColumnLineActive:function(t){this.setTextSelectable(!t),this.rowHoverable=!t,t!==this.previousColumnLineActive&&(this.previousColumnLineActive=t,t?this.$columnLineItem.addClass("tg-active"):this.$columnLineItem.removeClass("tg-active"))},getColumnLineLeft:function(t){let e=t.tg_left;return t.tg_frozen||(e-=this.scrollLeft),this.frozenInfo.right&&(t.tg_frozen?e=t.tg_left+this.paneWidthL:e-=this.columnsWidthR),e},renderColumnLine:function(t){const e=this.getHeaderItemNode(t).offsetTop,i=t.tg_width,o=this.getColumnLineLeft(t);this.$columnLineItemL.css({top:e,left:o}),this.$columnLineItemR.css({top:e,left:o+i-1}),this.frozenInfo.right||(this.frozenInfo.columns&&!t.tg_frozen&&o{this.renderColumnLine(e.columnItem)})),this.resize()},columnWidthTouchStartHandler:function(t,e){d.preventDefault(e.e);const i=e.columnItem;this.showColumnLine(i),this.setColumnLineActive(!0),e.index=i.tg_index;const o=this.getColumnHeaderNode(i);e.width=o.clientWidth},columnWidthTouchMoveHandler:function(t,e){d.preventDefault(e.e);const i=e.columnItem;let o=e.width+e.offsetX;o=d.clamp(o,i.minWidth,i.maxWidth),i.tg_width!==o&&(i.width=o,this.updateViewColumnWidth(i),this.renderColumnLine(i))},columnWidthTouchEndHandler:function(t,e){d.preventDefault(e.e),this.setColumnLineActive(!1),this.hideColumnLine(),this.resize()}},I={getColumnItem:function(t){return d.isNum(t)?(t<0&&(t=this.columnsInfo.length+t),this.columnsInfo.indexCache[t]):t?d.isNum(t.tg_index)?t:this.getColumnItemById(t.id||t):void 0},getColumnItemById:function(t){return this.getColumnItemBy("id",t)},getColumnItemBy:function(t,e){if(void 0!==e)return this.columnsInfo.indexCache.find((i=>i[t]===e))},getColumnsLength:function(t){return t?this.columnsInfo.length:this.viewColumns.length},getViewColumnItem:function(t){return this.viewAllColumns[t]},isColumnSortable:function(t){return!!t&&(!t.tg_group&&(!(!t.name||!t.id)&&this.isSortable(t)))},isColumnResizable:function(t){return!!t&&(!t.tg_group&&(!d.hasOwn(t,"resizable")||Boolean(t.resizable)))},updateViewColumnWidth:function(t){return t.tg_width=t.width,this.updateColumnHeaderSize(t),this.updateTotalColumnsWidth(),this.updateHeaderLayerHeight(),this.cssRulesInvalid=!0,this.resizeBodyHandler(),this.trigger(y.onColumnWidthChanged,t),!0},updateTotalColumnsWidth:function(){this.blankColumn.tg_width=0;const t=this.viewColumns;let e=0,i=0;const o=this.frozenInfo.columns,n=t.length;let s=0;for(let r=0;r0&&(s+=l,o&&r>=o?i+=l:e+=l)}if(this.frozenInfo.right){const t=e;e=i,i=t}this.columnsWidthL=e,this.columnsWidthR=i,this.columnsWidth=e+i},updateColumnHeaderSize:function(t){this.updateColumnHeaderWidth(t),this.updateColumnHeaderHeight(t,!0),this.updateColumnGroupWidth(t)},updateColumnHeaderWidth:function(t){const e=this.getColumnHeaderNode(t);if(!e)return;const i=t.tg_width;this.isInvisible(t)||i<=0?e.style.display="none":(e.style.display="",e.style.width=`${i}px`)},updateColumnHeaderHeight:function(t,e){if(t.tg_height=0,t.tg_width<=0)return;if(this.isInvisible(t))return;e&&(t.tg_element_height=0);const i=t.tg_element_height;if(i)return void(t.tg_height=i);const o=this.getColumnHeaderHeight(t);t.tg_height=o,t.tg_element_height=o},getColumnHeaderHeight:function(t){const e=this.getColumnHeaderNode(t);return e?e.clientHeight:0},updateColumnGroupWidth:function(t){const e=t.tg_parent;if(!e)return;const i=this.getColumnGroupWidth(e);e.tg_width!==i&&(e.tg_width=i,this.updateColumnHeaderSize(e))},getColumnGroupWidth:function(t){if(this.isInvisible(t))return 0;let e=0;return t.subs&&t.subs.forEach((t=>{this.isInvisible(t)||d.isNum(t.tg_width)&&(e+=t.tg_width)})),e}},L={initTreeInfo:function(t,e){const i=[];let o=!1,n=0,s=0;const r=function(t,r,l){(t=>{t.invisible?t.tg_invisible=!0:t.tg_invisible&&(t.tg_invisible=!1)})(t),((t,i)=>{if(e>=0&&!t.tg_invisible)return t.tg_frozen=!0,void(e-=1);t.tg_frozen&&(t.tg_frozen=!1)})(t),(t=>{if(d.hasOwn(t,"subs")){if(Array.isArray(t.subs))return o=!0,t.tg_group=!0,void(t.tg_subs_length=t.subs.length);t.subs=null}t.tg_group&&(t.tg_group=!1)})(t),((t,e)=>{t.tg_parent=e;let i=0;e&&(i=e.tg_level+1,i>n&&(n=i)),t.tg_level=i})(t,l),t.tg_index=s,t.tg_sub_index=r,i.push(t),s+=1},l=function(t,e){let i=0;const o=t.length;for(;i{if(!this.isInvisible(e))return this.isRowSelectable(e)?t(e,i,o):void 0})),this},toRowItemList:function(t,e){let i=d.toList(t).map((t=>this.getRowItem(t))).filter((t=>t));return"function"==typeof e&&(i=i.filter(e)),i},toColumnItemList:function(t,e){let i=d.toList(t).map((t=>this.getColumnItem(t))).filter((t=>t));return"function"==typeof e&&(i=i.filter(e)),i},isRowLeaf:function(t){return!!t&&("blank"!==t.formatter&&(!t.tg_frozen&&!t.tg_group))},isRowSelectable:function(t){return!!t&&(d.hasOwn(t,"selectable")?Boolean(t.selectable):this.isRowLeaf(t))},isEmptyGroup:function(t){return!(!t||!t.tg_group||0!==t.tg_subs_length)},isInvisible:function(t){return!!t&&(!(!t.tg_filtered&&!t.tg_invisible)||!!this.isInvisible(t.tg_parent))},isSortable:function(t){return!!t&&(!d.hasOwn(t,"sortable")||Boolean(t.sortable))},isCollapsedChanged:function(t,e){return Boolean(t.collapsed)!==e},isSelectedChanged:function(t,e){return Boolean(t.selected)!==e}},x={updateCssRules:function(){this.cssRulesInvalid&&(this.cssRulesInvalid=!1,this.initCssRules(),this.updateColumnsCssRules(),this.updateHeadersCssRules(),this.updateStyleElement())},initCssRules:function(){this.removeCssRules(),this.cssList={},this.cssDisplayCache={};const t=this.getRowHeight(),e=this.createCssRule(".tg-row");e.height=`${t}px`,e["line-height"]=`${t}px`},resetCssDisplay:function(t){if(this.cssDisplayCache){t=t||"";for(const e in this.cssDisplayCache)if(d.hasOwn(this.cssDisplayCache,e)){this.cssDisplayCache[e].style.display=t}}},updateColumnsCssRules:function(){const t=this.viewColumns,e=this.frozenInfo.column,i={};let o=0;for(let n=0,s=t.length;n=0;i--){const e=this.headerLayerHeight[i],o=this.createCssRule(`.tg-h-${i}`);o.bottom=`${t}px`,o.height=`${e}px`,t+=e}this.getLayerCombinations(e).forEach((t=>{const e=this.createCssRule(`.tg-h-${t}`);let i=0;t.split("").forEach((t=>{i+=this.headerLayerHeight[t]||0})),e.height=`${i}px`}))},getLayerCombinations:function(t){let e="";for(;t>=0;)e+=t,t--;if(e.length<2)return[];const i=[],o=function(t,e){const n=t.length;let s=e+2;for(;s<=n;){const o=t.substring(e,s);i.push(o),s++}e=i){let t="Possible Event memory leak detected. ";return t+=`More than ${i} (max limit) listeners added. `,t+="Use setMaxListeners(n) to increase limit.",void console.warn(t,e)}t.events.push(e)},addEvents:function(t,e,i){e.forEach((function(e){const o=e.type;t[o]||(t[o]={events:[]});if("function"!=typeof e.handler)return;const n=t[o];N.addEvent(n,e,i)}))},removeEventByNamespace:function(t,e){Object.keys(t).forEach((function(i){const o=t[i],n=[];o.events.forEach((function(t){t&&t.namespace!==e&&n.push(t)})),o.events=n}))},removeEventByHandler:function(t,e,i){const o=t[e];if(!o)return;const n=[];o.events.forEach((function(t){t&&t.handler!==i&&n.push(t)})),o.events=n},removeEventByType:function(t,e){const i=t[e];i&&(i.events=[])},removeEvent:function(t,e){const i=e.type,o=e.namespace;if(!i&&o)return void N.removeEventByNamespace(t,o);const n=e.handler;"function"!=typeof n?N.removeEventByType(t,i):N.removeEventByHandler(t,i,n)},removeEvents:function(t,e){e.forEach((function(e){N.removeEvent(t,e)}))},removeAllEvents:function(t){Object.keys(t).forEach((function(e){N.removeEventByType(t,e)}))},sendEventList:function(t,e,i,o){const n=e.events;for(let e=0;e!t.onceCalled))},sendEvent:function(t,e,i,o){const n=e[i];if(!n)return;const s=new P({type:i,target:t,currentTarget:t,data:o});N.sendEventList(t,n,s,o)}},_=N;class k{maxListeners=10;setMaxListeners(t){this.maxListeners=Number(t)||10}getMaxListeners(){return this.maxListeners}getEventListeners(){return this.eventListeners||(this.eventListeners={}),this.eventListeners}delEventListeners(){this.eventListeners=null}bind(t,e,i){const o=_.getEventList(this,t,e,i);if(!o.length)return this;const n=this.getEventListeners();return _.addEvents(n,o,this.maxListeners),this}once(t,e){return this.bind(t,e,{once:!0})}unbind(t,e,i){const o=this.getEventListeners();if(!arguments.length)return _.removeAllEvents(o),this;const n=_.getEventList(this,t,e,i);return n.length?(_.removeEvents(o,n),this):this}trigger(t,e){const i=this.getEventListeners();return _.sendEvent(this,i,t,e),this}}const V={DRAG_START:"drag_start",DRAG_MOVE:"drag_move",DRAG_END:"drag_end"};class O extends k{static EVENT=V;generateOptions(t){return d.merge({type:"mouse",startX:0,startY:0,previousX:0,previousY:0,currentX:0,currentY:0,moveX:0,moveY:0,offsetX:0,offsetY:0,changed:!1},t)}start(t,e){t&&(this.unbindEvents(),this.bindEvents(),this.options=this.generateOptions(e),this.startHandler(t))}bindEvents(){this.windowEvents={mousemove:{handler:t=>{this.iframeHandler(t),this.mouseMoveHandler(t)},options:!0},mouseup:{handler:t=>{this.mouseUpHandler(t)},options:{once:!0}}},d.bindEvents(this.windowEvents,window)}unbindEvents(){d.unbindEvents(this.windowEvents),this.windowEvents=null,this.previousIframe&&(this.previousIframe.classList.remove("tg-pointer-events-none"),this.previousIframe=null)}iframeHandler(t){const e=t.target;"IFRAME"===e.nodeName&&e!==this.previousIframe&&(this.previousIframe&&this.previousIframe.classList.remove("tg-pointer-events-none"),e.classList.add("tg-pointer-events-none"),this.previousIframe=e)}startHandler(t){const e=this.options;e.e=t,e.startX=t.pageX,e.startY=t.pageY,e.currentX=e.startX,e.currentY=e.startY,this.hasMoved=!1}mouseMoveHandler(t){d.preventDefault(t);const e=this.options;e.e=t,e.previousX=e.currentX,e.previousY=e.currentY,e.currentX=t.pageX,e.currentY=t.pageY,e.moveX=e.currentX-e.previousX,e.moveY=e.currentY-e.previousY,e.offsetX=e.currentX-e.startX,e.offsetY=e.currentY-e.startY,e.changed=!(0===e.offsetX&&0===e.offsetY),this.hasMoved?this.trigger(V.DRAG_MOVE,e):(this.hasMoved=!0,this.trigger(V.DRAG_START,e))}mouseUpHandler(t){this.unbindEvents();const e=this.options;this.hasMoved&&(e.e=t,d.preventDefault(t),this.trigger(V.DRAG_END,e))}destroy(){this.unbindEvents(),this.unbind()}}const $={Linear:{None:function(t){return t}}},D={MOTION_START:"motion_start",MOTION_MOVE:"motion_move",MOTION_END:"motion_end",MOTION_STOP:"motion_stop"};class B extends k{static EVENT=D;constructor(t){super(),this.constructorOptions=t,this.stopped=!0}generateOptions(t){return d.merge({easing:null,duration:100,from:0,till:1,data:0},this.constructorOptions,t)}stop(){return this.stopped||(this.stopped=!0,this.cancelAnimationFrame(),this.trigger(D.MOTION_STOP,this.data)),this}start(t){return this.stop(),this.stopped=!1,this.options=this.generateOptions(t),this.initCalculation(),this.data=this.calculateHandler(0),this.trigger(D.MOTION_START,this.data),this.stopped||(this.time=Date.now(),this.requestAnimationFrame(this.moveHandler)),this}requestAnimationFrame(t){this.requestId=window.requestAnimationFrame((()=>{t.apply(this)}))}cancelAnimationFrame(){window.cancelAnimationFrame(this.requestId)}getEasing(t){return"function"!=typeof t&&(t=d.getValue($,t,$.Linear.None)),t}moveHandler(){const t=Date.now()-this.time,e=this.duration;if(t{o[n]=this.calculateNumber(t,e[n],i[n])})),o):(this.calculateKeys=[],Object.keys(e).forEach((n=>{const s=e[n],r=i[n];d.isNum(s)&&d.isNum(r)&&(o[n]=this.calculateNumber(t,s,r),this.calculateKeys.push(n))})),o)}calculateNumber(t,e,i){return(i-e)*t+e}calculateNone(t,e,i){return e}destroy(){this.stop(),this.unbind()}}const A={TOUCH_START:"touch_start",TOUCH_MOVE:"touch_move",TOUCH_END:"touch_end",TOUCH_INERTIA:"touch_inertia"};class W extends k{static EVENT=A;generateOptions(t){return d.merge({type:"touch",startX:0,startY:0,previousX:0,previousY:0,currentX:0,currentY:0,moveX:0,moveY:0,offsetX:0,offsetY:0,changed:!1,touchLength:0,direction:"",inertia:!1,inertiaTime:200},t)}start(t,e){t&&(this.unbindEvents(),this.bindEvents(),this.options=this.generateOptions(e),this.startHandler(t))}bindEvents(){this.touchEvents={touchmove:{handler:t=>{this.touchMoveHandler(t)},options:{passive:!1}},touchend:{handler:t=>{this.touchEndHandler(t)},options:{passive:!1,once:!0}},touchcancel:{handler:t=>{this.touchCancelHandler(t)},options:{passive:!1,once:!0}}},d.bindEvents(this.touchEvents,document.body)}unbindEvents(){this.motionStop(),d.unbindEvents(this.touchEvents),this.touchEvents=null}startHandler(t){this.trackingPoints=[];const e=t.touches,i=e[0];if(!i)return;const o=this.options;o.e=t,o.startX=i.clientX,o.startY=i.clientY,o.currentX=o.startX,o.currentY=o.startY,o.touchLength=e.length,this.addTrackingPoint(o),this.trigger(A.TOUCH_START,o)}touchMoveHandler(t){const e=t.touches,i=e[0];if(!i)return;const o=this.options;o.e=t,o.previousX=o.currentX,o.previousY=o.currentY,o.currentX=i.clientX,o.currentY=i.clientY,o.moveX=o.currentX-o.previousX,o.moveY=o.currentY-o.previousY,o.offsetX=o.currentX-o.startX,o.offsetY=o.currentY-o.startY,o.changed=!(0===o.offsetX&&0===o.offsetY),o.touchLength=e.length,o.direction=this.getDirection(o),this.addTrackingPoint(o),this.trigger(A.TOUCH_MOVE,o)}touchEndHandler(t){this.unbindEvents();const e=this.options;e.e=t,this.trigger(A.TOUCH_END,e);const i=t.changedTouches[0];if(!i)return;const o=t.touches;e.touchLength=o.length,e.touchLength>0||(e.currentX=i.clientX,e.currentY=i.clientY,this.addTrackingPoint(e),this.motionStart())}touchCancelHandler(t){this.unbindEvents(),this.trigger(A.TOUCH_END,this.options)}getMotionInfo(){const t=this.trackingPoints;if(t.length<2)return;if(this.filterTrackingPoints(t),t.length<2)return;const e=t[0],i=t[t.length-1],o=i.t-e.t;if(o<=0)return;let n=i.x-e.x,s=i.y-e.y;const r=Math.abs(n),l=Math.abs(s);r>l?s=0:n=0;return{offsetDistance:Math.max(r,l),offsetTime:o,offsetX:n,offsetY:s}}motionStart(){const t=this.options;if(!t.inertia)return;const e=this.getMotionInfo();if(!e)return;const i=500*e.offsetDistance/50,o=d.clamp(i,20,2e3),n={x:20*(e.offsetX/e.offsetTime),y:20*(e.offsetY/e.offsetTime)};this.motion=new B,this.motion.bind(B.EVENT.MOTION_MOVE,((e,i)=>{t.touchInertiaX=i.x,t.touchInertiaY=i.y,this.trigger(A.TOUCH_INERTIA,t)})),this.motion.start({duration:o,from:n,till:{x:0,y:0}})}motionStop(){this.motion&&(this.motion.destroy(),this.motion=null)}getDirection(t){const i=t.offsetX,o=t.offsetY,n=Math.abs(i),s=Math.abs(o);if(n0)return e.UP;if(o<0)return e.DOWN}if(n>s){if(i>0)return e.LEFT;if(i<0)return e.RIGHT}return""}filterTrackingPoints(t){t.reverse();const e=t.length,i=Date.now(),o=this.options.inertiaTime;for(let n=0;no){t.length=n;break}t.reverse()}addTrackingPoint(t){if(!t.inertia)return;const e=t.currentX,i=t.currentY,o=Date.now(),n=this.trackingPoints;n.push({x:e,y:i,t:o}),n.length>100&&this.filterTrackingPoints(n)}destroy(){this.unbindEvents(),this.unbind()}}const F={getAllEvents:function(){return[].concat(H)},bindEvents:function(){this.unbindEvents(),this.containerEvents={mousedown:{handler:t=>{this.containerMouseDownHandler(t)},options:!0},mousemove:{handler:t=>{this.containerMouseMoveHandler(t)},options:!0},mouseover:{handler:t=>{this.containerMouseOverOutHandler(t,!0)},options:!0},mouseout:{handler:t=>{this.containerMouseOverOutHandler(t,!1)},options:!0},mouseenter:{handler:t=>{this.containerMouseEnterLeaveHandler(t,!0)},options:!0},mouseleave:{handler:t=>{this.containerMouseEnterLeaveHandler(t,!1)},options:!0},touchstart:{handler:t=>{this.containerTouchStartHandler(t)},options:{passive:!1}},touchmove:{handler:t=>{this.containerTouchMoveHandler(t)},options:{passive:!1}},touchend:{handler:t=>{this.containerTouchEndHandler(t)},options:{passive:!1}},touchcancel:{handler:t=>{this.containerTouchCancelHandler(t)},options:{passive:!1}},wheel:{handler:t=>{this.containerWheelHandler(t)},options:{passive:!1}},click:{handler:t=>{this.containerClickHandler(t)},options:!0},dblclick:{handler:t=>{this.containerDblClickHandler(t)},options:!0},contextmenu:{handler:t=>{this.containerContextMenuHandler(t)},options:!0},selectstart:{handler:t=>{this.containerSelectStartHandler(t)},options:!0},keydown:{handler:t=>{this.containerKeyDownHandler(t)},options:!0}},d.bindEvents(this.containerEvents,this.container),this.columnWidthDrag=new O,this.columnWidthDrag.bind(O.EVENT.DRAG_START,((t,e)=>{this.columnWidthDragStartHandler(t,e)})).bind(O.EVENT.DRAG_MOVE,((t,e)=>{this.columnWidthDragMoveHandler(t,e)})).bind(O.EVENT.DRAG_END,((t,e)=>{this.columnWidthDragEndHandler(t,e)})),this.columnWidthTouch=new W,this.columnWidthTouch.bind(W.EVENT.TOUCH_START,((t,e)=>{this.columnWidthTouchStartHandler(t,e)})).bind(W.EVENT.TOUCH_MOVE,((t,e)=>{this.columnWidthTouchMoveHandler(t,e)})).bind(W.EVENT.TOUCH_END,((t,e)=>{this.columnWidthTouchEndHandler(t,e)})),this.rowDrag=new O,this.rowDrag.bind(O.EVENT.DRAG_START,((t,e)=>{this.rowDragStartHandler(t,e)})).bind(O.EVENT.DRAG_MOVE,((t,e)=>{this.rowDragMoveHandler(t,e)})).bind(O.EVENT.DRAG_END,((t,e)=>{this.rowDragEndHandler(t,e)})),this.rowTouch=new W,this.rowTouch.bind(W.EVENT.TOUCH_START,((t,e)=>{this.rowDragStartHandler(t,e)})).bind(W.EVENT.TOUCH_MOVE,((t,e)=>{this.rowDragMoveHandler(t,e)})).bind(W.EVENT.TOUCH_END,((t,e)=>{this.rowDragEndHandler(t,e)})),this.scrollTouch=new W,this.scrollTouch.bind(W.EVENT.TOUCH_START,((t,e)=>{this.scrollTouchStartHandler(t,e)})).bind(W.EVENT.TOUCH_MOVE,((t,e)=>{this.scrollTouchMoveHandler(t,e)})).bind(W.EVENT.TOUCH_END,((t,e)=>{this.scrollTouchEndHandler(t,e)})).bind(W.EVENT.TOUCH_INERTIA,((t,e)=>{this.scrollTouchInertiaHandler(t,e)}))},isDefaultPrevented:function(t){if(t){if(t.defaultPrevented)return!0;if(t.e&&t.e.defaultPrevented)return!0}return!1},getEventClosestNode:function(t,e){if(t&&t!==this.container)return t.classList.contains(e)?t:this.getEventClosestNode(t.parentNode,e)},getEventClosestData:function(t){if(!t||t===this.container)return;const e=this.getNodeDataCache(t);return e||this.getEventClosestData(t.parentNode)},getEventData:function(t){const e=this.getEventClosestData(t.target);if(e)return e.e=t,e},getWheelDelta:function(t,e,i){let o=t.deltaX,n=t.deltaY;return d.isNum(o)||(o=d.toNum(t.wheelDeltaX)),d.isNum(n)||(n=d.toNum(t.wheelDeltaY||t.wheelDelta)),1===t.deltaMode?(n*=e,o*=e):2===t.deltaMode&&(n*=i,o*=i),{deltaX:o,deltaY:n}},columnResizingMouseDownHandler:function(t){const e=this.getEventData(t);e&&this.columnWidthDrag.start(t,{columnItem:e.columnItem})},columnResizingTouchStartHandler:function(t){const e=this.getEventData(t);e&&this.columnWidthTouch.start(t,{columnItem:e.columnItem})},columnResizingMouseEnterLeaveHandler:function(t,e){const i=this.getEventData(t);i&&(e?this.showColumnLine(i.columnItem):this.hideColumnLine())},rowDragMouseDownHandler:function(t){const e=this.getEventData(t);e&&this.rowDrag.start(t,{rowItem:e.rowItem})},rowDragTouchStartHandler:function(t){const e=this.getEventData(t);e&&(this.protectedItem=e,this.rowTouch.start(t,{rowItem:e.rowItem}))},scrollPaneTouchStartHandler:function(t){if(!this.hasHScroll&&!this.hasVScroll)return;const e=this.getEventData(t);this.protectedItem=e,this.scrollTouch.start(t,{inertia:!0})},sortHandler:function(t,e){const i=e.columnItem;if(!this.isColumnSortable(i))return;const o=this.getEventClosestNode(t.target,"tg-column-name"),n=this.getEventClosestNode(t.target,"tg-column-sort");(o||n)&&(this.trigger(y.onSort,e),this.isDefaultPrevented(e)||this.setSortColumn(i))},selectIconAllClickHandler:function(t){const e=w(t);let i=!1;(e.hasClass("tg-selected")||e.hasClass("tg-mixed"))&&(i=!0),i=!i,this.selectAll(i)},cellEnterLeaveHandler:function(t,e){const i=this.getEventData(t);i&&(e?this.trigger(y.onCellMouseEnter,i):this.trigger(y.onCellMouseLeave,i))},rowEnterLeaveHandler:function(t,e){const i=this.getEventData(t);if(i&&(e?this.trigger(y.onRowMouseEnter,i):this.trigger(y.onRowMouseLeave,i),!this.isDefaultPrevented(i)))return this.renderRowHover(i.rowItem,e),this},containerMouseDownHandler:function(t){if(this.getEventClosestNode(t.target,"tg-column-resizing"))this.columnResizingMouseDownHandler(t);else if(this.options.rowDragVisible){this.getEventClosestNode(t.target,"tg-row-drag-icon")&&this.rowDragMouseDownHandler(t)}},containerMouseMoveHandler:function(t){this.scrollbarFadeInOutHandler(t,!0)},containerMouseOverOutHandler:function(t,e){const i=this.getEventClosestNode(t.target,"tg-cell"),o=this.getEventClosestNode(t.target,"tg-header-item");if(i||o){const i=this.getEventData(t);if(!i)return;e?this.trigger(y.onMouseOver,i):this.trigger(y.onMouseOut,i)}},containerMouseEnterLeaveHandler:function(t,e){this.scrollbarFadeInOutHandler(t,e);if(w(t.target).hasClass("tg-column-resizing"))return void this.columnResizingMouseEnterLeaveHandler(t,e);if(w(t.target).hasClass("tg-cell"))return void this.cellEnterLeaveHandler(t,e);w(t.target).hasClass("tg-row")&&this.rowEnterLeaveHandler(t,e)},containerTouchStartHandler:function(t){this.scrollTouch.motionStop();if(this.getEventClosestNode(t.target,"tg-column-resizing"))return void this.columnResizingTouchStartHandler(t);if(this.options.rowDragVisible){if(this.getEventClosestNode(t.target,"tg-row-drag-icon"))return void this.rowDragTouchStartHandler(t)}const e=this.getEventData(t);e&&(this.trigger(y.onTouchStart,e),this.isDefaultPrevented(e))||this.scrollPaneTouchStartHandler(t)},containerTouchMoveHandler:function(t){const e=this.getEventData(t);e&&this.trigger(y.onTouchMove,e)},containerTouchEndHandler:function(t){const e=this.getEventData(t);e&&this.trigger(y.onTouchEnd,e)},containerTouchCancelHandler:function(t){this.trigger(y.onTouchEnd,{e:t})},containerWheelHandler:function(t){if(this.hasMask)return;const e=this.getRowHeight(),i=this.bodyHeight,o=this.getWheelDelta(t,e,i),n={e:t,deltaX:o.deltaX,deltaY:o.deltaY,delta:o};if(this.trigger(y.onMouseWheel,n),this.isDefaultPrevented(n))return;let s=!1;this.scrollPaneHidden&&(s=this.scrollPaneFrozen.setOffsetH(o.deltaX),o.deltaX=0);(this.scrollPane.mouseWheelHandler(o)||s)&&d.preventDefault(t)},containerClickHandler:function(t){if(this.getEventClosestNode(t.target,"tg-tree-icon-all"))return void this.toggleAllRows();const e=this.getEventClosestNode(t.target,"tg-select-icon-all");if(e)return void this.selectIconAllClickHandler(e);const i=this.getEventData(t);if(!i)return;if(this.getEventClosestNode(t.target,"tg-header-item")){if(this.trigger(y.onClick,i),this.isDefaultPrevented(i))return;return void this.sortHandler(t,i)}if(this.getEventClosestNode(t.target,"tg-tree-icon"))return void this.toggleRow(i.rowItem);this.getEventClosestNode(t.target,"tg-select-icon")?this.setRowSelected(i.rowItem,t):this.trigger(y.onClick,i)},containerDblClickHandler:function(t){const e=this.getEventData(t)||{e:t};this.trigger(y.onDblClick,e)},containerContextMenuHandler:function(t){const e=this.getEventData(t)||{e:t};this.trigger(y.onContextMenu,e)},containerSelectStartHandler:function(t){if(this.options.textSelectable)return;w(t.target).is("input,textarea,code")||d.preventDefault(t)},containerKeyDownHandler:function(t){if(this.hasMask)return;const e={e:t};if(this.trigger(y.onKeyDown,e),this.isDefaultPrevented(e))return;const i=t.keyCode,o={9:this.keyTabHandler,13:this.keyEnterHandler,27:this.keyEscHandler,33:this.keyPageUpHandler,34:this.keyPageDownHandler,35:this.keyEndHandler,36:this.keyHomeHandler,37:this.keyLeftHandler,38:this.keyUpHandler,39:this.keyRightHandler,40:this.keyDownHandler}[i];if(!o)return;o.call(this,t)&&d.preventDefault(t)},unbindEvents:function(){d.unbindEvents(this.containerEvents),this.containerEvents=null,this.columnWidthDrag&&(this.columnWidthDrag.destroy(),this.columnWidthDrag=null),this.columnWidthTouch&&(this.columnWidthTouch.destroy(),this.columnWidthTouch=null),this.rowDrag&&(this.rowDrag.destroy(),this.rowDrag=null),this.rowTouch&&(this.rowTouch.destroy(),this.rowTouch=null),this.scrollTouch&&(this.scrollTouch.destroy(),this.scrollTouch=null),this.protectedItem=null}},G={exportData:function(t){const e=this.getData();return{columns:this.getTreeSnapshot(e.columns,t),rows:this.getTreeSnapshot(e.rows,t)}},isItemExportable:function(t){return!!t&&(!d.hasOwn(t,"exportable")||Boolean(t.exportable))},getTreeSnapshot:function(t,e){const i=(t,o)=>{d.isList(o)&&o.forEach((o=>{if(!this.isItemExportable(o))return;const n=this.getItemSnapshot(o,e),s=o.subs;Array.isArray(s)&&(n.subs=[],i(n.subs,s)),t.push(n)}))},o=[];return i(o,t),o},getItemSnapshot:function(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const i={};return Object.keys(t).forEach((o=>{!0!==e[o]?!1!==e[o]&&"subs"!==o&&0!==o.indexOf("tg_")&&(i[o]=t[o]):i[o]=t[o]})),i}},j={flushRow:function(t){d.toList(t).forEach((t=>{this.deleteRowCache(t)}))},flushRowFrom:function(t){d.isNum(t)&&(0!==t?this.forEachRowsCache((e=>{e>=t&&this.deleteRowCache(e)})):this.flushBody())},flushBody:function(){this.forEachRowsCache((t=>{this.deleteRowCache(t)}))},flushSort:function(){this.frozenInfo.rows?this.flushRowFrom(this.frozenInfo.rows):this.flushBody()},flushColumn:function(t){const e=d.toList(t);this.forEachRowsCache(((t,i,o,n)=>{e.forEach((t=>{this.deleteCellCache(t,o,n)}))}))},flushColumnFrom:function(t){d.isNum(t)&&this.forEachRowsCache(((e,i,o,n)=>{o.forEach(((e,i)=>{i>=t&&this.deleteCellCache(i,o,n)}))}))},flushCell:function(t,e){const i=d.toList(t),o=d.toList(e);i.forEach((t=>{const e=this.getRowCache(t);if(!e)return;const i=e.cellNodes,n=e.observerNodes;o.forEach((t=>{this.deleteCellCache(t,i,n)}))}))},flushWithViewport:function(){const{rows:t,columns:e}=this.viewport;this.forEachRowsCache(((i,o,n,s)=>{t.includes(i)?n.forEach(((t,i)=>{e.includes(i)||this.deleteCellCache(i,n,s)})):this.deleteRowCache(i)}))}},U={"sort-h":'\n\n \n \n \n \n\n',"sort-v":'\n\n \n \n \n \n\n',checkbox:'\n\n \n \n \n\n',radio:'
    ',drag:'\n\n \n\n',tree:'\n\n \n \n\n'},X={icons:U,getIcon:function(t){let e=U[t];return e=String(e).trim(),e}},Y={header:function(t,e,i,o){return t},null:function(t,e,i,o){return e&&e.tg_group?t:null==t?"—":t},blank:function(t,e,i,o){return""},string:function(t,e,i,o){return t},number:function(t,e,i,o){return t},icon:function(t,e,i,o){return`${t}`},select:function(t,e,i,o){return this.isRowSelectable(e)?this.getSelectFormatterContent(e):""},rowDrag:function(t,e,i,o){return this.getRowDragFormatterContent(e)},rowNumber:function(t,e,i,o){return e.tg_row_number||""},tree:function(t,e,i,o){return this.getTreeFormatterContent(t,e)}},K={setFormatter:function(t,e){this.renderType="all";let i=t;if("string"==typeof t){if(this.formatters)return this.formatters[t]=e,this;i={},i[t]=e}return this.customFormatters=i,this},getFormatter:function(t){if(!t)return;const e=this.formatters[t];return"function"==typeof e?e.bind(this):void 0},getDefaultFormatter:function(t){return(Y[t]||Y.string).bind(this)},getSelectFormatterContent:function(t){let e="radio";this.options.selectMultiple&&(e="checkbox");const i=X.getIcon(e);return`
    ${i}
    `},getRowDragFormatterContent:function(t){if(t.tg_frozen)return"";return`
    ${X.getIcon("drag")}
    `},getTreeIndentWidth:function(t,i,o){if(!t)return 0;let n=5;return i||(n+=e.TREE_INDENT),n+=o*e.TREE_INDENT,n},getTreeFormatterContent:function(t,e){const i=this.rowsInfo.isTree,o=e.tg_group,n=this.isEmptyGroup(e);n&&(e.collapsed=!0);const s=e.collapsed,r=d.toNum(e.tg_level),l=this.getTreeIndentWidth(i,o,r),h=[];if(h.push(`
    `),o){const t={"tg-tree-icon":!0,"tg-tree-icon-collapsed":s,"tg-tree-icon-expanded":!s,"tg-tree-icon-empty":n},e=X.getIcon("tree"),i=`
    ${e}
    `;h.push(i)}return h.push(`
    ${t}
    `),h.push("
    "),h.join("")}},q={renderHeaderTables:function(){this.clearHeaderCache();const t=this.viewColumns,e=this.frozenInfo.columns;this.hasTreeColumn=!1,this.hasSortColumn=!1;let i=[],o=[];for(let n=0,s=t.length;n=e?o.push(s):i.push(s)}if(this.frozenInfo.right){const t=i;i=o,o=t}this.renderHeaderTable(i,this.$headerL),this.renderHeaderTable(o,this.$headerR)},renderHeaderTable:function(t,e){const i=document.createElement("div"),o=["tg-header-table"];this.hasSortColumn&&(o.push("tg-header-sortable"),o.push(`tg-header-sort-${this.options.sortIndicator}`)),i.className=d.classMap(o);const n=t.length;if(n){let e=t[n-1];e&&"tg-column-blank"===e.id&&(e=t[n-2]),t.forEach((t=>{this.renderHeaderItem(t,i,e)}))}e.append(i)},renderHeaderItem:function(t,e,i){const o=t.tg_view_index;if(this.getHeaderCache(o))return;const n=this.getHeaderItemClass(t,i),s=d.styleMap(t.headerStyleMap),r={column:o,class:n,data:t.id};s&&(r.style=s);const l=[this.createColumnHeader(t)];if(this.isColumnResizable(t)){const e=this.createColumnResizing(t);l.push(e)}const h=this.createElement("div",r,l);e.appendChild(h),this.setHeaderCache(o,h),this.setNodeDataCache(h,{rowItem:this.headerRowItem,column:o,columnItem:t,headerNode:h}),t.tg_parent&&this.renderHeaderItem(t.tg_parent,e)},createColumnHeader:function(t){const e={class:this.getHeaderClass(t),style:this.getHeaderStyle(t)},i=[this.createColumnName(t)];if(this.hasSortColumn&&!t.tg_group){const e=this.createColumnSort(t);i.push(e)}return this.createElement("div",e,i)},createColumnName:function(t){const e=["tg-column-name"];t.tg_group&&e.push("tg-header-group-name");const i={class:e.join(" ")};let o=t.name;const n=t.tg_headerFormatter;return"function"==typeof n&&(o=n.call(this,o,this.headerRowItem,t)),"tree"===t.formatter?o=this.createHeaderTreeName(o):t===this.selectColumn&&this.isSelectAllVisible()&&(o=this.createHeaderSelectName()),this.createElement("div",i,o)},createHeaderTreeName:function(t){this.hasTreeColumn=!0;const e=[];if(this.options.collapseAllVisible){const t=X.getIcon("tree"),i=this.createElement("div",{class:"tg-tree-icon tg-tree-icon-all"},t);e.push(i)}else{const t=this.createElement("div",{class:"tg-tree-icon"});e.push(t)}const i=this.createElement("div",{class:"tg-tree-name"},t);e.push(i);return this.createElement("div",{class:"tg-tree"},e)},createHeaderSelectName:function(){const t=X.getIcon("checkbox");return this.createElement("div",{class:"tg-select-icon-all tg-checkbox"},t)},createColumnSort:function(t){let e;return this.isColumnSortable(t)&&(e="h"===this.options.sortIndicator?this.createSortIndicatorH(t):this.createSortIndicatorV(t)),this.createElement("div",{class:"tg-column-sort"},e)},createSortIndicatorH:function(t){const e=X.getIcon("sort-h"),i=[this.createElement("div",{class:"tg-sort-indicator-line"}),this.createElement("div",{class:"tg-sort-indicator-icon"},e)];return this.createElement("div",{class:"tg-sort-indicator"},i)},createSortIndicatorV:function(t){const e=X.getIcon("sort-v"),i=[this.createElement("div",{class:"tg-sort-indicator-icon"},e)];return this.createElement("div",{class:"tg-sort-indicator"},i)},createColumnResizing:function(){return this.createElement("div",{class:"tg-column-resizing"})},getHeaderItemClass:function(t,e){const i=["tg-header-item"];return t.tg_group&&i.push("tg-header-group-item"),t===e&&i.push("tg-header-column-last"),i.push(`tg-c-${t.tg_view_index}`),i.push(`tg-h-${t.tg_layer}`),t.tg_combination&&i.push(`tg-h-${t.tg_combination}`),i.push(d.classMap(t.headerClassMap)),d.classMap(i)},getHeaderClass:function(t){const e=["tg-column-header"];return"tree"===t.formatter&&(e.push("tg-tree-header"),this.rowsInfo.isTree&&e.push("tg-tree-header-indent")),this.isColumnSortable(t)&&e.push(`tg-column-sortable tg-column-sort-${this.options.sortIndicator}`),t.align&&e.push(`tg-align-${t.align}`),e.join(" ")},getHeaderStyle:function(t){const e=[d.styleMap(t.headerStyleMap)],i=t.tg_width;return this.isInvisible(t)||i<=0?e.push("display:none;"):e.push(`width:${i}px;`),e.join("")}},J={renderHeader:function(){this.cssRulesInvalid=!0,this.$headerL.empty(),this.$headerR.empty(),this.resetCssDisplay(),this.renderHeaderTables(),this.renderHeaderSort(),this.headerCreated=!0,this.trigger(y.onHeaderUpdated,{node:this.$headerFrame.get(0)})},initHeaderLayerHeight:function(){this.updateScrollPaneHiddenState(),this.resetCssDisplay(),this.viewAllColumns.forEach((t=>{this.updateColumnHeaderHeight(t)})),this.resetCssDisplay("none"),this.updateHeaderLayerHeight()},updateHeaderLayerHeight:function(){const t={},e=this.columnsInfo.maxLevel;for(let i=0;i<=e;i++)t[i]=0;const i=[];this.viewAllColumns.forEach((function(e){if(e.tg_combination)i.push(e);else{const i=e.tg_height,o=e.tg_layer;t[o]=Math.max(t[o],i)}})),i.forEach((function(e){let i=e.tg_height;const o=e.tg_combination.split(""),n=o.pop();o.forEach((function(e){i-=t[e]||0})),t[n]=Math.max(t[n],i)}));const o=JSON.stringify(t);this.previousHeaderLayerHeight!==o&&(this.previousHeaderLayerHeight=o,this.headerLayerHeight=t,this.cssRulesInvalid=!0)}};var Q=i(915);const Z={create:function(t){this.id=d.uid(4,"tg-"),d.isObject(t)||(t={container:t}),this.constructorOptions=t,this.createCache(),this.createView(t.container)},createView:function(t){this.createHolder(t),this.$holder?(this.createGlobalStyle(),this.createContainer()):console.error("ERROR: Grid requires a container")},createHolder:function(t){const e=w(t);if(!e.length)return;this.$holder=e,this.$holder.empty(),this.holder=this.$holder.get(0);const i=this.holder.getRootNode();this.shadowRoot=null,i&&i.host&&(this.shadowRoot=i)},createGlobalStyle:function(){const t=this.shadowRoot||document.head;if(t.querySelector(`style[context="${e.ID}"]`))return;const i=document.createElement("style");i.setAttribute("context",e.ID),i.innerHTML=Q.A.toString(),t.appendChild(i)},createContainer:function(){return this.$container=w('
    \r\n\r\n
    \r\n\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n\r\n
    \r\n\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n\r\n
    \r\n\r\n
    \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n\r\n
    \r\n
    \r\n \r\n \r\n \r\n
    \r\n
    \r\n\r\n
    \r\n').appendTo(this.$holder),this.$container.attr("id",this.id),this.$container.addClass(`${e.NS} ${this.id}`),this.container=this.$container.get(0),d.setInstance(this.container,this),this.$headerFrame=this.$container.find(".tg-header-frame"),this.$paneHL=this.$headerFrame.find(".tg-pane-header-left"),this.$paneHR=this.$headerFrame.find(".tg-pane-header-right"),this.$headerL=this.$paneHL.find(".tg-header-left"),this.$headerR=this.$paneHR.find(".tg-header-right"),this.$header=w().add(this.$headerL).add(this.$headerR),this.$bodyFrame=this.$container.find(".tg-body-frame"),this.$paneTL=this.$bodyFrame.find(".tg-pane-top-left"),this.$paneTR=this.$bodyFrame.find(".tg-pane-top-right"),this.$paneBL=this.$bodyFrame.find(".tg-pane-bottom-left"),this.$paneBR=this.$bodyFrame.find(".tg-pane-bottom-right"),this.$bodyTL=this.$paneTL.find(".tg-body-top-left"),this.$bodyTR=this.$paneTR.find(".tg-body-top-right"),this.$bodyBL=this.$paneBL.find(".tg-body-bottom-left"),this.$bodyBR=this.$paneBR.find(".tg-body-bottom-right"),this.$body=w().add(this.$bodyTL).add(this.$bodyTR).add(this.$bodyBL).add(this.$bodyBR),this.$columnLineContainer=this.$container.find(".tg-column-line"),this.$columnLineItem=this.$columnLineContainer.find(".tg-column-line-item"),this.$columnLineItemL=this.$columnLineContainer.find(".tg-column-line-l"),this.$columnLineItemR=this.$columnLineContainer.find(".tg-column-line-r"),this}},tt={initColumnsHandler:function(){this.columns=this.data.columns,this.columns.forEach(((t,e)=>{t&&"object"==typeof t||(this.columns[e]={})}));const t=this.getPrivateColumns();this.columnsInfo=this.initTreeInfo(t,this.frozenInfo.column);const e=[],i=[],o=(t,n)=>{if(!d.isList(t))return;let s,r=0;t.forEach((t=>{if(!this.isInvisible(t))if(t.tg_group){if(this.isEmptyGroup(t))return;i.push(t),o(t.subs,t)}else t.tg_list_index=r,r+=1,t.tg_list_last=!1,s=t,e.push(t)})),s&&(s.tg_list_last=!0)};o(t),e.forEach((t=>{this.initColumnItemHandler(t)})),i.forEach((t=>{this.initColumnGroupHandler(t)}));const n=[].concat(e).concat(i);this.initViewList(n,((t,e)=>{})),this.viewColumns=e,this.viewGroupColumns=i,this.viewAllColumns=n,this.initHeaderHandler(t),this.initSortColumn()},getPrivateColumns:function(){const t=this.options;this.selectColumn=t.selectColumn,this.rowDragColumn=t.rowDragColumn,this.rowNumberColumn=t.rowNumberColumn,this.blankColumn=t.blankColumn;let e=[];const i=()=>{t.selectVisible&&e.push(this.selectColumn),t.rowDragVisible&&e.push(this.rowDragColumn),t.rowNumberVisible&&(this.rowNumberColumn.width=t.rowNumberWidth,e.push(this.rowNumberColumn))};if(this.frozenInfo.right){const t=this.frozenInfo.column;this.columns.forEach(((o,n)=>{e.push(o),n===t&&i()}))}else i(),e=e.concat(this.columns);return e.push(this.blankColumn),e},setColumns:function(t){this.data.columns=d.toList(t),this.rerender()},getColumns:function(){return this.columns},getViewColumns:function(t){return t?this.viewAllColumns:this.viewColumns},initColumnItemHandler:function(t){this.initColumnProps(t),this.initColumnFormatter(t),this.initColumnWidth(t)},initColumnGroupHandler:function(t){this.initColumnFormatterByName(t,"headerFormatter","header")},initColumnProps:function(t){const e=this.options.columnTypes;if(!d.hasOwn(t,"type")){const i=e[t.id];"string"==typeof i&&(t.type=i)}let i=this.options.columnProps;const o=e[t.type];o&&"object"==typeof o&&(i=d.merge(i,o));for(const e in i)d.hasOwn(t,e)||(t[e]=i[e])},initColumnFormatter:function(t){this.initColumnFormatterByName(t,"headerFormatter","header");let e=t.type;const i=t.formatter;"string"==typeof i&&(e=i),this.initColumnFormatterByName(t,"formatter",e)},initColumnFormatterByName:function(t,e,i){let o=t[e];"function"!=typeof o?(o=this.getFormatter(i),t[`tg_${e}`]=o||this.getFormatter("string")):t[`tg_${e}`]=o.bind(this)},initColumnWidth:function(t){if(t!==this.blankColumn)return d.isNum(t.width)&&t.width>=0?(t.tg_width=t.width,t.minWidth=Math.min(t.minWidth,t.tg_width),void(t.maxWidth=Math.max(t.maxWidth,t.tg_width))):void this.initColumnWidthByName(t);t.tg_width=0},initColumnWidthByName:function(t){const e=this.getComputedColumnWidth(t);d.isNum(e)&&(t.tg_width=e)},getComputedColumnWidth:function(t){const e=t.name||"",i=d.getCharLen(e);let o=Math.round(10*i);return o>103&&(o=Math.max(103,Math.round(10*i/2)),o>133&&(o=Math.max(133,Math.round(10*i/3)),o>163&&(o=Math.max(163,Math.round(10*i/4))))),d.clamp(o,t.minWidth,t.maxWidth)},initSortColumn:function(){this.sortColumn=null;const t=this.options,e=t.sortField;if(!e)return;const i=this.getColumnItemById(e);return i&&this.isColumnSortable(i)?(d.hasOwn(i,"sortAsc")||(i.sortAsc=t.sortAsc),this.sortColumn=i,this):void 0}},et={initHeaderHandler:function(t){this.initHeaderRowItem(),this.viewGroupColumns.reverse(),this.initGroupColumnsWidth(),this.initGroupColumnsLayer(t)},initHeaderRowItem:function(){this.headerRowItem={tg_index:-1,tg_view_index:-1},this.viewAllColumns.forEach((t=>{d.hasOwn(t,"id")&&(this.headerRowItem[t.id]=t.name)}))},initGroupColumnsWidth:function(){this.viewGroupColumns.forEach((t=>{let e=0;t.subs.forEach((t=>{this.isInvisible(t)||(e+=t.tg_width)})),t.tg_width=e}))},initGroupColumnsLayer:function(t){const e=this.columnsInfo.maxLevel;this.viewColumns.forEach((function(t){t.tg_layer=e,t.tg_parent&&(t.tg_parent.tg_layer=e-1)})),this.viewGroupColumns.forEach((function(t){const e=t.tg_layer,i=t.tg_parent;if(i){let t=e-1;d.isNum(i.tg_layer)&&(t=Math.min(t,i.tg_layer)),i.tg_layer=t}})),this.initColumnRowspanHandler(t,0)},initColumnRowspanHandler:function(t,e){t.forEach((t=>{const i=this.initColumnCombinationHandler(t,e);t.tg_group&&this.initColumnRowspanHandler(t.subs,e+i)}))},initColumnCombinationHandler:function(t,e){const i=[],o=t.tg_layer;for(;e<=o;)i.push(e),e+=1;i.reverse();const n=i.length;let s="";return n>1&&(s=i.join("")),t.tg_combination=s,n}},it={},ot={name:"",minWidth:81,maxWidth:300},nt=function(t){return null==t},st=function(t,e){const i=nt(t),o=nt(e);return i&&o?0:i?1:o?-1:void 0},rt=function(t,e){return t.tg_index>e.tg_index?1:-1},lt=function(t,e){return rt(t,e)},ht=function(t,e){if("string"==typeof t&&"string"==typeof e){const i=t.toUpperCase(),o=e.toUpperCase();if(i!==o)return i>o?-1:1}return t>e?-1:1},at=function(t,e,i,o){return t?-1:e?1:ht(i,o)},ct=function(t,e){const i="number"==typeof t,o="number"==typeof e;return i&&o?t>e?-1:1:at(i,o,t,e)},dt=function(t,e){const i=new Date(t),o=new Date(e),n=d.isDate(i),s=d.isDate(o);if(n&&s){const t=i.getTime(),e=o.getTime();if(t===e)return;return t>e?-1:1}return at(n,s,t,e)},ut=function(t,e){const i="boolean"==typeof t,o="boolean"==typeof e;return i&&o?t>e?-1:1:at(i,o,t,e)},gt=function(t,e,i,o){const n=t[i.sortField],s=e[i.sortField],r=st(n,s);if("number"==typeof r)return 0===r?lt(t,e):i.sortBlankFactor*r;if(n!==s&&"function"==typeof o){const t=o(n,s);if(d.isNum(t))return i.sortFactor*t}return lt(t,e)},ft={blankValue:st,equal:lt,index:rt,value:gt,diffType:at,string:function(t,e,i){return gt(t,e,i,ht)},stringValue:ht,number:function(t,e,i){return gt(t,e,i,ct)},numberValue:ct,date:function(t,e,i){return gt(t,e,i,dt)},dateValue:dt,boolean:function(t,e,i){return gt(t,e,i,ut)},booleanValue:ut};const pt={initOptionsHandler:function(){return this.options=this.generateOptions(),this.initOptionsFormatters(),this.initOptionsSort(),this.initOptionsFrozen(),this.initOptionsScrollbar(),this.initOptionsContainer(),this.initBindWindowResize(),this.initBindContainerResize(),this},generateOptions(){const t={className:e.NS,theme:e.ID,headerVisible:!0,rowHeight:32,rowFilter:null,rowFilteredSort:null,rowNotFound:"",rowMoveCrossLevel:!0,rowCacheLength:0,rowProps:it,columnTypes:{tree:{type:"tree",formatter:"tree",width:230,minWidth:120,maxWidth:810},number:{type:"number",align:"right"},date:{type:"date",align:"right"},name:"tree"},columnCacheLength:0,columnProps:ot,collapseAllOnInit:null,collapseAllVisible:!0,selectAllOnInit:null,selectVisible:!1,selectAllVisible:!0,selectMultiple:!0,selectColumn:{private:!0,id:"tg-column-select",name:"",formatter:"select",headerClassMap:"tg-header-select",classMap:"tg-cell-select",width:36,align:"center",resizable:!1,sortable:!1,exportable:!1},rowDragCrossLevel:!0,rowDragVisible:!1,rowDragColumn:{private:!0,id:"tg-column-row-drag",name:"",formatter:"rowDrag",headerClassMap:"tg-header-row-drag",classMap:"tg-cell-row-drag",align:"center",width:36,resizable:!1,sortable:!1,exportable:!1},rowNumberWidth:36,rowNumberFilter:null,rowNumberVisible:!1,rowNumberColumn:{private:!0,id:"tg-column-row-number",name:"",formatter:"rowNumber",headerClassMap:"tg-header-row-number",classMap:"tg-cell-row-number",align:"center",maxWidth:100,sortable:!1,exportable:!1},blankColumn:{private:!0,id:"tg-column-blank",name:"",formatter:"blank",headerClassMap:"tg-header-blank",classMap:"tg-cell-blank",width:0,minWidth:0,maxWidth:4096,resizable:!1,sortable:!1,exportable:!1},sortField:"",sortAsc:!0,sortBlankValueBottom:!0,sortComparers:ft,sortOnInit:!1,sortIndicator:"h",highlightKeywords:{textKey:"tg_text_",textGenerator:null,highlightKey:"tg_highlight_",highlightPre:"",highlightPost:""},frozenRow:-1,frozenRowMax:10,frozenRowHoverable:!1,frozenBottom:!1,frozenColumn:-1,frozenColumnMax:10,frozenRight:!1,scrollbarSize:12,scrollbarSizeH:null,scrollbarSizeV:null,scrollbarRound:!1,scrollbarFade:!1,scrollbarFadeTimeout:1e3,scrollbarType:"auto",scrollPaneMinWidth:30,scrollPaneGradient:30,autoHeight:!1,textSelectable:!1,bindWindowResize:!1,bindContainerResize:!1,cellResizeObserver:null},i=this.generateThemeOptions();return d.merge(t,i,this.constructorOptions,this.customOptions,this.dataOptions)},generateThemeOptions(){const t=this.pickOptions("theme").pop();if(t)return this.getThemeOptions(t)},pickOptions(t){return[this.constructorOptions,this.customOptions,this.dataOptions].map((e=>e&&e[t])).filter((t=>t))},initOptionsFormatters(){let t;const e=this.pickOptions("formatters");e.length&&(t=d.merge.apply(null,e)),this.formatters=d.merge(Y,t,this.customFormatters),this.nullFormatter=this.getFormatter("null")},initOptionsSort(){"v"!==this.options.sortIndicator&&(this.options.sortIndicator="h")},initOptionsFrozen:function(){const t=this.options;this.frozenInfo={column:-1,row:-1,columns:0,rows:0,bottom:Boolean(t.frozenBottom),right:Boolean(t.frozenRight)};let e=d.toNum(t.frozenColumn,!0);e=d.clamp(e,-1,t.frozenColumnMax),e>-1&&!this.frozenInfo.right&&(t.selectVisible&&(e+=1),t.rowDragVisible&&(e+=1),t.rowNumberVisible&&(e+=1)),this.frozenInfo.column=e,e>-1?this.frozenInfo.columns=e+1:(this.frozenInfo.columns=0,this.frozenInfo.right=!1);let i=d.toNum(t.frozenRow,!0);i=d.clamp(i,-1,t.frozenRowMax),this.frozenInfo.row=i,i>-1?this.frozenInfo.rows=i+1:(this.frozenInfo.rows=0,this.frozenInfo.bottom=!1)},initOptionsScrollbar:function(){const t=this.options;("auto"===t.scrollbarType&&d.isTouchDevice()||["touch","mobile"].includes(t.scrollbarType))&&(t.scrollbarFade=!0,t.scrollbarSize=6,t.scrollbarRound=!0);const e=d.toNum(t.scrollbarSize);this.scrollbarSizeH=e,d.isNum(t.scrollbarSizeH)&&(this.scrollbarSizeH=t.scrollbarSizeH),this.scrollbarSizeV=e,d.isNum(t.scrollbarSizeV)&&(this.scrollbarSizeV=t.scrollbarSizeV)},initOptionsContainer:function(){this.$container.attr("id",this.id);const t=this.options;this.$container.removeClass();const i=[e.NS,this.id,`tg-${t.theme}`,t.className];t.textSelectable||i.push("tg-text-unselectable"),d.isTouchDevice()&&i.push("tg-touch-device"),this.$container.addClass(d.classMap(i))},setTextSelectable:function(t){this.options.textSelectable&&(t?this.$container.removeClass("tg-text-unselectable"):this.$container.addClass("tg-text-unselectable"))}},mt={initBindWindowResize:function(){this.unbindWindowResize(),this.options.bindWindowResize&&(this.windowResizeEvents={resize:{handler:t=>{this.resize()}}},d.bindEvents(this.windowResizeEvents,window))},unbindWindowResize:function(){d.unbindEvents(this.windowResizeEvents)},createResizeObserver:function(t){if("undefined"==typeof ResizeObserver)return console.error("ERROR: This browser does not support ResizeObserver"),{observe:()=>{},unobserve:()=>{},disconnect:()=>{}};return new ResizeObserver((e=>{t.call(this,e)}))},initBindContainerResize:function(){this.unbindContainerResize(),this.options.bindContainerResize&&this.holder&&(this.resizeObserver=this.createResizeObserver((t=>{Boolean(this.holder.offsetWidth||this.holder.offsetHeight||this.holder.getClientRects().length)&&this.resize()})),this.resizeObserver.observe(this.holder))},unbindContainerResize:function(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null)}},bt={initRowsHandler:function(){this.rows=this.data.rows,this.rowsInfo=this.initTreeInfo(this.rows,this.frozenInfo.row)},getRows:function(){return this.rows},getViewRows:function(){return this.viewRows},createViewRows:function(){this.initRowFilterHandler();const t=[],e=this.getRowNumberFilter();let i=1;const o=(t,o)=>{if(e.call(this,t,o))return t.tg_row_number=i,void(i+=1);t.tg_row_number=""},n=(e,i,s)=>{if(!d.isList(e))return;let r,l=0;e.forEach((e=>{if(this.isInvisible(e))return;e.tg_list_index=l,l+=1,e.tg_list_last=!1,r=e,this.gridRowItemHandler(e),o(e,l),s||t.push(e);const i=s||e.tg_group&&e.collapsed;n(e.subs,e,i)})),r&&(r.tg_list_last=!0)};n(this.rows);let s,r=0;return this.initViewList(t,((t,e)=>{t.tg_top=r,r+=this.getRowHeight(t),t.tg_group_line=!1,t.collapsed&&(t.tg_group_line=!0),s&&(t.tg_group||t.tg_level{if(e.tg_invisible)return;const n=!t.call(this,e,i,o);if(e.tg_filtered=n,!n){let t=e;for(;t.tg_parent;)t.tg_parent.tg_filtered=!1,t=t.tg_parent}})),this.sortColumn)return;let e=this.options.rowFilteredSort;if("function"==typeof e&&(e=e.call(this)),!e)return;"string"==typeof e&&(e={sortField:e,sortAsc:this.options.sortAsc});const i=e.sortField||e.id;i&&this.sortRows(i,e)},highlightKeywordsFilter:function(t,e,i){const{textKey:o,textGenerator:n,highlightKey:s}=this.options.highlightKeywords;if(e.forEach((e=>{t[`${s}${e}`]=null})),!i)return!0;const r=`${i}`.trim().toLowerCase().split(/\s+/g).filter((t=>t));if(!r.length)return!0;let l=!1;const h=(e,i)=>(/<\/?[a-z][\s\S]*>/i.test(e)&&(e=((e,i)=>{const n=`${o}${i}`,s=t[n];if(s)return s;const r=document.createElement("div");r.innerHTML=e;const l=r.innerText;return t[n]=l,l})(e,i)),(t=>{const e=t.toLowerCase();let i=0;for(const t of r){const o=e.indexOf(t,i);if(-1===o)return;i=o+t.length}return!0})(e));let a=function(t,e){return t[e]};return"function"==typeof n&&(a=n),e.forEach((e=>{const i=a(t,e);if(null==i)return;const o=`${i}`.trim();if(!o)return;const n=h(o,e);n&&(t[`${s}${e}`]=n,l=!0,this.highlightKeywords=r)})),l},highlightKeywordsHandler:function(){const{highlightCells:t}=this.renderSettings;if(!t.length)return;const e=this.highlightKeywords;e&&(this.asyncHighlightKeywords||(this.asyncHighlightKeywords=d.debounce(this.highlightKeywordsSync,10)),this.asyncHighlightKeywords.apply(this,[t,e]))},highlightKeywordsSync:function(t,e){t.forEach((t=>{const i=Array.from(t.querySelectorAll("svg")).concat(Array.from(t.querySelectorAll("textarea"))),o=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,(t=>{if(i.length)for(const e of i)if(e.contains(t))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_ACCEPT})),n=[];let s=o.nextNode();for(;s;)n.push(s),s=o.nextNode();n.length&&this.highlightTextNodes(n,e)}))},highlightTextNodes:function(t,e){const{highlightPre:i,highlightPost:o}=this.options.highlightKeywords;let n=0;const s=()=>(n>=e.length&&(n=0),e[n++]);let r=s();t.forEach((t=>{const e=t.textContent,n=e.toLowerCase(),l=[];let h=0;const a=e.length;let c=!1;for(;h{if(e.selected){if(t)return void(e.selected=!1);t=e}}))}const t=this.options.selectAllOnInit;!0!==t?!1===t&&this.updateAllRowsSelected(!1):this.updateAllRowsSelected(!0)},updateAllRowsSelected:function(t){this.forEachSelectableRow((e=>{e.selected=t}))},initCollapseAllOnInitHandler:function(){const t=this.options.collapseAllOnInit;!0!==t?!1===t&&this.updateAllRowsCollapsed(!1):this.updateAllRowsCollapsed(!0)},getToBeAddedItemList:function(t){const e=[];return d.toList(t).forEach((t=>{t&&"object"==typeof t?e.push(t):void 0!==t&&e.push({name:t})})),e},getToBeAddedParentSubs:function(t,e){return t?(t.subs||(t.subs=[]),t.subs):e},getToBeAddedPositionIndex:function(t,e){const i=e.length;return d.isNum(t)&&t>=0&&t<=i?Math.round(t):i},generateDataSnapshot:function(t){if(!t||"object"!=typeof t)return t;const e=this.cleanTreeList(t.rows),i=this.cleanTreeList(t.columns);return this.convertNumberType(e,i),t.rows=e,t.columns=i,t},cleanTreeList:function(t){if(!d.isList(t))return[];const e=(t,i)=>{i.forEach((i=>{if(!i||"object"!=typeof i)return void t.push({});const o=this.getItemSnapshot(i),n=i.subs;Array.isArray(n)&&(o.subs=[],e(o.subs,n)),t.push(o)}))},i=[];return e(i,t),i},convertNumberType:function(t,e){const i=[];d.forEachTree(e,(function(t){"number"===t.type&&t.id&&i.push(t.id)})),i.length&&d.forEachTree(t,(function(t){i.forEach((function(e){t[e]=d.convertNum(t[e])}))}))}},vt={setDefaultLoading:function(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t)return;const i=t.style;e.size&&(i.width=e.size,i.height=e.size),e.color&&(i.color=e.color),e.size||e.color||t.removeAttribute("style"),e.fast?t.classList.add("tg-loading-fast"):t.classList.remove("tg-loading-fast")},getDefaultLoading:function(t){return this.setDefaultLoading(this.$defaultLoading,t),this.$defaultLoading},getLoadingHolder:function(){return this.$container?this.$container.find(".tg-loading"):w()},setLoading:function(t){if(!this.$container)return this;this.$defaultLoading||(this.$defaultLoading=this.$container.find(".tg-loading-default").get(0));const e=this.getLoadingHolder().get(0);return"function"==typeof t&&(t=t.call(this,e)),d.isObject(t)&&(t=this.getDefaultLoading(t)),t||(t=this.getDefaultLoading()),this.renderNodeContent(e,t),this},showLoading:function(){return this.getLoadingHolder().show(),this},hideLoading:function(){return this.getLoadingHolder().hide(),this}},Ht={showMask:function(t){if(!this.hasMask||t){const e=this.$container.find(".tg-mask"),i=e.get(0);if(t&&i){const e=d.styleMap(t);e&&(i.style.cssText=e)}e.show(),this.hasMask=!0}return this},hideMask:function(){return this.hasMask&&(this.$container.find(".tg-mask").hide(),this.hasMask=!1),this}},Ct={renderNodeContent:function(t,e){if(t){if(e&&e.nodeType)return this.emptyNode(t),void t.appendChild(e);if(Array.isArray(e))return this.emptyNode(t),void e.forEach((e=>{e&&e.nodeType&&t.appendChild(e)}));void 0===e&&(e=""),t.innerHTML=e}},emptyNode:function(t){if(t)for(;t.firstChild;)t.removeChild(t.firstChild)},removeNode:function(t){t&&t.parentNode&&t.parentNode.removeChild(t)},appendNode:function(t,e){t&&e&&t.appendChild(e)},createElement:function(t,e,i){const o=document.createElement(t);e&&Object.keys(e).forEach((function(t){const i=e[t];void 0!==i&&o.setAttribute(t,i)})),d.isArray(i)||(i=[i]);let n="";return i.forEach((function(t){t&&t.nodeType?o.appendChild(t):void 0!==t&&(n+=t)})),n&&(o.innerHTML=n),o},find:function(t,e){return w(e||this.$container).find(t)},getRowNodes:function(t){const e=this.getRowItem(t);if(e)return this.getRowNodesByIndex(e.tg_view_index)},getCellNode:function(t,e){const i=this.getRowItem(t);if(!i)return;const o=this.getColumnItem(e);return o?this.getCellNodeByIndex(i.tg_view_index,o.tg_view_index):void 0},getHeaderItemNode:function(t){const e=this.getColumnItem(t);if(e)return this.getHeaderCache(e.tg_view_index)},getColumnHeaderNode:function(t){const e=this.getHeaderItemNode(t);if(e)return e.querySelector(".tg-column-header")}},yt={render:function(){this.asyncRender||(this.asyncRender=d.microtask(this.renderSync)),this.asyncRender.apply(this,arguments)},renderSync:function(){this.renderStartedTimestamp=Date.now();const t=this.generateRenderSettings.apply(this,arguments);return this.renderSettings=t,"all"===t.type?(this.flushBody(),this.initHandler(),this.renderHeader(),this.updateViewRowsAndSize(),this.renderBody(),this):"columns"===t.type?(this.flushBody(),this.initColumnsHandler(),this.renderHeader(),this.updateViewRowsAndSize(),this.renderBody(),this):"rows"===t.type?(this.updateViewRowsAndSize(),this.renderBody(),this):"rows_cache"===t.type?(this.cssRulesInvalid=!0,this.updateViewRowsAndSize(),this.updateRowCacheTopAndHeight(),this.renderBody(),this):"resize"===t.type?(this.resizeHandler(),this.renderBody(),this):(this.renderBody(),this)},generateRenderSettings:function(t){const e={type:this.renderType,scrollLeft:null,scrollTop:null,scrollColumn:null,scrollRow:null,highlightCells:[]};return"string"==typeof t?e.type=t:t&&Object.assign(e,t),this.headerCreated||(e.type="all"),e},renderBody:function(){this.scrollOnInit(),this.scrollTopOffset=this.scrollPane.getScrollTopOffset();const t=this.getViewport();return this.viewport=t,this.flushWithViewport(),this.previousScrollTopOffset!==this.scrollTopOffset&&(this.previousScrollTopOffset=this.scrollTopOffset,this.updateRowCacheTopOffset()),this.renderRows(t.rows),this.renderCells(t.rows,t.columns),this.renderUpdatedTimestamp=Date.now(),this.renderDuration=this.renderUpdatedTimestamp-this.renderStartedTimestamp,this.trigger(y.onUpdated,t),this.firstUpdated||(this.firstUpdated=!0,this.trigger(y.onFirstUpdated,t)),this.layoutEventHandler(),this.resizeEventHandler(),this.highlightKeywordsHandler(),this.renderSettings=null,this.renderType=null,this},rerender:function(){return this.render("all"),this}},Rt={resize:function(){return this.asyncResize||(this.asyncResize=d.throttle(this.resizeSync,100)),this.asyncResize.apply(this,arguments),this},resizeSync:function(){return this.headerCreated?(this.resizeHolderHandler.apply(this,arguments),this.firstUpdated&&this.isHolderInvisible()||this.render("resize"),this):this},resizeHolderHandler(t,e){if(0!==arguments.length)return 1===arguments.length?t&&"object"==typeof t?void this.$holder.css(t):void this.$holder.css({width:t}):void this.$holder.css({width:t,height:e})},isHolderInvisible(){const t=this.$holder.width(),e=this.$holder.height();return!t||!e},resizeHandler:function(){this.containerWidth=this.$container.width(),this.containerHeight=this.$container.height(),this.headerWidth=this.containerWidth,this.bodyWidth=this.containerWidth,this.updateTotalColumnsWidth(),this.resizeHeaderHandler(),this.resizeBodyHandler()},layoutEventHandler:function(){const t=this.previousLayout||{},e={headerWidth:this.headerWidth,headerHeight:this.headerHeight,bodyWidth:this.bodyWidth,bodyHeight:this.bodyHeight,scrollbarWidth:this.getScrollbarWidth(),scrollbarHeight:this.getScrollbarHeight()};Object.values(e).join("")!==Object.values(t).join("")&&(this.previousLayout=e,this.trigger(y.onLayout,d.merge({previous:t},e)))},resizeEventHandler:function(){const t=this.previousSize||{},e={width:this.containerWidth,height:this.containerHeight};Object.values(e).join("")!==Object.values(t).join("")&&(this.previousSize=e,this.trigger(y.onResize,d.merge({previous:t},e)))},resizeHeaderHandler:function(){this.initHeaderLayerHeight();const t=this.options;t.autoHeight&&this.viewRows.length>5e3&&(t.autoHeight=!1),this.headerHeight=0,t.headerVisible&&(this.containerHeight>0||t.autoHeight)&&this.updateHeaderTableHeight(),this.$headerFrame.css({width:this.headerWidth,height:this.headerHeight})},updateHeaderTableHeight:function(){let t=0;Object.keys(this.headerLayerHeight).forEach((e=>{t+=this.headerLayerHeight[e]}));const e=this.$headerL.find(".tg-header-table"),i=this.$headerR.find(".tg-header-table");e.css({height:t}),i.css({height:t}),this.headerHeight=t},resizeBodyHandler:function(){this.updateScrollState(),this.bodyHeight=this.containerHeight-this.headerHeight,this.$bodyFrame.css({width:this.bodyWidth,height:this.bodyHeight}),this.updatePaneWidth(),this.updatePaneHeight(),this.updateCanvasWidth(),this.updateCanvasHeight(),this.updateScrollPane(),this.updateCssRules()},updatePaneWidth:function(){let t=this.bodyWidth,e=0;if(this.frozenInfo.columns){const i=this.getScrollbarWidth();this.frozenInfo.right?(e=this.columnsWidthR+i,t=this.bodyWidth-e):(t=this.columnsWidthL,e=this.bodyWidth-t),this.scrollPaneHidden&&(this.frozenInfo.right?(t<=0&&(t=0),e=Math.max(0,this.bodyWidth-t)):(e3&&void 0!==arguments[3])||arguments[3];const n=this.getToBeAddedItemList(t);if(!n.length)return!1;let s;if(null!=e&&(s=this.getRowItem(e),!s))return!1;const r=this.getToBeAddedParentSubs(s,this.rows),l=this.getToBeAddedPositionIndex(i,r),h=[l,0].concat(n);r.splice.apply(r,h),this.initRowsHandler(),s?(s.collapsed=!1,this.flushRowFrom(s.tg_view_index+l)):this.flushRowFrom(l),this.onNextUpdated((function(){this.trigger(y.onRowAdded,n)}));const a={type:"rows"};return o&&(a.scrollRow=n[n.length-1]),this.render(a),!0},deleteRow:function(t){const e=d.toList(t),i=[];if(e.forEach((t=>{const e=this.getRowItem(t);e&&i.push(e)})),!i.length)return!1;const o=this.removeRowsHandler(i);this.initRowsHandler();const n=this.getRemovedMinIndex(o);return this.flushRowFrom(n),this.onNextUpdated((function(){this.trigger(y.onRowRemoved,i)})),this.render("rows"),!0},getRemovedMinIndex:function(t){let e=0;const i=t[t.length-1];if(this.isInvisible(i))return e;e=i.tg_view_index,e>0&&(e-=1);let o=i.tg_parent;for(;o;)o.collapsed&&(e=o.tg_view_index),o=o.tg_parent;return e},removeRowsHandler:function(t){const e=[].concat(t);e.sort((function(t,e){return e.tg_index-t.tg_index}));const i=[];return e.forEach((t=>{this.getRowParentSubs(t).splice(t.tg_sub_index,1),i.push(t)})),i}},Tt={renderCollapseAllState:function(){this.hasTreeColumn&&(this.asyncRenderCollapseAllState||(this.asyncRenderCollapseAllState=d.microtask(this.renderCollapseAllStateSync)),this.asyncRenderCollapseAllState.apply(this,arguments))},renderCollapseAllStateSync:function(){const t=this.$header.find(".tg-tree-header");this.rowsInfo.isTree?t.addClass("tg-tree-header-indent"):t.removeClass("tg-tree-header-indent"),this.renderCollapseAllIcon()},checkCollapseAllState:function(t){if(t!==this.allRowsCollapsed){if(t){let t=0;const e=this.rows.length;for(;t{if(e.tg_group&&e.tg_subs_length&&e.collapsed)return t=!0,!1})),t)return}this.allRowsCollapsed=t,this.renderCollapseAllIcon()}},expandAllRows:function(){return this.renderAllRowsCollapsed(!1)},collapseAllRows:function(){return this.renderAllRowsCollapsed(!0)},toggleAllRows:function(){return this.allRowsCollapsed?this.expandAllRows():this.collapseAllRows()},renderAllRowsCollapsed:function(t){const e=this.updateAllRowsCollapsed(t);return e.length?(this.flushBody(),this.onNextUpdated((()=>{this.renderCollapseAllIcon(),t?this.trigger(y.onRowCollapsed,e):this.trigger(y.onRowExpanded,e)})),this.render("rows"),this):this},updateAllRowsCollapsed:function(t){this.allRowsCollapsed=t;const e=[];return this.forEachRow((i=>{i.subs&&i.tg_subs_length&&this.isCollapsedChanged(i,t)&&(i.collapsed=t,e.push(i))})),e},expandRow:function(t){const e=this.getRowItem(t);return e?this.isEmptyGroup(e)?(this.trigger(y.onRowSubsRequest,e),this):this.isCollapsedChanged(e,!1)?(e.collapsed=!1,this.flushRowFrom(e.tg_view_index),this.renderCollapseIcon(e),this.onNextUpdated((()=>{this.checkCollapseAllState(!1),this.trigger(y.onRowExpanded,e)})),this.render("rows"),this):this:this},collapseRow:function(t){const e=this.getRowItem(t);return e&&e.subs&&e.tg_subs_length&&this.isCollapsedChanged(e,!0)?(e.collapsed=!0,this.flushRowFrom(e.tg_view_index),this.renderCollapseIcon(e),this.onNextUpdated((()=>{this.checkCollapseAllState(!0),this.trigger(y.onRowCollapsed,e)})),this.render("rows"),this):this},toggleRow:function(t){const e=this.getRowItem(t);return e?(e.collapsed?this.expandRow(e):this.collapseRow(e),this):this},expandRowLevel:function(t){t=d.toNum(t,!0);const e=[],i=[];return this.forEachRow((o=>{o.subs&&o.tg_subs_length&&(o.tg_level<=t?this.isCollapsedChanged(o,!1)&&(o.collapsed=!1,i.push(o)):this.isCollapsedChanged(o,!0)&&(o.collapsed=!0,e.push(o)))})),e.length||i.length?(this.flushBody(),this.onNextUpdated((()=>{e.length&&this.trigger(y.onRowCollapsed,e),i.length&&this.trigger(y.onRowExpanded,i)})),this.render("rows"),this):this},renderCollapseAllIcon:function(){if(!this.options.collapseAllVisible||!this.hasTreeColumn)return;const t=this.$header.find(".tg-tree-icon-all");this.renderTreeIcon(t,this.allRowsCollapsed)},renderCollapseIcon:function(t){if(!this.headerCreated)return;const e=this.getRowNodesByIndex(t.tg_view_index);if(!e)return;const i=e.find(".tg-tree-icon");this.renderTreeIcon(i,t.collapsed)},renderTreeIcon:function(t,e){t&&(e?t.removeClass("tg-tree-icon-expanded").addClass("tg-tree-icon-collapsed"):t.removeClass("tg-tree-icon-collapsed").addClass("tg-tree-icon-expanded"))}},Et={rowDragStartHandler:function(t,e){this.removeSortColumn();const i=e.rowItem;if(!i)return;const o=this.getRowNodesByIndex(i.tg_view_index);if(!o)return;e.dragCloneNodes=this.getRowDragCloneNodes(o),e.dropPlaceholder=this.getRowDropPlaceholder(o),e.dragStartTop=this.getRowTop(i),e.dragRowHeight=this.getRowHeight(i),e.dragStartScrollTop=this.scrollTop,e.dragMaxScrollTop=this.scrollPane.getMaxScrollTop();const n={e:t,rowItem:i};this.trigger(y.onRowDragged,n),this.isDefaultPrevented(n)||("touch"===e.type&&d.preventDefault(e.e),this.setRowState(i,"dragging"),this.setTextSelectable(!1),this.rowDropListHandler(e),this.updateDragCloneRowPosition(e))},rowDragMoveHandler:function(t,e){"touch"===e.type&&d.preventDefault(e.e),this.updateDragCloneRowPosition(e),this.updateDragPlaceholderPosition(e),this.rowDragAutoScrollHandler(e)},rowDragEndHandler:function(t,e){"touch"===e.type&&(this.protectedItem=null,d.preventDefault(e.e)),this.autoScrollStop(),this.setRowState(e.rowItem,"dragging",!1),this.setTextSelectable(!0),e.dragCloneNodes&&(e.dragCloneNodes.remove(),e.dragCloneNodes=null),e.dropPlaceholder&&(e.dropPlaceholder.remove(),e.dropPlaceholder=null),e.changed&&this.rowDropHandler(e)},updateDragCloneRowPosition:function(t){const e=this.scrollTop-t.dragStartScrollTop,i=t.dragStartTop+t.offsetY+e,o=i-this.scrollTopOffset;t.dragCloneNodes&&t.dragCloneNodes.css("top",o).show(),t.dragCurrentPosition=i+.5*t.dragRowHeight},getRowDragCloneNodes:function(t){const e=w();return t.each((function(t){const i=w(t),o=i.clone();o.appendTo(i.parent()),e.add(o)})),e.addClass("tg-clone").hide(),e},getRowDropPlaceholder:function(t){const e=w();return t.each((function(t){const i=w(t),o=w("
    ").addClass("tg-row-placeholder").hide(),n=i.parent();n.find(".tg-row-placeholder").remove(),o.appendTo(n),e.add(o)})),e},updateDragPlaceholderPosition:function(t){this.rowDropItemHandler(t);const e=t.dropItem;if(!e)return;let i=t.dropPosition-1;t.dropBottom?e.tg_view_last&&(i=t.dropPosition-2):e.tg_view_index-this.frozenInfo.rows==0&&(i=t.dropPosition);const o=i-this.scrollTopOffset;t.dropPlaceholder&&t.dropPlaceholder.css("top",o).show()},rowDragAutoScrollHandler:function(t){const e=t.dragCurrentPosition,i=this.scrollTop,o=this.bodyHeight-this.frozenRowsHeight,n=i+o,s=this.options.rowHeight,r=Math.min(3*s,.5*o);if(!(rn-r){const i=e-(n-r),o=this.getAutoScrollOffset(i,r);this.autoScrollStart(o,t)}else this.autoScrollStop()},getAutoScrollOffset:function(t,e){return Math.floor(t/e*20)},autoScrollStop:function(){this.autoScrollMotion&&(this.autoScrollMotion.destroy(),this.autoScrollMotion=null)},autoScrollStart:function(t,e){this.autoScrollStop();const i=e.dragMaxScrollTop;this.autoScrollMotion=new B,this.autoScrollMotion.bind(B.EVENT.MOTION_MOVE,(()=>{const o=d.clamp(this.scrollTop+t,0,i);o!==this.scrollTop?(this.setScrollTop(o),this.updateDragCloneRowPosition(e),this.updateDragPlaceholderPosition(e)):this.autoScrollStop()})),this.autoScrollMotion.once(B.EVENT.MOTION_END,(()=>{this.autoScrollStart(t,e)})),this.autoScrollMotion.start({duration:200})},rowDropListHandler:function(t){const e=this.getRowDropList(t);if(!d.isList(e))return;const i=t.rowItem,o=e.filter((t=>{if(t===i)return!1;if(t.tg_frozen)return!1;let e=t.tg_parent;for(;e;){if(e===i)return!1;e=e.tg_parent}return!0}));if(!d.isList(o))return;const n=[];o.forEach((t=>{const e=this.getRowTop(t),i=this.getRowHeight(t);n.push({rowItem:t,position:e}),n.push({rowItem:t,position:e+i-1,dropBottom:!0})})),t.dropList=n},getRowDropList:function(t){const e=this.options.rowDragCrossLevel;return e?"function"==typeof e?e.call(this,t):this.viewRows:this.getRowParentSubs(t.rowItem)},rowDropItemHandler:function(t){const e=t.dropList;if(!e)return;const i=t.dragCurrentPosition;let o=Number.MAX_VALUE;for(let n=0,s=e.length;no)break;o=r,t.dropItem=s.rowItem,t.dropBottom=s.dropBottom,t.dropPosition=s.position}},rowDragDropPositionHandler:function(t,e,i){const o=this.getRowParentSubs(t),n=t.tg_sub_index;let s,r;return this.isDropIntoGroupFirstChild(e,i)?(s=e.subs,r=0):(s=this.getRowParentSubs(e),r=e.tg_sub_index,o===s&&n{this.trigger(y.onRowDropped,n)})),this.render({type:"rows",scrollRow:i})}},It={getMoveFocusRow:function(t,e){let i=t[0];return e>0&&(i=t[t.length-1]),i},getMoveLengthInList:function(t,e){let i=0;return t.forEach((t=>{this.getRowParentSubs(t)===e&&(i+=1)})),i},getMoveInfo:function(t,e,i){const o=this.getRowParentSubs(i);let n=i.tg_sub_index+e;const s=i.tg_parent;if(s&&this.options.rowMoveCrossLevel){const e=0,i=s.tg_subs_length-1;if(ni){const e=n-i;return this.getMoveInfo(t,e,s)}}if(e>0){n-=this.getMoveLengthInList(t,o)-1}return n=d.clamp(n,0,o.length),{list:o,index:n}},moveRowsHandler:function(t,e){(t=this.removeRowsHandler(t)).reverse();const i=this.getMoveFocusRow(t,e),o=this.getMoveInfo(t,e,i),n=[o.index,0].concat(t);return o.list.splice.apply(o.list,n),this.initRowsHandler(),this.onNextUpdated((function(){this.scrollRowIntoView(i),this.trigger(y.onRowMoved,t)})),this.removeSortColumn(),this.update(),!0},moveRows:function(t,e){t=d.toList(t);const i=[];return t.forEach((t=>{const e=this.getRowItem(t);e&&i.push(e)})),!!i.length&&(!(i.length>=this.getRowsLength())&&(0!==(e=d.toNum(e,!0))&&this.moveRowsHandler(i,e)))},moveRowsUp:function(t){return this.moveRows(t,-1)},moveRowsDown:function(t){return this.moveRows(t,1)},moveRowsToTop:function(t){return this.moveRows(t,-this.getRowsLength(!0))},moveRowsToBottom:function(t){return this.moveRows(t,this.getRowsLength(!0))},moveSelectedRowsUp:function(){return this.moveRows(this.getSelectedRows(),-1)},moveSelectedRowsDown:function(){return this.moveRows(this.getSelectedRows(),1)},moveSelectedRowsToTop:function(){return this.moveRows(this.getSelectedRows(),-this.getRowsLength(!0))},moveSelectedRowsToBottom:function(){return this.moveRows(this.getSelectedRows(),this.getRowsLength(!0))}},Lt={getSelectedRow:function(){let t=null;return this.forEachSelectableRow((function(e){if(e.selected)return t=e,!1})),t},getSelectedRows:function(){const t=[];return this.forEachSelectableRow((function(e){e.selected&&t.push(e)})),t.length>1&&t.sort((function(t,e){const i=t.tg_selected_index,o=e.tg_selected_index;return i>o?1:i0&&void 0!==arguments[0])||arguments[0];if(t=Boolean(t),this.globalSelectedIndex=0,t&&!this.options.selectMultiple)return this;const e=this.getAllSelectedChangedList(t);return e.length?(this.updateRowsSelectedState(e),this):this},setRowSelected:function(){return(this.options.selectMultiple?this.setRowMultipleSelected:this.setRowSingleSelected).apply(this,arguments)},setRowSingleSelected:function(t){const e=this.getRowItem(t);if(!e)return this;if(!this.isRowSelectable(e))return this;if(e.selected)return this;const i=[],o=this.getSelectedRow();return o&&o.selected&&i.push(o),e.selected||i.push(e),i.length?(this.updateRowsSelectedState(i),this):this},setRowMultipleSelected:function(t,e){if(0===arguments.length)return this;if(1===arguments.length&&!1===arguments[0])return this.selectAll(!1);const i=this.toRowItemList(t,(t=>this.isRowSelectable(t)));return i.length?!1===e?(this.setRowListUnselected(i),this):d.hasShiftKey(e)&&1===i.length?(this.setRowBetweenListSelected(i[0]),this):(this.updateRowsSelectedState(i),this):this},setRowListUnselected:function(t){const e=this.getSelectedChangedList(t,!1);e.length&&this.updateRowsSelectedState(e)},setRowBetweenListSelected:function(t){const e=this.previousSelectedRow;if(e&&e!==t){const i=this.getBetweenSelectedChangedList(e,t);if(!i.length)return;this.updateRowsSelectedState(i,!0)}else this.updateRowsSelectedState([t])},getAllSelectedChangedList:function(t){const e=[];return this.forEachSelectableRow((i=>{this.isSelectedChanged(i,t)&&e.push(i)})),e},getSelectedChangedList:function(t,e){const i=[];return t.forEach((t=>{this.isSelectedChanged(t,e)&&i.push(t)})),i},getBetweenSelectedChangedList:function(t,e){const i=t.tg_index,o=e.tg_index,n=[];if(i=o;)n.push(t),t--}return this.toRowItemList(n,(t=>this.isRowSelectable(t)&&!t.selected))},updateRowsSelectedState:function(t,e){let i;t.forEach((t=>{const e=!t.selected;t.selected=e,e&&(t.tg_selected_index=this.globalSelectedIndex++,i=t),this.renderRowSelectedState(t)})),e||(this.previousSelectedRow=i),this.renderSelectAllState(),this.onNextUpdated((()=>{this.trigger(y.onSelectChanged,t)})),this.render()},renderRowSelectedState:function(t){const e=t.tg_view_index;this.viewport.rows.includes(e)&&(this.renderRowState(t,"selected"),this.flushCell(e,this.selectColumn.tg_view_index))},renderSelectAllState:function(){this.isSelectAllVisible()&&(this.asyncRenderSelectAllState||(this.asyncRenderSelectAllState=d.microtask(this.renderSelectAllStateSync)),this.asyncRenderSelectAllState.apply(this,arguments))},renderSelectAllStateSync:function(){const t=this.getSelectAllState();if(t===this.previousSelectAllState)return;this.previousSelectAllState=t;const e=this.selectColumn,i=w(this.getColumnHeaderNode(e)).find(".tg-select-icon-all");i.length&&(i.removeClass("tg-selected tg-mixed"),t&&i.addClass(`tg-${t}`))},getSelectAllState:function(){let t=0;this.forEachSelectableRow((e=>{t+=1}));const e=this.getSelectedRows().length;let i="mixed";return 0===e?(i="",this.previousSelectedRow=null):e===t&&(i="selected"),i},isSelectAllVisible:function(){const t=this.options;return!!(t.selectVisible&&t.selectAllVisible&&t.selectMultiple)}},xt={setRowHover:function(t,e){const i=this.getRowItem(t);return i?(this.renderRowHover(i,e),this):this},renderRowHover:function(t,e){if(this.previousHover&&(this.previousHover.removeClass("tg-hover"),this.previousHover=null),!e)return this;if(!1===this.rowHoverable)return;if(!1===t.hoverable)return this;if(t.tg_frozen&&!this.options.frozenRowHoverable)return this;const i=t.tg_view_index;return this.previousHover=this.$body.find(`.tg-row[row='${i}']`).addClass("tg-hover"),this},setRowState:function(t,e){let i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];const o=this.getRowItem(t);return o?(o.tg_state_names||(o.tg_state_names=new Set),o.tg_state_names.add(e),o[e]=i,this.renderRowState(o,e),this):this},renderRowState:function(t,e){const i=this.getRowNodesByIndex(t.tg_view_index);if(i){const o=`tg-${e}`;t[e]?i.addClass(o):i.removeClass(o)}}},zt={getRowItem:function(t){return d.isNum(t)?(t<0&&(t=this.rowsInfo.length+t),this.rowsInfo.indexCache[t]):t?d.isNum(t.tg_index)?t:this.getRowItemById(t.id||t):void 0},getRowItemById:function(t){return this.getRowItemBy("id",t)},getRowItemBy:function(t,e){if(void 0!==e)return this.rowsInfo.indexCache.find((i=>i[t]===e))},getRowsLength:function(t){return t?this.rowsInfo.length:this.viewRows.length},getViewRowItem:function(t){return this.viewRows[t]},getPreRenderRowInfo:function(t){const e={rows:[],rowNotFound:!1,benchmark:0};if(!t.length)return 0===this.getRowsLength()&&(e.rowNotFound=!0),e;const i=[],o=this.frozenInfo.row;return t.forEach((t=>{this.getRowCache(t)?t>o&&i.push(t):e.rows.push(t)})),i.length&&(e.benchmark=Math.min.apply(Math,i)),e.rows.sort((function(t,i){return t{this.renderRowNodes(t,e.benchmark)}))},createRowNode:function(t,e,i,o,n,s){const r=document.createElement("div");return r.setAttribute("row",t),r.className=i,o&&(r.style.cssText=o),r.style.top=`${n}px`,s!==this.options.rowHeight&&(r.style.height=`${s}px`,r.style.lineHeight=`${s}px`),this.setNodeDataCache(r,{row:t,rowItem:e,rowNode:r}),r},appendRowNode:function(t,e,i,o){ithis.frozenInfo.row))return e;e-=this.frozenRowsHeight}return e-=this.scrollTopOffset,e},getRowTop:function(t){let e=t.tg_top;return t.tg_frozen||(e-=this.frozenRowsHeight),e},getRowVPos:function(t){const e=this.frozenInfo.bottom,i=this.frozenInfo.row;let o="top";return this.frozenInfo.rows&&(t<=i?e&&(o="bottom"):e||(o="bottom")),o},getRowCanvas:function(t,e){return"top"===t?"left"===e?this.$bodyTL:this.$bodyTR:"left"===e?this.$bodyBL:this.$bodyBR}},Mt={CHANGE:"change",START:"start",END:"end"},Pt={h:{type:"h",className:"tg-scrollbar-h",offset:"left",size:"width",page:"pageX",axis:"x",offsetName:"offsetX"},v:{type:"v",className:"tg-scrollbar-v",offset:"top",size:"height",page:"pageY",axis:"y",offsetName:"offsetY"}};class Nt extends k{static EVENT=Mt;static H="h";static V="v";type="h";settings={};size=0;viewSize=0;bodySize=0;trackSize=0;position=0;scale=0;thumbPosition=0;thumbScale=0;constructor(t,e){super(),this.settings=Pt[t]||Pt.h,this.type=this.settings.type,this.id=d.uid(4,`tg-scrollbar-${this.type}-`),this.$holder=w(e),this.$holder.find(`.${this.settings.className}`).remove(),this.options=this.generateOptions()}generateOptions(t){return d.merge({size:15,round:!1,blank:!1,motionDuration:200},t)}updateOptions(t){this.options=this.generateOptions(t);let e=this.options.size;d.isNum(e)||(e=d.toNum(e)),e=Math.round(e),e=Math.max(e,0),e=Math.min(e,30),this.size=e}create(){this.$container=w('
    ').appendTo(this.$holder),this.$container.attr("id",this.id),this.$container.addClass(d.classMap(["tg-scrollbar",this.settings.className,{"tg-scrollbar-round":this.options.round}])),this.$track=this.$container.find(".tg-scrollbar-track"),this.$thumb=this.$container.find(".tg-scrollbar-thumb"),this.thumbDrag=new O,this.thumbDrag.bind(O.EVENT.DRAG_START,((t,e)=>{this.thumbDragStart(e)})).bind(O.EVENT.DRAG_MOVE,((t,e)=>{this.thumbDragMove(e)})).bind(O.EVENT.DRAG_END,((t,e)=>{this.thumbDragEnd(e)}));const t=this.$container.get(0);return this.scrollEvents={mousedown:{handler:e=>{e.target.classList.contains("tg-scrollbar-thumb")?this.thumbMouseDownHandler(e):(this.trackEvents={mouseup:{handler:t=>{this.trackMouseupHandler(t)},options:{once:!0}}},d.bindEvents(this.trackEvents,t),this.trackMousedownHandler(e))},options:!0},selectstart:{handler:t=>{d.preventDefault(t)},options:!0}},d.bindEvents(this.scrollEvents,t),this}getBlank(){return this.options.blank}getSize(){return this.size}getViewSize(){return this.viewSize}getBodySize(){return this.bodySize}getTrackMouseDirection(){let t=1;return this.trackMousePosition0){const i=this.getMaxThumbPosition();t=Math.round(i*this.position/e),t=d.clamp(t,0,i)}return this.setThumbPosition(t),this}trackMousedownHandler(t){return this.motionStop(),this.trackMousePosition=this.getTrackMousePos(t),this.motionStart(),this}trackMouseupHandler(t){return d.unbindEvents(this.trackEvents),this.motionStop(),this.motionStarted||(this.trackMousePosition=this.getTrackMousePos(t),this.trackScrollHandler(),this.triggerEvent()),this}trackScrollHandler(){const t=Math.max(0,this.viewSize-20)*this.getTrackMouseDirection();return this.setOffset(t),this}motionStop(){return this.motion&&(this.motion.destroy(),this.motion=null),this}motionStart(){const t=this.position,e=Math.round(this.trackMousePosition/this.viewSize*this.getMaxPosition());return this.motionStarted=!1,this.motion=new B,this.motion.bind(B.EVENT.MOTION_START,((t,e)=>{this.motionStarted=!0})),this.motion.bind(B.EVENT.MOTION_MOVE,((t,e)=>{this.motionUpdateHandler(t,e)})),this.motion.start({duration:this.options.motionDuration,from:t,till:e}),this}motionUpdateHandler(t,e){e!==this.position&&(this.setPosition(e),this.triggerEvent())}thumbMouseDownHandler(t){this.$thumb.addClass("tg-scrollbar-thumb-hold"),this.thumbDrag.start(t,{target:this.$thumb})}thumbDragStart(t){this.motionStop(),t.thumbPositionStart=this.thumbPosition,this.trigger(Mt.START)}thumbDragMove(t){let e=t.thumbPositionStart+t[this.settings.offsetName];const i=this.getMaxThumbPosition();e=d.clamp(e,0,i),this.setThumbPosition(e);let o=0;i>0&&(o=d.per(e/i)*this.getMaxPosition(),o=Math.round(o)),this.position=o,this.triggerEvent()}thumbDragEnd(t){this.$thumb&&this.$thumb.removeClass("tg-scrollbar-thumb-hold"),this.trigger(Mt.END)}triggerEvent(){this.trigger(Mt.CHANGE,this.position)}getPosition(){return this.position}setPosition(t){t=d.toNum(t,!0);const e=this.getMaxPosition();t=d.clamp(t,0,e),this.position=t,this.updateThumbPosition()}getMaxPosition(){return this.bodySize-this.viewSize}updatePosition(){const t=this.getMaxPosition(),e=d.clamp(this.position,0,t);this.position=e}setOffset(t){t=d.toNum(t);const e=this.position+t;return this.setPosition(e),this}getScale(){return this.scale}setScale(t){return t=d.per(t),this.scale=t,this.scaleChangeHandler(),this}scaleChangeHandler(){let t=Math.round(this.viewSize*this.scale);if(t=Math.max(t,Math.round(1.5*this.options.size)),t=Math.min(t,this.viewSize-1),this.thumbSize=t,this.$thumb){const t={};"h"===this.type?(t.height=this.size,t.width=this.thumbSize):(t.width=this.size,t.height=this.thumbSize),this.$thumb.css(t)}}updateTrackSize(){const t={};return"h"===this.type?(t.width=this.trackSize,t.height=this.size):(t.height=this.trackSize,t.width=this.size),this.$container.css(t),this}updateThumbSize(){let t=0;return this.bodySize&&(t=this.trackSize/this.bodySize),this.setScale(t),this}parseSize(t){return t=d.toNum(t),t=Math.round(t),t=Math.max(t,0)}updateSize(t,e,i){t=this.parseSize(t),this.viewSize=t,e=this.parseSize(e),this.bodySize=e,i=d.isNum(i)?this.parseSize(i):t,this.trackSize=i,this.previousFadeIn=null}fade(t){return!(!this.$container||!this.size)&&(this.previousFadeIn!==t&&(this.previousFadeIn=t,t?this.$container.hasClass("tg-fade-out")&&this.$container.removeClass("tg-fade-out").addClass("tg-fade-in"):this.$container.removeClass("tg-fade-in").addClass("tg-fade-out"),!0))}show(){if(this.updatePosition(),!this.getBlank())return!this.$container&&this.size>0&&this.create(),this.$container?(this.updateTrackSize(),this.updateThumbSize(),this):this;this.remove()}hide(){return this.updatePosition(),this.remove(),this}remove(){if(this.motionStop(),d.unbindEvents(this.scrollEvents),d.unbindEvents(this.trackEvents),this.thumbDrag&&(this.thumbDrag.destroy(),this.thumbDrag=null),!this.$container)return this;this.$thumb=null,this.$track=null,this.$container.remove(),this.$container=null}destroy(){return this.remove(),this}}const _t={CHANGE:"change",START:"start",END:"end"};class kt extends k{static EVENT=_t;visible=!0;constructor(t,e){super(),this.id=d.uid(4,`tg-scroll-pane-${e}-`),this.gradientInfo=[],this.$container=w(t).attr("id",this.id),this.$container.addClass("tg-scroll-pane"),this.$scrollView=this.$container.find(".tg-scroll-view"),this.$scrollBody=this.$scrollView.find(".tg-scroll-body"),this.scrollbarH=new Nt(Nt.H,this.$container),this.scrollbarH.bind(Nt.EVENT.CHANGE,((t,e)=>{this.scrollHChangeHandler()})).bind(Nt.EVENT.START,(t=>{this.scrollStartEndHandler(!0)})).bind(Nt.EVENT.END,(t=>{this.scrollStartEndHandler()})),this.scrollbarV=new Nt(Nt.V,this.$container),this.scrollbarV.bind(Nt.EVENT.CHANGE,((t,e)=>{this.scrollVChangeHandler()})).bind(Nt.EVENT.START,(t=>{this.scrollStartEndHandler(!0)})).bind(Nt.EVENT.END,(t=>{this.scrollStartEndHandler()})),this.options=this.generateOptions()}generateOptions(t){return d.merge({scrollbarH:{},scrollbarV:{},scrollbarFade:!1,scrollSizeOnKeyPress:20,gradient:30},t)}scrollStartEndHandler(t){t?this.trigger(_t.START):this.trigger(_t.END)}show(){return this.$container.show(),this.visible=!0,this}hide(){return this.$container.hide(),this.visible=!1,this}width(){return this.scrollPaneW}height(){return this.scrollPaneH}render(t){return this.visible?(this.options=this.generateOptions(t),this.update(),this):this}update(){this.scrollPaneW=this.options.scrollPaneW,this.scrollPaneH=this.options.scrollPaneH,this.scrollBodyW=this.options.scrollBodyW,this.scrollBodyH=this.options.scrollBodyH,this.updateScrollbar()}setGroupH(t){this.groupH=d.toList(t)}setGroupV(t){this.groupV=d.toList(t)}updateGroupH(){if(!d.isList(this.groupH))return this;const t=this.scrollbarH.getPosition();return this.groupH.forEach((function(e){e&&e.updateScrollHFromGroup(t)})),this}updateGroupV(){if(!d.isList(this.groupV))return this;const t=this.scrollbarV.getPosition();return this.groupV.forEach((function(e){e&&e.updateScrollVFromGroup(t)})),this}updateGroupList(){this.updateGroupH(),this.updateGroupV()}updateScrollHFromGroup(t){this.scrollbarH.getPosition()!==t&&(this.scrollbarH.setPosition(t),this.updateScrollLeft(),this.triggerEvent())}updateScrollVFromGroup(t){this.scrollbarV.getPosition()!==t&&(this.scrollbarV.setPosition(t),this.updateScrollTop(),this.triggerEvent())}setPosition(t,e){return this.scrollbarH.setPosition(t),this.scrollbarV.setPosition(e),this.updateScrollLeft(),this.updateScrollTop(),this.updateGroupList(),this}updateScrollbar(){this.scrollbarH.updateOptions(this.options.scrollbarH),this.scrollbarV.updateOptions(this.options.scrollbarV),this.updateScrollState(),this.updateScrollView(),this.updateScrollTrack(),this.scrollbarH.updateSize(this.scrollViewW,this.scrollBodyW,this.scrollTrackW),this.scrollbarV.updateSize(this.scrollViewH,this.scrollBodyH,this.scrollTrackH),this.hasScrollH?(this.scrollbarH.show(),this.scrollbarH.setPosition(this.scrollbarH.getPosition())):this.scrollbarH.hide(),this.hasScrollV?(this.scrollbarV.show(),this.scrollbarV.setPosition(this.scrollbarV.getPosition())):this.scrollbarV.hide(),this.updateScrollLeft(),this.updateScrollTop(),this.updateGroupList()}updateScrollState(){const t=this.scrollbarH.getSize(),e=this.scrollbarV.getSize(),i=this.scrollbarH.getBlank(),o=this.scrollbarV.getBlank(),n=this.options.scrollbarFade;let s=!1,r=0;(function(){(this.scrollPaneWe&&t.push("left"),ie&&t.push("top"),o{const i=`tg-gradient-${e}`;t.includes(e)?this.$container.addClass(i):this.$container.removeClass(i)})))}getScrollLeft(){return this.scrollbarH.getPosition()}getScrollTop(){return this.scrollbarV.getPosition()}getMaxScrollLeft(){return this.scrollbarH.getMaxPosition()}getMaxScrollTop(){return this.scrollbarV.getMaxPosition()}getScrollTopOffset(){const t=this.getScrollTop();return t-t%1e4}triggerEvent(){this.trigger(_t.CHANGE,{scrollLeft:this.getScrollLeft(),scrollTop:this.getScrollTop()})}scrollHChangeHandler(){this.updateScrollLeft(),this.updateGroupList(),this.triggerEvent()}scrollVChangeHandler(){this.updateScrollTop(),this.updateGroupList(),this.triggerEvent()}setOffsetH(t){const e=this.getScrollLeft();this.scrollbarH.setOffset(t);return this.getScrollLeft()!==e&&(this.updateScrollLeft(),this.updateGroupList(),this.triggerEvent(),!0)}setOffsetV(t){const e=this.getScrollTop();this.scrollbarV.setOffset(t);return this.getScrollTop()!==e&&(this.updateScrollTop(),this.updateGroupList(),this.triggerEvent(),!0)}mouseWheelHandler(t){const e=t.deltaX,i=t.deltaY,o=Math.abs(e);if(o>Math.abs(i)){if(this.hasScrollH)return this.setOffsetH(e)}else{if(this.hasScrollV)return this.setOffsetV(i);if(this.hasScrollH&&!o)return this.setOffsetH(i)}return!1}keyPageUpHandler(t){return this.setOffsetV(-this.scrollViewH)}keyPageDownHandler(t){return this.setOffsetV(this.scrollViewH)}keyEndHandler(t){return this.setOffsetV(this.scrollBodyH)}keyHomeHandler(t){return this.setOffsetV(-this.scrollBodyH)}keyLeftHandler(t){return this.setOffsetH(-this.options.scrollSizeOnKeyPress)}keyUpHandler(t){return this.setOffsetV(-this.options.scrollSizeOnKeyPress)}keyRightHandler(t){return this.setOffsetH(this.options.scrollSizeOnKeyPress)}keyDownHandler(t){return this.setOffsetV(this.options.scrollSizeOnKeyPress)}destroy(){return this.visible=!1,this.groupH=null,this.groupV=null,this.scrollbarV&&(this.scrollbarV.destroy(),this.scrollbarV=null),this.scrollbarH&&(this.scrollbarH.destroy(),this.scrollbarH=null),this.$container=null,this.$scrollView=null,this.$scrollBody=null,this}}const Vt={initScrollPane:function(){this.initFrozenStyle(),this.createScrollPane()},initFrozenStyle:function(){const t={HL:{container:this.$paneHL,cls:[]},HR:{container:this.$paneHR,cls:[]},TL:{container:this.$paneTL,cls:[]},TR:{container:this.$paneTR,cls:[]},BL:{container:this.$paneBL,cls:[]},BR:{container:this.$paneBR,cls:[]}},e="tg-frozen-h";this.frozenInfo.rows&&(this.frozenInfo.bottom?(t.BL.cls.push(e),t.BR.cls.push(e)):(t.TL.cls.push(e),t.TR.cls.push(e)));const i="tg-frozen-v",o="tg-frozen-line-v";this.frozenInfo.columns&&(this.frozenInfo.right?(t.HR.cls.push(i),t.TR.cls.push(i),t.BR.cls.push(i)):(t.HL.cls.push(i),t.TL.cls.push(i),t.BL.cls.push(i)),t.HL.cls.push(o),t.TL.cls.push(o),t.BL.cls.push(o));const n="tg-frozen",s=[n,e,i,o].join(" ");Object.keys(t).forEach((function(e){const i=t[e],o=i.container;o.removeClass(s);const r=i.cls;if(!r.length)return;const l=[n].concat(r).join(" ");o.addClass(l)}))},createScrollPane:function(){this.removeScrollPane(),this.scrollPaneMap={HL:new kt(this.$paneHL,"header-left"),HR:new kt(this.$paneHR,"header-right"),TL:new kt(this.$paneTL,"top-left"),TR:new kt(this.$paneTR,"top-right"),BL:new kt(this.$paneBL,"bottom-left"),BR:new kt(this.$paneBR,"bottom-right")},this.scrollPaneMap.BR.setGroupH([this.scrollPaneMap.HR,this.scrollPaneMap.TR]),this.scrollPaneMap.TR.setGroupH([this.scrollPaneMap.HR,this.scrollPaneMap.BR]),this.scrollPaneMap.BL.setGroupH([this.scrollPaneMap.HL,this.scrollPaneMap.TL]),this.scrollPaneMap.TL.setGroupH([this.scrollPaneMap.HL,this.scrollPaneMap.BL]),this.scrollPaneMap.BR.setGroupV(this.scrollPaneMap.BL),this.scrollPaneMap.BL.setGroupV(this.scrollPaneMap.BR),this.scrollPaneMap.TR.setGroupV(this.scrollPaneMap.TL),this.scrollPaneMap.TL.setGroupV(this.scrollPaneMap.TR),this.initActiveScrollPane(),this.initPaneVisibility()},initActiveScrollPane:function(){const t=this.getScrollPaneVP(),e=this.getScrollPaneHP(),i=`${t}${e}`;this.scrollPane=this.scrollPaneMap[i],this.scrollPane.bind(kt.EVENT.CHANGE,((t,e)=>{this.scrollPaneChangeHandler(t,e)})).bind(kt.EVENT.START,(t=>{this.rowHoverable=!1})).bind(kt.EVENT.END,(t=>{this.rowHoverable=!0}));let o={L:"L",R:"L"};this.frozenInfo.columns&&this.frozenInfo.right&&(o={L:"R",R:"L"});const n=`${t}${o[e]}`;this.scrollPaneFrozen=this.scrollPaneMap[n]},getScrollPaneVP:function(){return this.frozenInfo.rows&&!this.frozenInfo.bottom?"B":"T"},getScrollPaneHP:function(){return this.frozenInfo.columns&&!this.frozenInfo.right?"R":"L"},initPaneVisibility:function(){this.scrollPaneMap.HL.show(),this.scrollPaneMap.TL.show(),this.frozenInfo.columns?(this.scrollPaneMap.HR.show(),this.scrollPaneMap.TR.show(),this.frozenInfo.rows?(this.scrollPaneMap.BL.show(),this.scrollPaneMap.BR.show()):(this.scrollPaneMap.BL.hide(),this.scrollPaneMap.BR.hide())):(this.scrollPaneMap.HR.hide(),this.scrollPaneMap.TR.hide(),this.scrollPaneMap.BR.hide(),this.frozenInfo.rows?this.scrollPaneMap.BL.show():this.scrollPaneMap.BL.hide())},scrollPaneChangeHandler:function(t,e){this.hideColumnLine(),this.scrollLeft=e.scrollLeft,this.scrollTop=e.scrollTop,this.scrollRenderHandler()},scrollbarFadeInOutHandler:function(t,e){this.options.scrollbarFade&&(e?this.updateScrollPaneFade(!0):this.options.scrollbarFadeTimeout||this.updateScrollPaneFade(!1))},updateScrollPaneFade:function(t){if(!this.options.scrollbarFade)return;this.updateScrollPaneFadeSync(t);const e=this.options.scrollbarFadeTimeout;e&&(clearTimeout(this.timeout_fade),this.timeout_fade=setTimeout((()=>{this.updateScrollPaneFadeSync(!1)}),e))},updateScrollPaneFadeSync:function(t){if(this.previousScrollbarFadeIn===t)return;this.previousScrollbarFadeIn=t;const e=[];Object.keys(this.scrollPaneMap).forEach((t=>{const i=this.scrollPaneMap[t];i.hasScrollbar()&&e.push(i)})),e.length&&e.forEach((function(e){e.fade(t)}))},updateScrollPane:function(){const t=this.getScrollbarOptions();this.scrollPaneMap.HL.render(this.getScrollPaneOptions({scrollPaneW:this.paneWidthL,scrollPaneH:this.headerHeight,scrollBodyW:this.bodyWidthL,scrollBodyH:this.headerHeight,scrollbarV:t.HLV,scrollbarH:t.HLH})),this.scrollPaneMap.HR.render(this.getScrollPaneOptions({scrollPaneW:this.paneWidthR,scrollPaneH:this.headerHeight,scrollBodyW:this.bodyWidthR,scrollBodyH:this.headerHeight,scrollbarV:t.HRV,scrollbarH:t.HRH})),this.scrollPaneMap.TL.render(this.getScrollPaneOptions({scrollPaneW:this.paneWidthL,scrollPaneH:this.paneHeightT,scrollBodyW:this.bodyWidthL,scrollBodyH:this.bodyHeightT,scrollbarV:t.TLV,scrollbarH:t.TLH})),this.scrollPaneMap.TR.render(this.getScrollPaneOptions({scrollPaneW:this.paneWidthR,scrollPaneH:this.paneHeightT,scrollBodyW:this.bodyWidthR,scrollBodyH:this.bodyHeightT,scrollbarV:t.TRV,scrollbarH:t.TRH})),this.scrollPaneMap.BL.render(this.getScrollPaneOptions({scrollPaneW:this.paneWidthL,scrollPaneH:this.paneHeightB,scrollBodyW:this.bodyWidthL,scrollBodyH:this.bodyHeightB,scrollbarV:t.BLV,scrollbarH:t.BLH})),this.scrollPaneMap.BR.render(this.getScrollPaneOptions({scrollPaneW:this.paneWidthR,scrollPaneH:this.paneHeightB,scrollBodyW:this.bodyWidthR,scrollBodyH:this.bodyHeightB,scrollbarV:t.BRV,scrollbarH:t.BRH})),this.scrollLeft=this.getScrollLeft(),this.scrollTop=this.getScrollTop(),this.updateScrollPaneFade(Boolean(this.options.scrollbarFadeTimeout))},getScrollPaneOptions:function(t){const e=this.options;return t.scrollbarFade=e.scrollbarFade,t.gradient=d.clamp(d.toNum(e.scrollPaneGradient,!0),0,100),t},getScrollbarOptions:function(){const t=this.options.scrollbarRound,e={};return["HLH","HLV","HRH","HRV","TLH","TLV","TRH","TRV","BLH","BLV","BRH","BRV"].forEach((function(i){e[i]={size:0,round:t,blank:!1}})),this.scrollbarOptionsHandler(e),this.scrollbarFadeHandler(e),e},scrollbarOptionsHandler:function(t){const e=this.scrollbarSizeH,i=this.scrollbarSizeV;this.scrollbarHeaderHandler(t,e,i),this.frozenInfo.columns?this.frozenInfo.rows?this.scrollbarC1R1Handler(t,e,i):this.scrollbarC1R0Handler(t,e,i):this.frozenInfo.rows?this.scrollbarC0R1Handler(t,e,i):this.scrollbarC0R0Handler(t,e,i)},scrollbarFadeHandler:function(t){if(this.options.scrollbarFade)for(const e in t)if(d.hasOwn(t,e)){const i=t[e];i.size>0&&i.blank&&(i.blank=!1,i.size=0)}},scrollbarHeaderHandler:function(t,e,i){this.hasVScroll&&(this.frozenInfo.columns?(t.HRV.size=i,t.HRV.blank=1):(t.HLV.size=i,t.HLV.blank=1))},scrollbarC0R0Handler:function(t,e,i){t.TLH.size=e,t.TLV.size=i},scrollbarC0R1Handler:function(t,e,i){this.frozenInfo.bottom?this.scrollbarC0R1B1Handler(t,e,i):this.scrollbarC0R1B0Handler(t,e,i)},scrollbarC0R1B1Handler:function(t,e,i){t.BLH.size=e,t.TLV.size=i,this.hasVScroll&&(t.BLV.size=i,t.BLV.blank=1)},scrollbarC0R1B0Handler:function(t,e,i){t.BLH.size=e,t.BLV.size=i,this.hasVScroll&&(t.TLV.size=i,t.TLV.blank=1)},scrollbarC1R0Handler:function(t,e,i){this.frozenInfo.right?this.scrollbarC1R0R1Handler(t,e,i):this.scrollbarC1R0R0Handler(t,e,i)},scrollbarC1R0R1Handler:function(t,e,i){this.hasHScroll&&(t.TLH.size=e,this.scrollPaneHidden?(t.TRH.size=e,t.TLH.blank=!0):(t.TRH.size=e,t.TRH.blank=!0)),t.TRV.size=i},scrollbarC1R0R0Handler:function(t,e,i){this.hasHScroll&&(t.TRH.size=e,this.scrollPaneHidden?(t.TLH.size=e,t.TRH.blank=!0):(t.TLH.size=e,t.TLH.blank=!0)),t.TRV.size=i},scrollbarC1R1Handler:function(t,e,i){this.frozenInfo.right?this.frozenInfo.bottom?this.scrollbarC1R1R1B1Handler(t,e,i):this.scrollbarC1R1R1B0Handler(t,e,i):this.frozenInfo.bottom?this.scrollbarC1R1R0B1Handler(t,e,i):this.scrollbarC1R1R0B0Handler(t,e,i)},scrollbarC1R1R1B1Handler:function(t,e,i){this.hasHScroll&&(t.BLH.size=e,this.scrollPaneHidden&&(t.BRH.size=e,t.BLH.blank=!0)),t.TRV.size=i,this.hasVScroll&&(t.BRV.size=i,t.BRV.blank=1)},scrollbarC1R1R1B0Handler:function(t,e,i){this.hasHScroll&&(t.BLH.size=e,this.scrollPaneHidden?(t.BRH.size=e,t.BLH.blank=!0):(t.BRH.size=e,t.BRH.blank=!0)),t.BRV.size=i,this.hasVScroll&&(t.TRV.size=i,t.TRV.blank=1)},scrollbarC1R1R0B1Handler:function(t,e,i){this.hasHScroll&&(t.BRH.size=e,this.scrollPaneHidden&&(t.BLH.size=e,t.BRH.blank=!0)),t.TRV.size=i,this.hasVScroll&&(t.BRV.size=i,t.BRV.blank=1)},scrollbarC1R1R0B0Handler:function(t,e,i){this.hasHScroll&&(t.BRH.size=e,this.scrollPaneHidden?(t.BLH.size=e,t.BRH.blank=!0):(t.BLH.size=e,t.BLH.blank=!0)),t.BRV.size=i,this.hasVScroll&&(t.TRV.size=i,t.TRV.blank=1)},removeScrollPane:function(){clearTimeout(this.timeout_fade),this.previousScrollbarFadeIn=null,this.scrollPaneMap&&(Object.keys(this.scrollPaneMap).forEach((t=>{const e=this.scrollPaneMap[t];e&&e.destroy()})),this.scrollPaneMap=null,this.scrollPane=null,this.scrollPaneFrozen=null)}},Ot={updateScrollState:function(){this.updateGlobalScrollInfo(),this.updateHScrollState(),this.updateVScrollState(),this.updateBlankColumnWidth(),this.scrollStateChanged=!1,this.previousHasHScroll===this.hasHScroll&&this.previousHasVScroll===this.hasVScroll||(this.scrollStateChanged=!0,this.previousHasHScroll=this.hasHScroll,this.previousHasVScroll=this.hasVScroll,this.trigger(y.onScrollStateChanged,{hasHScroll:this.hasHScroll,hasVScroll:this.hasVScroll}))},updateGlobalScrollInfo:function(){this.totalRowsLength=this.getRowsLength(),this.totalRowsHeight=this.getRowsHeight(),this.frozenRowsHeight=this.getFrozenRowsHeight(),this.scrollRowsHeight=this.totalRowsHeight-this.frozenRowsHeight,this.totalRowsHeight=Math.max(this.totalRowsHeight,1),this.scrollRowsHeight=Math.max(this.scrollRowsHeight,1),this.flushRowFrom(this.totalRowsLength)},updateHScrollState:function(){if(this.hasHScroll=!0,this.updateScrollPaneHiddenState(),this.updateHScrollByScrollPaneHidden(),this.scrollPaneHidden)return;this.containerWidth-this.columnsWidth>=0&&(this.hasHScroll=!1)},getScrollPaneCurrentWidth:function(){return this.frozenInfo.right?this.bodyWidth-this.columnsWidthR:this.bodyWidth-this.columnsWidthL},updateHScrollByScrollPaneHidden:function(){if(this.scrollPaneHidden){this.hasHScroll=!1;this.getScrollPaneCurrentWidth()=this.totalRowsHeight&&(this.hasVScroll=!1)}},updateBlankColumnWidth:function(){let t=this.containerWidth-this.columnsWidth;!this.hasVScroll||this.hasHScroll||this.options.scrollbarFade||(t-=this.scrollbarSizeV),this.scrollPaneHidden&&(t=0),this.hasHScroll||(t>=0?(this.frozenInfo.columns?this.columnsWidthR+=t:this.columnsWidthL+=t,this.blankColumn.tg_width=t):this.hasHScroll=!0)}},$t={scrollToRow:function(t){const e=this.getRowItem(t);return this.scrollToItem(e,null),this},scrollToColumn:function(t){const e=this.getColumnItem(t);return this.scrollToItem(null,e),this},scrollToCell:function(t,e){const i=this.getRowItem(t),o=this.getColumnItem(e);return this.scrollToItem(i,o),this},scrollToFirstRow:function(){return this.setScrollTop(0),this},scrollToLastRow:function(){const t=this.getViewRows(),e=t[t.length-1],i=this.getScrollRowPosition(e);if(d.isNum(i))return this.setScrollTop(i),this},scrollToFirstColumn:function(){return this.setScrollLeft(0),this},scrollToLastColumn:function(t){const e=this.getViewColumns();let i=e[e.length-2];t&&(i=e[e.length-1]);const o=this.getScrollColumnPosition(i);if(d.isNum(o))return this.setScrollLeft(o),this},scrollRowIntoView:function(t){const e=this.getRowItem(t);return this.scrollItemIntoView(e,null),this},scrollColumnIntoView:function(t){const e=this.getColumnItem(t);return this.scrollItemIntoView(null,e),this},scrollCellIntoView:function(t,e){const i=this.getRowItem(t),o=this.getColumnItem(e);return this.scrollItemIntoView(i,o),this},setScroll:function(t,e){return t===this.scrollLeft&&e===this.scrollTop||(this.scrollLeft=t,this.scrollTop=e,this.scrollHandler()),this},setScrollLeft:function(t){return t===this.scrollLeft||(this.scrollLeft=t,this.scrollHandler()),this},setScrollTop:function(t){return t===this.scrollTop||(this.scrollTop=t,this.scrollHandler()),this},getScrollRowPosition:function(t){if(!t)return;let e=t.tg_view_index;return e-=this.frozenInfo.rows,e>=0?this.getRowTop(t):void 0},getScrollColumnPosition:function(t){if(!t)return;let e=t.tg_left;return this.frozenInfo.columns&&(e-=this.bodyWidthL),e>=0?e:void 0},scrollToItem:function(t,e){return this.scrollToChanged=!1,this.scrollToRowHandler(t),this.scrollToColumnHandler(e),this.scrollToChanged?(this.scrollHandler(),this):this},scrollToRowHandler:function(t){if(!t)return;const e=this.getScrollRowPosition(t);d.isNum(e)&&e!==this.scrollTop&&(this.scrollTop=e,this.scrollToChanged=!0)},scrollToColumnHandler:function(t){if(!t)return;const e=this.getScrollColumnPosition(t);d.isNum(e)&&e!==this.scrollLeft&&(this.scrollLeft=e,this.scrollToChanged=!0)},scrollItemIntoView:function(t,e){return this.scrollIntoViewChanged=!1,this.scrollRowIntoViewHandler(t),this.scrollColumnIntoViewHandler(e),this.scrollIntoViewChanged?(this.scrollHandler(),this):this},scrollRowIntoViewHandler:function(t){if(!t)return;const e=this.getScrollRowPosition(t);if(!d.isNum(e))return;if(ethis.scrollTop+o){const t=e-(o-i);this.scrollTop=t,this.scrollIntoViewChanged=!0}},scrollColumnIntoViewHandler:function(t){if(!t)return;const e=this.getScrollColumnPosition(t);if(!d.isNum(e))return;if(ethis.scrollLeft+o){const t=e-(o-i);this.scrollLeft=t,this.scrollIntoViewChanged=!0}},scrollOnInit:function(){const{scrollLeft:t,scrollTop:e,scrollColumn:i,scrollRow:o}=this.renderSettings;this.scrollIntoViewChanged=!1,Number.isInteger(t)&&t!==this.scrollLeft&&(this.scrollLeft=t,this.scrollIntoViewChanged=!0),Number.isInteger(e)&&e!==this.scrollTop&&(this.scrollTop=e,this.scrollIntoViewChanged=!0),i&&this.scrollColumnIntoViewHandler(i),o&&this.scrollRowIntoViewHandler(o),this.scrollIntoViewChanged&&this.scrollPane.setPosition(this.scrollLeft,this.scrollTop)},scrollHandler:function(){this.scrollPane.setPosition(this.scrollLeft,this.scrollTop),this.scrollRenderHandler()},scrollRenderHandler:function(){this.previousScrollLeft===this.scrollLeft&&this.previousScrollTop===this.scrollTop||(this.previousScrollLeft=this.scrollLeft,this.previousScrollTop=this.scrollTop,this.onNextUpdated((()=>{this.updateScrollPaneFade(!0),this.trigger(y.onScroll,{scrollLeft:this.scrollLeft,scrollTop:this.scrollTop})})),this.render())},scrollTouchStartHandler:function(t,e){this.hideColumnLine(),this.scrollTouchLeft=this.getScrollLeft(),this.scrollTouchTop=this.getScrollTop(),this.scrollMaxTouchLeft=this.getMaxScrollLeft(),this.scrollMaxTouchTop=this.getMaxScrollTop()},getTouchOrientation:function(t){return t.orientation?t.orientation:[e.LEFT,e.RIGHT].includes(t.direction)?(t.orientation||(t.orientation="Y"),t.orientation):[e.UP,e.DOWN].includes(t.direction)?(t.orientation||(t.orientation="X"),t.orientation):void 0},scrollTouchMoveHandler:function(t,e){if(e.touchLength>1)return;let i=e.offsetX,o=e.offsetY;const n=this.getTouchOrientation(e);"X"===n?i=0:"Y"===n&&(o=0);let s=this.scrollTouchLeft-i,r=this.scrollTouchTop-o;s=d.clamp(s,0,this.scrollMaxTouchLeft),r=d.clamp(r,0,this.scrollMaxTouchTop);let l=!1;this.scrollPaneHidden&&(l=this.scrollPaneFrozen.setOffsetH(-e.moveX),s=0);const h=this.getScrollLeft(),a=this.getScrollTop();(s!==h||r!==a||l)&&(d.preventDefault(e.e),this.setScroll(s,r))},scrollTouchEndHandler:function(){this.protectedItem=null},scrollTouchInertiaHandler:function(t,e){const i=this.getScrollLeft(),o=this.getScrollTop(),n=i-e.touchInertiaX,s=o-e.touchInertiaY;this.setScroll(n,s)},getScrollViewWidth:function(){let t=this.getScrollPaneWidth();return this.frozenInfo.right||(t-=this.getScrollbarWidth()),t},getScrollViewHeight:function(){let t=this.getScrollPaneHeight();return this.frozenInfo.bottom||(t-=this.getScrollbarHeight()),t},getScrollPaneWidth:function(){return this.scrollPane.width()},getScrollPaneHeight:function(){return this.scrollPane.height()},getScrollbarWidth:function(){return this.hasVScroll&&!this.options.scrollbarFade?this.scrollbarSizeV:0},getScrollbarHeight:function(){return this.hasHScroll&&!this.options.scrollbarFade?this.scrollbarSizeH:0},getScrollLeft:function(){return this.scrollPane.getScrollLeft()},getScrollTop:function(){return this.scrollPane.getScrollTop()},getMaxScrollLeft:function(){return this.scrollPane.getMaxScrollLeft()},getMaxScrollTop:function(){return this.scrollPane.getMaxScrollTop()}};class Dt{constructor(t){this.options=this.generateOptions(t)}generateOptions(t){return d.merge({ignore:null,sortField:"",sortFactor:1,sortBlankFactor:1,sortComparer:null},t)}sortList(t){if(!d.isList(t)||1===t.length)return!1;this.ignoreExcludeHandler(t);const e=this.comparerHandler(t);return this.ignoreIncludeHandler(t),e}getDefaultComparer(t){return(ft[t]||ft.string).bind(this)}comparerHandler(t){const e=this.options,i=e.sortField,o=e.sortFactor,n=e.sortBlankFactor,s=e.sortComparer;return"function"==typeof s&&(t.sort(((t,e)=>s.call(this,t,e,{sortField:i,sortFactor:o,sortBlankFactor:n}))),!0)}ignoreExcludeHandler(t){const e=this.options.ignore;this.ignoreListTop=[],this.ignoreListBottom=[];const i=[];for(let o=0,n=t.length;o{t.unshift(e.item)})),this.ignoreListBottom.forEach((e=>{t.push(e.item)}))}}const Bt={removeSortColumn:function(){return this.sortColumn=null,this.$header&&this.$header.find(".tg-column-sorted").removeClass("tg-column-sorted"),this},setSortColumn:function(t){if(!(t=this.getColumnItem(t)))return;if(!this.isColumnSortable(t))return;t===this.sortColumn?t.sortAsc=!t.sortAsc:d.hasOwn(t,"sortAsc")||(t.sortAsc=this.options.sortAsc),this.sortColumn=t;if(this.getRowsLength()-this.frozenInfo.rows<2)return;if(!this.headerCreated)return;this.updateRowsSort()&&(this.renderHeaderSort(),this.flushSort(),this.render("rows"))},renderHeaderSort:function(){const t=this.sortColumn;if(!t)return this;if(!this.isColumnSortable(t))return this;this.$header.find(".tg-column-sorted").removeClass("tg-column-sorted");const e=t.tg_view_index,i=this.$header.find(`.tg-header-item[column='${e}']`).find(".tg-column-header").addClass("tg-column-sorted");return t.sortAsc?i.removeClass("tg-sort-desc").addClass("tg-sort-asc"):i.removeClass("tg-sort-asc").addClass("tg-sort-desc"),this},getSortComparer:function(t){const e=t.comparer;if("function"==typeof e)return e;const i=this.options.sortComparers,o=i[e||t.type];return"function"==typeof o?o:i.string},updateRowsSort:function(){const t=this.sortColumn;if(!t)return!1;const e=t.id;return!!e&&this.sortRows(e,t)},sortRows:function(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const i=e.sortAsc?-1:1,o=this.options.sortBlankValueBottom?1:i,n=this.getSortComparer(e);let s=!1;const r=new Dt({ignore:function(t){return t.tg_frozen?{item:t,top:!0}:t.sortFixed?{item:t,top:"top"===t.sortFixed}:void 0},sortField:t,sortFactor:i,sortBlankFactor:o,sortComparer:n}),l=function(t){r.sortList(t)&&(s=!0),t.forEach((function(t,e){t.tg_sub_index=e,t.subs&&l(t.subs)}))};return l(this.rows),s&&this.initRowsHandler(),s}},At={default:{},lightblue:{rowHeight:35,scrollbarSize:10,scrollbarRound:!0},dark:{}},Wt={getAllThemes:function(){return Object.keys(At)},getThemeOptions:function(t){return At[t]}},Ft={update:function(){return this.flushBody(),this.render("rows"),this},updateRow:function(t,e){const i=this.getRowItem(t);if(!i)return this;if(e&&"object"==typeof e){const t=this.getItemSnapshot(e);Object.keys(t).forEach((function(e){i[e]=t[e]}))}return this.flushRow(i.tg_view_index),this.render("rows"),this},updateCell:function(t,e,i){const o=this.getRowItem(t);if(!o)return this;const n=this.getColumnItem(e);return n?(arguments.length>2&&(o[n.id]=i),this.flushCell(o.tg_view_index,n.tg_view_index),this.render("rows"),this):this},onNextUpdated:function(t){return"function"!=typeof t||this.once(y.onUpdated,t),this}},Gt={getViewport:function(){this.scrollLeft=this.getScrollLeft(),this.scrollTop=this.getScrollTop();return{rows:this.getViewportRows(),columns:this.getViewportColumns()}},getViewportRows:function(){const t=[],e=this.viewRows,i=e.length;if(!i)return t;let o=this.options.rowCacheLength;o=d.clamp(d.toNum(o,!0),0,i);const n=this.frozenInfo.rows;if(n){let e=0;for(;e1;){const n=Math.floor(.5*(e+i)),s=t[n],r=this.getRowTop(s),l=this.getRowHeight(s);if(or+l))return n;e=n}}const n=t[i];return o=e)return[];const i=[],o=this.frozenInfo.columns,n=this.viewColumns;for(let s=o,r=n.length;s0;){const n=t[0]-1;n>o&&t.unshift(n);const s=t[t.length-1]+1;si)&&!(n0&&(e.rows.length=o),i=t.options}return this.data=e,this.dataOptions=i,this}setDataSnapshot(t){return this.setData(this.generateDataSnapshot(t)),this}getData(){return this.data}toString(){return"[object Grid]"}}var Ut;Ut=jt.prototype,[v,R,S,T,E,I,L,x,z,F,G,j,K,q,J,Z,tt,et,pt,mt,bt,wt,vt,Ht,{keyTabHandler:function(t){},keyEnterHandler:function(t){},keyEscHandler:function(t){},keyPageUpHandler:function(t){return this.scrollPane.keyPageUpHandler(t)},keyPageDownHandler:function(t){return this.scrollPane.keyPageDownHandler(t)},keyEndHandler:function(t){return this.scrollPane.keyEndHandler(t)},keyHomeHandler:function(t){return this.scrollPane.keyHomeHandler(t)},keyLeftHandler:function(t){return this.scrollPaneHidden?this.scrollPaneFrozen.keyLeftHandler(t):this.scrollPane.keyLeftHandler(t)},keyUpHandler:function(t){return this.scrollPane.keyUpHandler(t)},keyRightHandler:function(t){return this.scrollPaneHidden?this.scrollPaneFrozen.keyRightHandler(t):this.scrollPane.keyRightHandler(t)},keyDownHandler:function(t){return this.scrollPane.keyDownHandler(t)}},Ct,yt,Rt,St,Tt,{showRow:function(t){return this.updateRowsInvisible(this.toRowItemList(t),!1)},hideRow:function(t){return this.updateRowsInvisible(this.toRowItemList(t),!0)},updateRowsInvisible:function(t,e){if(!t.length)return!1;const i=[];return t.forEach((t=>{t.invisible!==e&&(t.invisible=e,t.tg_invisible=e,i.push(t))})),!!i.length&&(this.update(),!0)}},Et,It,Lt,xt,zt,Vt,Ot,$t,Bt,Wt,Ft,Gt].forEach((t=>{for(const e in t){if(d.hasOwn(Ut,e))throw new Error(`ERROR: extends with an existing key: "${e}"`);Ut[e]=t[e]}}));const Xt=jt,Yt=e.VERSION,Kt=e.TIMESTAMP,qt={VERSION:Yt,TIMESTAMP:Kt,Grid:Xt,$:w,CONST:e,EventBase:k,Icon:X,Motion:B,ScrollPane:kt,Util:d}})();var n=o.$,s=o.MP,r=o._d,l=o.xA,h=o.In,a=o.T8,c=o.Gr,d=o.ht,u=o.J0,g=o.xv,f=o.Ay;export{n as $,s as CONST,r as EventBase,l as Grid,h as Icon,a as Motion,c as ScrollPane,d as TIMESTAMP,u as Util,g as VERSION,f as default}; \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/json-checker.py b/custom_nodes/ComfyUI-Manager/json-checker.py new file mode 100644 index 000000000..a6c1317ff --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/json-checker.py @@ -0,0 +1,23 @@ +import json +import argparse + +def check_json_syntax(file_path): + try: + with open(file_path, 'r') as file: + json_str = file.read() + json.loads(json_str) + print(f"[ OK ] {file_path}") + except json.JSONDecodeError as e: + print(f"[FAIL] {file_path}\n\n {e}\n") + except FileNotFoundError: + print(f"[FAIL] {file_path}\n\n File not found\n") + +def main(): + parser = argparse.ArgumentParser(description="JSON File Syntax Checker") + parser.add_argument("file_path", type=str, help="Path to the JSON file for syntax checking") + + args = parser.parse_args() + check_json_syntax(args.file_path) + +if __name__ == "__main__": + main() diff --git a/custom_nodes/ComfyUI-Manager/misc/Impact.pack b/custom_nodes/ComfyUI-Manager/misc/Impact.pack new file mode 100644 index 000000000..93fd32847 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/misc/Impact.pack @@ -0,0 +1,444 @@ +{ + "Impact::MAKE_BASIC_PIPE": { + "category": "", + "config": { + "1": { + "input": { + "text": { + "name": "Positive prompt" + } + } + }, + "2": { + "input": { + "text": { + "name": "Negative prompt" + } + } + } + }, + "datetime": 1705418802481, + "external": [], + "links": [ + [ + 0, + 1, + 1, + 0, + 1, + "CLIP" + ], + [ + 0, + 1, + 2, + 0, + 1, + "CLIP" + ], + [ + 0, + 0, + 3, + 0, + 1, + "MODEL" + ], + [ + 0, + 1, + 3, + 1, + 1, + "CLIP" + ], + [ + 0, + 2, + 3, + 2, + 1, + "VAE" + ], + [ + 1, + 0, + 3, + 3, + 3, + "CONDITIONING" + ], + [ + 2, + 0, + 3, + 4, + 4, + "CONDITIONING" + ] + ], + "nodes": [ + { + "flags": {}, + "index": 0, + "mode": 0, + "order": 0, + "outputs": [ + { + "links": [], + "name": "MODEL", + "shape": 3, + "slot_index": 0, + "type": "MODEL" + }, + { + "links": [], + "name": "CLIP", + "shape": 3, + "slot_index": 1, + "type": "CLIP" + }, + { + "links": [], + "name": "VAE", + "shape": 3, + "slot_index": 2, + "type": "VAE" + } + ], + "pos": [ + 550, + 360 + ], + "properties": { + "Node name for S&R": "CheckpointLoaderSimple" + }, + "size": { + "0": 315, + "1": 98 + }, + "type": "CheckpointLoaderSimple", + "widgets_values": [ + "SDXL/sd_xl_base_1.0_0.9vae.safetensors" + ] + }, + { + "flags": {}, + "index": 1, + "inputs": [ + { + "link": null, + "name": "clip", + "type": "CLIP" + } + ], + "mode": 0, + "order": 1, + "outputs": [ + { + "links": [], + "name": "CONDITIONING", + "shape": 3, + "slot_index": 0, + "type": "CONDITIONING" + } + ], + "pos": [ + 940, + 480 + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "size": { + "0": 263, + "1": 99 + }, + "title": "Positive", + "type": "CLIPTextEncode", + "widgets_values": [ + "" + ] + }, + { + "flags": {}, + "index": 2, + "inputs": [ + { + "link": null, + "name": "clip", + "type": "CLIP" + } + ], + "mode": 0, + "order": 2, + "outputs": [ + { + "links": [], + "name": "CONDITIONING", + "shape": 3, + "slot_index": 0, + "type": "CONDITIONING" + } + ], + "pos": [ + 940, + 640 + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "size": { + "0": 263, + "1": 99 + }, + "title": "Negative", + "type": "CLIPTextEncode", + "widgets_values": [ + "" + ] + }, + { + "flags": {}, + "index": 3, + "inputs": [ + { + "link": null, + "name": "model", + "type": "MODEL" + }, + { + "link": null, + "name": "clip", + "type": "CLIP" + }, + { + "link": null, + "name": "vae", + "type": "VAE" + }, + { + "link": null, + "name": "positive", + "type": "CONDITIONING" + }, + { + "link": null, + "name": "negative", + "type": "CONDITIONING" + } + ], + "mode": 0, + "order": 3, + "outputs": [ + { + "links": null, + "name": "basic_pipe", + "shape": 3, + "slot_index": 0, + "type": "BASIC_PIPE" + } + ], + "pos": [ + 1320, + 360 + ], + "properties": { + "Node name for S&R": "ToBasicPipe" + }, + "size": { + "0": 241.79998779296875, + "1": 106 + }, + "type": "ToBasicPipe" + } + ], + "packname": "Impact", + "version": "1.0" + }, + "Impact::SIMPLE_DETAILER_PIPE": { + "category": "", + "config": { + "0": { + "output": { + "0": { + "visible": false + }, + "1": { + "visible": false + } + } + }, + "2": { + "input": { + "Select to add LoRA": { + "visible": false + }, + "Select to add Wildcard": { + "visible": false + }, + "wildcard": { + "visible": false + } + } + } + }, + "datetime": 1705419147116, + "external": [], + "links": [ + [ + null, + 0, + 2, + 0, + 6, + "BASIC_PIPE" + ], + [ + 0, + 0, + 2, + 1, + 13, + "BBOX_DETECTOR" + ], + [ + 1, + 0, + 2, + 2, + 15, + "SAM_MODEL" + ] + ], + "nodes": [ + { + "flags": {}, + "index": 0, + "mode": 0, + "order": 2, + "outputs": [ + { + "links": [], + "name": "BBOX_DETECTOR", + "shape": 3, + "type": "BBOX_DETECTOR" + }, + { + "links": null, + "name": "SEGM_DETECTOR", + "shape": 3, + "type": "SEGM_DETECTOR" + } + ], + "pos": [ + 590, + 830 + ], + "properties": { + "Node name for S&R": "UltralyticsDetectorProvider" + }, + "size": { + "0": 315, + "1": 78 + }, + "type": "UltralyticsDetectorProvider", + "widgets_values": [ + "bbox/Eyeful_v1.pt" + ] + }, + { + "flags": {}, + "index": 1, + "mode": 0, + "order": 3, + "outputs": [ + { + "links": [], + "name": "SAM_MODEL", + "shape": 3, + "type": "SAM_MODEL" + } + ], + "pos": [ + 590, + 960 + ], + "properties": { + "Node name for S&R": "SAMLoader" + }, + "size": { + "0": 315, + "1": 82 + }, + "type": "SAMLoader", + "widgets_values": [ + "sam_vit_b_01ec64.pth", + "AUTO" + ] + }, + { + "flags": {}, + "index": 2, + "inputs": [ + { + "link": null, + "name": "basic_pipe", + "type": "BASIC_PIPE" + }, + { + "link": null, + "name": "bbox_detector", + "slot_index": 1, + "type": "BBOX_DETECTOR" + }, + { + "link": null, + "name": "sam_model_opt", + "slot_index": 2, + "type": "SAM_MODEL" + }, + { + "link": null, + "name": "segm_detector_opt", + "type": "SEGM_DETECTOR" + }, + { + "link": null, + "name": "detailer_hook", + "type": "DETAILER_HOOK" + } + ], + "mode": 0, + "order": 5, + "outputs": [ + { + "links": null, + "name": "detailer_pipe", + "shape": 3, + "type": "DETAILER_PIPE" + } + ], + "pos": [ + 1044, + 812 + ], + "properties": { + "Node name for S&R": "BasicPipeToDetailerPipe" + }, + "size": { + "0": 400, + "1": 204 + }, + "type": "BasicPipeToDetailerPipe", + "widgets_values": [ + "", + "Select the LoRA to add to the text", + "Select the Wildcard to add to the text" + ] + } + ], + "packname": "Impact", + "version": "1.0" + } +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/misc/custom-nodes.jpg b/custom_nodes/ComfyUI-Manager/misc/custom-nodes.jpg new file mode 100644 index 0000000000000000000000000000000000000000..74c2a8bf5b98fde2cc196ca003fc1b8f10bb480c GIT binary patch literal 163372 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%0D0qEBa?%X?qs<$7wpGYKSgV=%X6$OQjuTDl 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 JSNmh>e*o)L@ZJCb literal 0 HcmV?d00001 diff --git a/custom_nodes/ComfyUI-Manager/misc/main.jpg b/custom_nodes/ComfyUI-Manager/misc/main.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ec31f76fcaf06cbd2b2b51d98f4d244bcd34fcb6 GIT binary patch literal 31758 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 T?>>o!VF(|5J8v&0TI9ib0_eR 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 V^gkaQ+YSon^c4*2Z~w9I{{hF=zo!5I literal 0 HcmV?d00001 diff --git a/custom_nodes/ComfyUI-Manager/misc/missing-list.jpg b/custom_nodes/ComfyUI-Manager/misc/missing-list.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ead9763725094ea69c5e7bc84fb8cbd786ab74f0 GIT binary patch literal 174344 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�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%0AR-(bIfxR=FMAEJQK;t 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 literal 0 HcmV?d00001 diff --git a/custom_nodes/ComfyUI-Manager/misc/models.png b/custom_nodes/ComfyUI-Manager/misc/models.png new file mode 100644 index 0000000000000000000000000000000000000000..9e985fb498d528218ec0f3ada8508c2abd6a6926 GIT binary patch literal 167680 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 literal 0 HcmV?d00001 diff --git a/custom_nodes/ComfyUI-Manager/misc/nickname.jpg b/custom_nodes/ComfyUI-Manager/misc/nickname.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e3cfdcac5f0be077c5f90543b0c480b87b0f2a1d GIT binary patch literal 186689 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

    6qs&2_LV5Z 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

      r#LBs_z6BT=Y%*7EVh7)ceXd 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

      (c4u!5*|@mFu{(E8N0-sD*0 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 literal 0 HcmV?d00001 diff --git a/custom_nodes/ComfyUI-Manager/misc/portable-install.png b/custom_nodes/ComfyUI-Manager/misc/portable-install.png new file mode 100644 index 0000000000000000000000000000000000000000..1771745132f0d541d17da70f5f131cef651cdada GIT binary patch literal 24418 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 literal 0 HcmV?d00001 diff --git a/custom_nodes/ComfyUI-Manager/misc/share-setting.jpg b/custom_nodes/ComfyUI-Manager/misc/share-setting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..631794a389d9cb4db96b39d1dd0c22d3b03bbce5 GIT binary patch literal 29478 zcmeFZbwHF&*EoDFEZr&10t+b3(nxnpH%cwt4IBHJ203{U{GvR9qPz$gf=853SQLQ(sUZb_ zm*q;v$Cv#@eRdciD_w)QUK zjNdw5F~aPv#Tg9*)Opn1WRZ6EN&y~7od6A8s{ltU5o< z;wkDU&Uh_c6ojwP+>Eem5-&$_MnkaJvaTLT7(W+37Y`?>J|6@lD8s|rMpRo);kN`Z zCeHY~sJ_0wT)uoyQ!=HCHPgsr`^+jTWSZT*#rwbfrVZr&bF*Xh<)+(;*+GbqdxY!}|Y zXhFWei2r5bud)VfC@SY_<$cAjEGN!*m8+<=tChXA=rt&4CCqDMC1lOXFNoj;Jqt@t zOA!GCCqJ(x!qQ3vDa_Ar^QRnT7f&w>7c1nI98fZsJt#!Ll3xTN#1FFaU2!3JcsMQi zt&yC(HiDo40c&9)r1hWtcRcLDZe-!~kL9_NV|^vZg4e=I*v5j>%Er=)lb^?mk5d@I zgX9#nvEk+C6%-Z`wzgt~T`5siT2on^5y8dtJF4kq;br6M;VjOmX7A$d_ZzEg?~K&( zvba(auMn>=uLy#Vhfk27kB8?^K7FKzC)hErL|qRXMwqpgr~)X+0&Hb_XA4^-w}Ttf z_PX$*vK~kaFINv;S63%-#=i#JA8G1fpSHH}vXHazLW0u%8hg5bjy-lB5z(t`!Mcj7 zyIR}Z`2SC&SEJ~<>6Gj}!EF71j|d&4`)|m}9(LUyMJ=qZdbc>Er-jdzqW?fz*;%;Q zBEfMA_LV;{_Wz>k5Eg>`7FGgQoB}-7e4P9?ptdbUtSmWskYE!Cf?Yv~U+_%A5*&3Ps3U(@`TSUhWR69R75U?7E*m79kb2%Cejps$zP z6`Tpeq@clO4Z=@Bn8O1sAPB#`!dw0Uf4PEfui>jrB0%b)t1S!G?P_-jv;7Cy@*iL; zI}c}&h99JXTRXde@=*-`fUU3Kz$@6<$r~)&wY%D(;v!x2bifb}erNziKp9X6Gyxc3 z33vncfD_;aaDt%=i17rp!E~Abf}iS|UlZiA1i9=1E09ADa0Q$Ji)()1strII(EY7j zPa8hOH41_&0|02tmzM|3;1)Us0DdK2UY-?RUj8Zq0MsP_=yLg+-?ab$gnxke#J_Ry zd;lN_2Y{B|zj2ls0MPmf04NsREIcf(^FalD6dQ26zF!Uict!v~G64YCCV%J+OuI@4 zisu197u1#7C;((-0|1LHDBJYEsQ1;L|1Z7$w=}=?cli#G1yE5?u3peV!50k^4GjuK z!^Xfs$Hc|P#l^wK!NJ2PCd9)h!pFfOBqt;yAtfUt!zH*uK~73ROiD(2B?N*B@<7qB z(9p0*@o?}+|IhC7H9&+3A%!@gLWlqqA_yuG74E&{lyAS)p%A=s5q=o*RtqPPOs$eoS504#4};Q7xBYDrfD=F?Zz z{7aj%07(?9XD}{S_LY<=&PfeVksQoQn>HR#CAbbE^s4{8v7AK;095K4bCzKCR}R937n{jz4nka3 z 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 A;Q#;t literal 0 HcmV?d00001 diff --git a/custom_nodes/ComfyUI-Manager/misc/share.jpg b/custom_nodes/ComfyUI-Manager/misc/share.jpg new file mode 100644 index 0000000000000000000000000000000000000000..97c0ae7de58265351e8cd4dfbb9489fedc41abb5 GIT binary patch literal 98371 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 ngm*MP1brH?u0vtUyQ?60y7|P!_>)B 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 WD^C9rjTiled Resample", + "reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", + "filename": "control_v11f1e_sd15_tile_fp16.safetensors", + "url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1e_sd15_tile_fp16.safetensors", + "size": "722.6MB" + }, + { + "name": "ControlNet-HandRefiner-pruned (inpaint-depth-hand; fp16)", + "type": "controlnet", + "base": "SD1.5", + "save_path": "default", + "description": "This inpaint-depth controlnet model is specialized for the hand refiner.", + "reference": "https://huggingface.co/hr16/ControlNet-HandRefiner-pruned", + "filename": "control_sd15_inpaint_depth_hand_fp16.safetensors", + "url": "https://huggingface.co/hr16/ControlNet-HandRefiner-pruned/resolve/main/control_sd15_inpaint_depth_hand_fp16.safetensors", + "size": "722.6MB" + }, + { + "name": "control_boxdepth_LooseControlfp16 (fp16)", + "type": "controlnet", + "base": "SD1.5", + "save_path": "default", + "description": "Loose ControlNet model", + "reference": "https://huggingface.co/ioclab/LooseControl_WebUICombine", + "filename": "control_boxdepth_LooseControlfp16.safetensors", + "url": "https://huggingface.co/ioclab/LooseControl_WebUICombine/resolve/main/control_boxdepth_LooseControlfp16.safetensors", + "size": "722.6MB" + }, + { + "name": "GLIGEN textbox (fp16; pruned)", + "type": "gligen", + "base": "SD1.5", + "save_path": "default", + "description": "GLIGEN textbox model", + "reference": "https://huggingface.co/comfyanonymous/GLIGEN_pruned_safetensors", + "filename": "gligen_sd14_textbox_pruned_fp16.safetensors", + "url": "https://huggingface.co/comfyanonymous/GLIGEN_pruned_safetensors/resolve/main/gligen_sd14_textbox_pruned_fp16.safetensors", + "size": "418.2MB" + }, + { + "name": "ViT-H SAM model", + "type": "sam", + "base": "SAM", + "save_path": "sams", + "description": "Segmenty Anything SAM model (ViT-H)", + "reference": "https://github.com/facebookresearch/segment-anything#model-checkpoints", + "filename": "sam_vit_h_4b8939.pth", + "url": "https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth", + "size": "2.56GB" + }, + { + "name": "ViT-L SAM model", + "type": "sam", + "base": "SAM", + "save_path": "sams", + "description": "Segmenty Anything SAM model (ViT-L)", + "reference": "https://github.com/facebookresearch/segment-anything#model-checkpoints", + "filename": "sam_vit_l_0b3195.pth", + "url": "https://dl.fbaipublicfiles.com/segment_anything/sam_vit_l_0b3195.pth", + "size": "1.25GB" + }, + { + "name": "ViT-B SAM model", + "type": "sam", + "base": "SAM", + "save_path": "sams", + "description": "Segmenty Anything SAM model (ViT-B)", + "reference": "https://github.com/facebookresearch/segment-anything#model-checkpoints", + "filename": "sam_vit_b_01ec64.pth", + "url": "https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth", + "size": "375.0MB" + }, + { + "name": "seecoder v1.0", + "type": "seecoder", + "base": "SEECODER", + "save_path": "seecoders", + "description": "SeeCoder model", + "reference": "https://huggingface.co/shi-labs/prompt-free-diffusion/tree/main/pretrained/pfd/seecoder", + "filename": "seecoder-v1-0.safetensors", + "url": "https://huggingface.co/shi-labs/prompt-free-diffusion/resolve/main/pretrained/pfd/seecoder/seecoder-v1-0.safetensors", + "size": "1.18GB" + }, + { + "name": "seecoder pa v1.0", + "type": "seecoder", + "base": "SEECODER", + "save_path": "seecoders", + "description": "SeeCoder model", + "reference": "https://huggingface.co/shi-labs/prompt-free-diffusion/tree/main/pretrained/pfd/seecoder", + "filename": "seecoder-pa-v1-0.safetensors", + "url": "https://huggingface.co/shi-labs/prompt-free-diffusion/resolve/main/pretrained/pfd/seecoder/seecoder-pa-v1-0.safetensors", + "size": "1.19GB" + }, + { + "name": "seecoder anime v1.0", + "type": "seecoder", + "base": "SEECODER", + "save_path": "seecoders", + "description": "SeeCoder model", + "reference": "https://huggingface.co/shi-labs/prompt-free-diffusion/tree/main/pretrained/pfd/seecoder", + "filename": "seecoder-anime-v1-0.safetensors", + "url": "https://huggingface.co/shi-labs/prompt-free-diffusion/resolve/main/pretrained/pfd/seecoder/seecoder-anime-v1-0.safetensors", + "size": "1.18GB" + }, + { + "name": "face_yolov8m (bbox)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/bbox", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "face_yolov8m.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/face_yolov8m.pt", + "size": "52.0MB" + }, + { + "name": "face_yolov8n (bbox)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/bbox", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "face_yolov8n.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/face_yolov8n.pt", + "size": "6.23MB" + }, + { + "name": "face_yolov8n_v2 (bbox)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/bbox", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "face_yolov8n_v2.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/face_yolov8n_v2.pt", + "size": "6.24MB" + }, + { + "name": "face_yolov8s (bbox)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/bbox", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "face_yolov8s.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/face_yolov8s.pt", + "size": "22.5MB" + }, + { + "name": "hand_yolov8n (bbox)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/bbox", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "hand_yolov8n.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/hand_yolov8n.pt", + "size": "6.24MB" + }, + { + "name": "hand_yolov8s (bbox)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/bbox", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "hand_yolov8s.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/hand_yolov8s.pt", + "size": "22.5MB" + }, + { + "name": "person_yolov8m (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "person_yolov8m-seg.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/person_yolov8m-seg.pt", + "size": "54.8MB" + }, + { + "name": "person_yolov8n (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "person_yolov8n-seg.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/person_yolov8n-seg.pt", + "size": "6.78MB" + }, + { + "name": "person_yolov8s (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "person_yolov8s-seg.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/person_yolov8s-seg.pt", + "size": "23.9MB" + }, + { + "name": "deepfashion2_yolov8s (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://huggingface.co/Bingsu/adetailer/tree/main", + "filename": "deepfashion2_yolov8s-seg.pt", + "url": "https://huggingface.co/Bingsu/adetailer/resolve/main/deepfashion2_yolov8s-seg.pt", + "size": "23.9MB" + }, + { + "name": "face_yolov8m-seg_60.pt (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://github.com/hben35096/assets/releases/tag/yolo8", + "filename": "face_yolov8m-seg_60.pt", + "url": "https://github.com/hben35096/assets/releases/download/yolo8/face_yolov8m-seg_60.pt", + "size": "54.8MB" + }, + { + "name": "face_yolov8n-seg2_60.pt (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://github.com/hben35096/assets/releases/tag/yolo8", + "filename": "face_yolov8n-seg2_60.pt", + "url": "https://github.com/hben35096/assets/releases/download/yolo8/face_yolov8n-seg2_60.pt", + "size": "6.77MB" + }, + { + "name": "hair_yolov8n-seg_60.pt (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://github.com/hben35096/assets/releases/tag/yolo8", + "filename": "hair_yolov8n-seg_60.pt", + "url": "https://github.com/hben35096/assets/releases/download/yolo8/hair_yolov8n-seg_60.pt", + "size": "6.77MB" + }, + { + "name": "skin_yolov8m-seg_400.pt (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://github.com/hben35096/assets/releases/tag/yolo8", + "filename": "skin_yolov8m-seg_400.pt", + "url": "https://github.com/hben35096/assets/releases/download/yolo8/skin_yolov8m-seg_400.pt", + "size": "54.9MB" + }, + { + "name": "skin_yolov8n-seg_400.pt (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://github.com/hben35096/assets/releases/tag/yolo8", + "filename": "skin_yolov8n-seg_400.pt", + "url": "https://github.com/hben35096/assets/releases/download/yolo8/skin_yolov8n-seg_400.pt", + "size": "6.83MB" + }, + { + "name": "skin_yolov8n-seg_800.pt (segm)", + "type": "Ultralytics", + "base": "Ultralytics", + "save_path": "ultralytics/segm", + "description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.", + "reference": "https://github.com/hben35096/assets/releases/tag/yolo8", + "filename": "skin_yolov8n-seg_800.pt", + "url": "https://github.com/hben35096/assets/releases/download/yolo8/skin_yolov8n-seg_800.pt", + "size": "6.84MB" + }, + { + "name": "animatediff/mmd_sd_v14.ckpt (comfyui-animatediff) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "AnimateDiff", + "description": "Pressing 'install' directly downloads the model from the ArtVentureX/AnimateDiff extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "mm_sd_v14.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v14.ckpt", + "size": "1.67GB" + }, + { + "name": "animatediff/mm_sd_v15.ckpt (comfyui-animatediff) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "AnimateDiff", + "description": "Pressing 'install' directly downloads the model from the ArtVentureX/AnimateDiff extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "mm_sd_v15.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v15.ckpt", + "size": "1.67GB" + }, + { + "name": "animatediff/mmd_sd_v14.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "mm_sd_v14.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v14.ckpt", + "size": "1.67GB" + }, + { + "name": "animatediff/mm_sd_v15.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "mm_sd_v15.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v15.ckpt", + "size": "1.67GB" + }, + { + "name": "animatediff/mm_sd_v15_v2.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "mm_sd_v15_v2.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v15_v2.ckpt", + "size": "1.82GB" + }, + { + "name": "animatediff/v3_sd15_mm.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v3_sd15_mm.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v3_sd15_mm.ckpt", + "size": "1.67GB" + }, + { + "name": "animatediff/mm_sdxl_v10_beta.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SDXL", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "mm_sdxl_v10_beta.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/mm_sdxl_v10_beta.ckpt", + "size": "950.1MB" + }, + { + "name": "AD_Stabilized_Motion/mm-Stabilized_high.pth (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/manshoety/AD_Stabilized_Motion", + "filename": "mm-Stabilized_high.pth", + "url": "https://huggingface.co/manshoety/AD_Stabilized_Motion/resolve/main/mm-Stabilized_high.pth", + "size": "1.67GB" + }, + { + "name": "AD_Stabilized_Motion/mm-Stabilized_mid.pth (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/manshoety/AD_Stabilized_Motion", + "filename": "mm-Stabilized_mid.pth", + "url": "https://huggingface.co/manshoety/AD_Stabilized_Motion/resolve/main/mm-Stabilized_mid.pth", + "size": "1.67GB" + }, + { + "name": "CiaraRowles/temporaldiff-v1-animatediff.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/CiaraRowles/TemporalDiff", + "filename": "temporaldiff-v1-animatediff.ckpt", + "url": "https://huggingface.co/CiaraRowles/TemporalDiff/resolve/main/temporaldiff-v1-animatediff.ckpt", + "size": "1.67GB" + }, + { + "name": "animatediff/v2_lora_PanLeft.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "motion lora", + "base": "SD1.x", + "save_path": "animatediff_motion_lora", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v2_lora_PanLeft.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_PanLeft.ckpt", + "size": "77.5MB" + }, + { + "name": "animatediff/v2_lora_PanRight.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "motion lora", + "base": "SD1.x", + "save_path": "animatediff_motion_lora", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v2_lora_PanRight.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_PanRight.ckpt", + "size": "77.5MB" + }, + { + "name": "animatediff/v2_lora_RollingAnticlockwise.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "motion lora", + "base": "SD1.x", + "save_path": "animatediff_motion_lora", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v2_lora_RollingAnticlockwise.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_RollingAnticlockwise.ckpt", + "size": "77.5MB" + }, + { + "name": "animatediff/v2_lora_RollingClockwise.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "motion lora", + "base": "SD1.x", + "save_path": "animatediff_motion_lora", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v2_lora_RollingClockwise.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_RollingClockwise.ckpt", + "size": "77.5MB" + }, + { + "name": "animatediff/v2_lora_TiltDown.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "motion lora", + "base": "SD1.x", + "save_path": "animatediff_motion_lora", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v2_lora_TiltDown.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_TiltDown.ckpt", + "size": "77.5MB" + }, + { + "name": "animatediff/v2_lora_TiltUp.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "motion lora", + "base": "SD1.x", + "save_path": "animatediff_motion_lora", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v2_lora_TiltUp.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_TiltUp.ckpt", + "size": "77.5MB" + }, + { + "name": "animatediff/v2_lora_ZoomIn.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "motion lora", + "base": "SD1.x", + "save_path": "animatediff_motion_lora", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v2_lora_ZoomIn.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_ZoomIn.ckpt", + "size": "77.5MB" + }, + { + "name": "animatediff/v2_lora_ZoomOut.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "motion lora", + "base": "SD1.x", + "save_path": "animatediff_motion_lora", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v2_lora_ZoomOut.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_ZoomOut.ckpt", + "size": "77.5MB" + }, + { + "name": "LongAnimatediff/lt_long_mm_32_frames.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/Lightricks/LongAnimateDiff", + "filename": "lt_long_mm_32_frames.ckpt", + "url": "https://huggingface.co/Lightricks/LongAnimateDiff/resolve/main/lt_long_mm_32_frames.ckpt", + "size": "1.82GB" + }, + { + "name": "LongAnimatediff/lt_long_mm_16_64_frames.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/Lightricks/LongAnimateDiff", + "filename": "lt_long_mm_16_64_frames.ckpt", + "url": "https://huggingface.co/Lightricks/LongAnimateDiff/resolve/main/lt_long_mm_16_64_frames.ckpt", + "size": "1.83GB" + }, + { + "name": "LongAnimatediff/lt_long_mm_16_64_frames_v1.1.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)", + "type": "animatediff", + "base": "SD1.x", + "save_path": "animatediff_models", + "description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.", + "reference": "https://huggingface.co/Lightricks/LongAnimateDiff", + "filename": "lt_long_mm_16_64_frames_v1.1.ckpt", + "url": "https://huggingface.co/Lightricks/LongAnimateDiff/resolve/main/lt_long_mm_16_64_frames_v1.1.ckpt", + "size": "1.83GB" + }, + { + "name": "animatediff/v3_sd15_sparsectrl_rgb.ckpt (ComfyUI-AnimateDiff-Evolved)", + "type": "controlnet", + "base": "SD1.x", + "save_path": "controlnet/SD1.5/animatediff", + "description": "AnimateDiff SparseCtrl RGB ControlNet model", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v3_sd15_sparsectrl_rgb.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v3_sd15_sparsectrl_rgb.ckpt", + "size": "1.99GB" + }, + { + "name": "animatediff/v3_sd15_sparsectrl_scribble.ckpt", + "type": "controlnet", + "base": "SD1.x", + "save_path": "controlnet/SD1.5/animatediff", + "description": "AnimateDiff SparseCtrl Scribble ControlNet model", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v3_sd15_sparsectrl_scribble.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v3_sd15_sparsectrl_scribble.ckpt", + "size": "1.99GB" + }, + { + "name": "animatediff/v3_sd15_adapter.ckpt", + "type": "lora", + "base": "SD1.x", + "save_path": "loras/SD1.5/animatediff", + "description": "AnimateDiff Adapter LoRA (SD1.5)", + "reference": "https://huggingface.co/guoyww/animatediff", + "filename": "v3_sd15_adapter.ckpt", + "url": "https://huggingface.co/guoyww/animatediff/resolve/main/v3_sd15_adapter.ckpt", + "size": "102.1MB" + }, + { + "name": "TencentARC/motionctrl.pth", + "type": "checkpoints", + "base": "MotionCtrl", + "save_path": "checkpoints/motionctrl", + "description": "To use the ComfyUI-MotionCtrl extension, downloading this model is required.", + "reference": "https://huggingface.co/TencentARC/MotionCtrl", + "filename": "motionctrl.pth", + "url": "https://huggingface.co/TencentARC/MotionCtrl/resolve/main/motionctrl.pth", + "size": "4.02GB" + }, + { + "name": "ip-adapter_sd15.safetensors", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter_sd15.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15.safetensors", + "size": "44.6MB" + }, + { + "name": "ip-adapter_sd15_light_v11.bin", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter_sd15_light_v11.bin", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_light_v11.bin", + "size": "44.6MB" + }, + { + "name": "ip-adapter_sd15_light.safetensors [DEPRECATED]", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter_sd15_light.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_light.safetensors", + "size": "44.6MB" + }, + { + "name": "ip-adapter-plus_sd15.safetensors", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter-plus_sd15.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-plus_sd15.safetensors", + "size": "98.2MB" + }, + { + "name": "ip-adapter-plus-face_sd15.safetensors", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter-plus-face_sd15.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-plus-face_sd15.safetensors", + "size": "98.2MB" + }, + { + "name": "ip-adapter-full-face_sd15.safetensors", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter-full-face_sd15.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-full-face_sd15.safetensors", + "size": "43.6MB" + }, + { + "name": "ip-adapter_sd15_vit-G.safetensors", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter_sd15_vit-G.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_vit-G.safetensors", + "size": "46.2MB" + }, + { + "name": "ip-adapter-faceid_sd15.bin", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Model (SD1.5) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid_sd15.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sd15.bin", + "size": "96.7MB" + }, + { + "name": "ip-adapter-faceid-plusv2_sd15.bin", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Plus V2 Model (SD1.5) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-plusv2_sd15.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sd15.bin", + "size": "156.6MB" + }, + { + "name": "ip-adapter-faceid-plus_sd15.bin [DEPRECATED]", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Plus Model (SD1.5) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-plus_sd15.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plus_sd15.bin", + "size": "156.6MB" + }, + { + "name": "ip-adapter-faceid-portrait-v11_sd15.bin", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Portrait V11 Model (SD1.5) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-portrait-v11_sd15.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait-v11_sd15.bin", + "size": "64.6MB" + }, + { + "name": "ip-adapter-faceid-portrait_sd15.bin [DEPRECATED]", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Portrait Model (SD1.5) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-portrait_sd15.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sd15.bin", + "size": "64.6MB" + }, + { + "name": "ip-adapter-faceid_sdxl.bin", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Model (SDXL) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid_sdxl.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sdxl.bin", + "size": "1.07GB" + }, + { + "name": "ip-adapter-faceid-plusv2_sdxl.bin", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Plus Model (SDXL) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-plusv2_sdxl.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sdxl.bin", + "size": "1.49GB" + }, + { + "name": "ip-adapter-faceid-portrait_sdxl.bin", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Portrait Model (SDXL) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-portrait_sdxl.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sdxl.bin", + "size": "749.8MB" + }, + { + "name": "ip-adapter-faceid-portrait_sdxl_unnorm.bin", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Portrait Model (SDXL/unnorm) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-portrait_sdxl_unnorm.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sdxl_unnorm.bin", + "size": "1.01GB" + }, + { + "name": "ip-adapter-faceid_sd15_lora.safetensors", + "type": "lora", + "base": "SD1.5", + "save_path": "loras/ipadapter", + "description": "IP-Adapter-FaceID LoRA Model (SD1.5) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid_sd15_lora.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sd15_lora.safetensors", + "size": "51.1MB" + }, + { + "name": "ip-adapter-faceid-plus_sd15_lora.safetensors [DEPRECATED]", + "type": "lora", + "base": "SD1.5", + "save_path": "loras/ipadapter", + "description": "IP-Adapter-FaceID Plus LoRA Model (SD1.5) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-plus_sd15_lora.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plus_sd15_lora.safetensors", + "size": "51.1MB" + }, + { + "name": "ip-adapter-faceid-plusv2_sd15_lora.safetensors", + "type": "lora", + "base": "SD1.5", + "save_path": "loras/ipadapter", + "description": "IP-Adapter-FaceID-Plus V2 LoRA Model (SD1.5) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-plusv2_sd15_lora.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sd15_lora.safetensors", + "size": "51.1MB" + }, + { + "name": "ip-adapter-faceid_sdxl_lora.safetensors", + "type": "lora", + "base": "SDXL", + "save_path": "loras/ipadapter", + "description": "IP-Adapter-FaceID LoRA Model (SDXL) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid_sdxl_lora.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sdxl_lora.safetensors", + "size": "371.8MB" + }, + { + "name": "ip-adapter-faceid-plusv2_sdxl_lora.safetensors", + "type": "lora", + "base": "SDXL", + "save_path": "loras/ipadapter", + "description": "IP-Adapter-FaceID-Plus V2 LoRA Model (SDXL) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-plusv2_sdxl_lora.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sdxl_lora.safetensors", + "size": "371.8MB" + }, + { + "name": "ip-adapter_sdxl.safetensors", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter_sdxl.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter_sdxl.safetensors", + "size": "702.6MB" + }, + { + "name": "ip-adapter_sdxl_vit-h.safetensors", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "This model requires the use of the SD1.5 encoder despite being for SDXL checkpoints [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter_sdxl_vit-h.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter_sdxl_vit-h.safetensors", + "size": "698.4MB" + }, + { + "name": "ip-adapter-plus_sdxl_vit-h.safetensors", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "This model requires the use of the SD1.5 encoder despite being for SDXL checkpoints [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter-plus_sdxl_vit-h.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter-plus_sdxl_vit-h.safetensors", + "size": "847.5MB" + }, + { + "name": "ip-adapter-plus-face_sdxl_vit-h.safetensors", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "This model requires the use of the SD1.5 encoder despite being for SDXL checkpoints [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter-plus-face_sdxl_vit-h.safetensors", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter-plus-face_sdxl_vit-h.safetensors", + "size": "847.5MB" + }, + { + "name": "ip_plus_composition_sd15.safetensors", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/ostris/ip-composition-adapter", + "filename": "ip_plus_composition_sd15.safetensors", + "url": "https://huggingface.co/ostris/ip-composition-adapter/resolve/main/ip_plus_composition_sd15.safetensors", + "size": "98.2MB" + }, + { + "name": "ip_plus_composition_sdxl.safetensors", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/ostris/ip-composition-adapter", + "filename": "ip_plus_composition_sdxl.safetensors", + "url": "https://huggingface.co/ostris/ip-composition-adapter/resolve/main/ip_plus_composition_sdxl.safetensors", + "size": "847.5MB" + }, + { + "name": "pfg-novel-n10.pt", + "type": "PFG", + "base": "SD1.5", + "save_path": "custom_nodes/pfg-ComfyUI/models", + "description": "Pressing 'install' directly downloads the model from the pfg-ComfyUI/models extension node. (Note: Requires ComfyUI-Manager V0.24 or above)", + "reference": "https://huggingface.co/furusu/PFG", + "filename": "pfg-novel-n10.pt", + "url": "https://huggingface.co/furusu/PFG/resolve/main/pfg-novel-n10.pt", + "size": "23.6MB" + }, + { + "name": "pfg-wd14-n10.pt", + "type": "PFG", + "base": "SD1.5", + "save_path": "custom_nodes/pfg-ComfyUI/models", + "description": "Pressing 'install' directly downloads the model from the pfg-ComfyUI/models extension node. (Note: Requires ComfyUI-Manager V0.24 or above)", + "reference": "https://huggingface.co/furusu/PFG", + "filename": "pfg-wd14-n10.pt", + "url": "https://huggingface.co/furusu/PFG/resolve/main/pfg-wd14-n10.pt", + "size": "31.5MB" + }, + { + "name": "pfg-wd15beta2-n10.pt", + "type": "PFG", + "base": "SD1.5", + "save_path": "custom_nodes/pfg-ComfyUI/models", + "description": "Pressing 'install' directly downloads the model from the pfg-ComfyUI/models extension node. (Note: Requires ComfyUI-Manager V0.24 or above)", + "reference": "https://huggingface.co/furusu/PFG", + "filename": "pfg-wd15beta2-n10.pt", + "url": "https://huggingface.co/furusu/PFG/resolve/main/pfg-wd15beta2-n10.pt", + "size": "31.5MB" + }, + { + "name": "GFPGANv1.4.pth", + "type": "GFPGAN", + "base": "GFPGAN", + "save_path": "facerestore_models", + "description": "Face Restoration Models. Download the model required for using the 'Facerestore CF (Code Former)' custom node.", + "reference": "https://github.com/TencentARC/GFPGAN/releases", + "filename": "GFPGANv1.4.pth", + "url": "https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/GFPGANv1.4.pth", + "size": "348.6MB" + }, + { + "name": "codeformer.pth", + "type": "CodeFormer", + "base": "CodeFormer", + "save_path": "facerestore_models", + "description": "Face Restoration Models. Download the model required for using the 'Facerestore CF (Code Former)' custom node.", + "reference": "https://github.com/sczhou/CodeFormer/releases", + "filename": "codeformer.pth", + "url": "https://github.com/sczhou/CodeFormer/releases/download/v0.1.0/codeformer.pth", + "size": "376.6MB" + }, + { + "name": "detection_Resnet50_Final.pth", + "type": "facexlib", + "base": "facexlib", + "save_path": "facerestore_models", + "description": "Face Detection Models. Download the model required for using the 'Facerestore CF (Code Former)' custom node.", + "reference": "https://github.com/xinntao/facexlib", + "filename": "detection_Resnet50_Final.pth", + "url": "https://github.com/xinntao/facexlib/releases/download/v0.1.0/detection_Resnet50_Final.pth", + "size": "109.5MB" + }, + { + "name": "detection_mobilenet0.25_Final.pth", + "type": "facexlib", + "base": "facexlib", + "save_path": "facerestore_models", + "description": "Face Detection Models. Download the model required for using the 'Facerestore CF (Code Former)' custom node.", + "reference": "https://github.com/xinntao/facexlib", + "filename": "detection_mobilenet0.25_Final.pth", + "url": "https://github.com/xinntao/facexlib/releases/download/v0.1.0/detection_mobilenet0.25_Final.pth", + "size": "1.79MB" + }, + { + "name": "yolov5l-face.pth", + "type": "facexlib", + "base": "facexlib", + "save_path": "facedetection", + "description": "Face Detection Models. Download the model required for using the 'Facerestore CF (Code Former)' custom node.", + "reference": "https://github.com/xinntao/facexlib", + "filename": "yolov5l-face.pth", + "url": "https://github.com/sczhou/CodeFormer/releases/download/v0.1.0/yolov5l-face.pth", + "size": "187.0MB" + }, + { + "name": "yolov5n-face.pth", + "type": "facexlib", + "base": "facexlib", + "save_path": "facedetection", + "description": "Face Detection Models. Download the model required for using the 'Facerestore CF (Code Former)' custom node.", + "reference": "https://github.com/xinntao/facexlib", + "filename": "yolov5n-face.pth", + "url": "https://github.com/sczhou/CodeFormer/releases/download/v0.1.0/yolov5n-face.pth", + "size": "7.15MB" + }, + { + "name": "photomaker-v1.bin", + "type": "photomaker", + "base": "SDXL", + "save_path": "photomaker", + "description": "PhotoMaker model. This model is compatible with SDXL.", + "reference": "https://huggingface.co/TencentARC/PhotoMaker", + "filename": "photomaker-v1.bin", + "url": "https://huggingface.co/TencentARC/PhotoMaker/resolve/main/photomaker-v1.bin", + "size": "934.1MB" + }, + { + "name": "1k3d68.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/antelopev2", + "description": "Antelopev2 1k3d68.onnx model for InstantId. (InstantId needs all Antelopev2 models)", + "reference": "https://github.com/cubiq/ComfyUI_InstantID#installation", + "filename": "1k3d68.onnx", + "url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/1k3d68.onnx", + "size": "143.6MB" + }, + { + "name": "2d106det.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/antelopev2", + "description": "Antelopev2 2d106det.onnx model for InstantId. (InstantId needs all Antelopev2 models)", + "reference": "https://github.com/cubiq/ComfyUI_InstantID#installation", + "filename": "2d106det.onnx", + "url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/2d106det.onnx", + "size": "5.03MB" + }, + { + "name": "genderage.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/antelopev2", + "description": "Antelopev2 genderage.onnx model for InstantId. (InstantId needs all Antelopev2 models)", + "reference": "https://github.com/cubiq/ComfyUI_InstantID#installation", + "filename": "genderage.onnx", + "url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/genderage.onnx", + "size": "1.32MB" + }, + { + "name": "glintr100.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/antelopev2", + "description": "Antelopev2 glintr100.onnx model for InstantId. (InstantId needs all Antelopev2 models)", + "reference": "https://github.com/cubiq/ComfyUI_InstantID#installation", + "filename": "glintr100.onnx", + "url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/glintr100.onnx", + "size": "260.7MB" + }, + { + "name": "scrfd_10g_bnkps.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/antelopev2", + "description": "Antelopev2 scrfd_10g_bnkps.onnx model for InstantId. (InstantId needs all Antelopev2 models)", + "reference": "https://github.com/cubiq/ComfyUI_InstantID#installation", + "filename": "scrfd_10g_bnkps.onnx", + "url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/scrfd_10g_bnkps.onnx", + "size": "16.9MB" + }, + { + "name": "ip-adapter.bin", + "type": "instantid", + "base": "SDXL", + "save_path": "instantid", + "description": "InstantId main model based on IpAdapter", + "reference": "https://huggingface.co/InstantX/InstantID", + "filename": "ip-adapter.bin", + "url": "https://huggingface.co/InstantX/InstantID/resolve/main/ip-adapter.bin", + "size": "1.69GB" + }, + { + "name": "diffusion_pytorch_model.safetensors", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/instantid", + "description": "InstantId controlnet model", + "reference": "https://huggingface.co/InstantX/InstantID", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "efficient_sam_s_cpu.jit [ComfyUI-YoloWorld-EfficientSAM]", + "type": "efficient_sam", + "base": "efficient_sam", + "save_path": "custom_nodes/ComfyUI-YoloWorld-EfficientSAM", + "description": "Install efficient_sam_s_cpu.jit into ComfyUI-YoloWorld-EfficientSAM", + "reference": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/tree/main", + "filename": "efficient_sam_s_cpu.jit", + "url": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/resolve/main/efficient_sam_s_cpu.jit", + "size": "106.0MB" + }, + { + "name": "efficient_sam_s_gpu.jit [ComfyUI-YoloWorld-EfficientSAM]", + "type": "efficient_sam", + "base": "efficient_sam", + "save_path": "custom_nodes/ComfyUI-YoloWorld-EfficientSAM", + "description": "Install efficient_sam_s_gpu.jit into ComfyUI-YoloWorld-EfficientSAM", + "reference": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/tree/main", + "filename": "efficient_sam_s_gpu.jit", + "url": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/resolve/main/efficient_sam_s_gpu.jit", + "size": "106.0MB" + }, + { + "name": "shape_predictor_68_face_landmarks.dat [Face Analysis]", + "type": "Shape Predictor", + "base": "DLIB", + "save_path": "custom_nodes/ComfyUI_FaceAnalysis/dlib", + "description": "To use the Face Analysis for ComfyUI custom node, installation of this model is needed.", + "reference": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/tree/main", + "filename": "shape_predictor_68_face_landmarks.dat", + "url": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/resolve/main/shape_predictor_68_face_landmarks.dat", + "size": "99.7MB" + }, + { + "name": "dlib_face_recognition_resnet_model_v1.dat [Face Analysis]", + "type": "Face Recognition", + "base": "DLIB", + "save_path": "custom_nodes/ComfyUI_FaceAnalysis/dlib", + "description": "To use the Face Analysis for ComfyUI custom node, installation of this model is needed.", + "reference": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/tree/main", + "filename": "dlib_face_recognition_resnet_model_v1.dat", + "url": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/resolve/main/dlib_face_recognition_resnet_model_v1.dat", + "size": "22.5MB" + }, + { + "name": "InstanceDiffusion/fusers", + "type": "InstanceDiffusion", + "base": "SD1.5", + "save_path": "instance_models/fuser_models", + "description": "Fusers checkpoints for multi-object prompting with InstanceDiffusion.", + "reference": "https://huggingface.co/logtd/instance_diffusion", + "filename": "fusers.ckpt", + "url": "https://huggingface.co/logtd/instance_diffusion/resolve/main/fusers.ckpt", + "size": "832.1MB" + }, + { + "name": "InstanceDiffusion/position_net", + "type": "InstanceDiffusion", + "base": "SD1.5", + "save_path": "instance_models/positionnet_models", + "description": "PositionNet checkpoints for multi-object prompting with InstanceDiffusion.", + "reference": "https://huggingface.co/logtd/instance_diffusion", + "filename": "position_net.ckpt", + "url": "https://huggingface.co/logtd/instance_diffusion/resolve/main/position_net.ckpt", + "size": "643.2MB" + }, + { + "name": "InstanceDiffusion/scaleu", + "type": "InstanceDiffusion", + "base": "SD1.5", + "save_path": "instance_models/scaleu_models", + "description": "ScaleU checkpoints for multi-object prompting with InstanceDiffusion.", + "reference": "https://huggingface.co/logtd/instance_diffusion", + "filename": "scaleu.ckpt", + "url": "https://huggingface.co/logtd/instance_diffusion/resolve/main/scaleu.ckpt", + "size": "53.1KB" + }, + { + "name": "1k3d68.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/buffalo_l", + "description": "Buffalo_l 1k3d68.onnx model for IpAdapterPlus", + "reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid", + "filename": "1k3d68.onnx", + "url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/1k3d68.onnx", + "size": "143.6MB" + }, + { + "name": "2d106det.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/buffalo_l", + "description": "Buffalo_l 2d106det.onnx model for IpAdapterPlus", + "reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid", + "filename": "2d106det.onnx", + "url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/2d106det.onnx", + "size": "5.03MB" + }, + { + "name": "det_10g.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/buffalo_l", + "description": "Buffalo_l det_10g.onnx model for IpAdapterPlus", + "reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid", + "filename": "det_10g.onnx", + "url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/det_10g.onnx", + "size": "16.9MB" + }, + { + "name": "genderage.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/buffalo_l", + "description": "Buffalo_l genderage.onnx model for IpAdapterPlus", + "reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid", + "filename": "genderage.onnx", + "url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/genderage.onnx", + "size": "1.32MB" + }, + { + "name": "w600k_r50.onnx", + "type": "insightface", + "base": "inswapper", + "save_path": "insightface/models/buffalo_l", + "description": "Buffalo_l w600k_r50.onnx model for IpAdapterPlus", + "reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid", + "filename": "w600k_r50.onnx", + "url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/w600k_r50.onnx", + "size": "174.4MB" + }, + { + "name": "BLIP ImageCaption (COCO) w/ ViT-B and CapFilt-L", + "type": "BLIP_MODEL", + "base": "blip_model", + "save_path": "blip", + "description": "BLIP ImageCaption (COCO) w/ ViT-B and CapFilt-L", + "reference": "https://github.com/salesforce/BLIP", + "filename": "model_base_capfilt_large.pth", + "url": "https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_capfilt_large.pth", + "size": "2.12GB" + }, + { + "name": "GroundingDINO SwinT OGC - Model", + "type": "GroundingDINO", + "base": "DINO", + "save_path": "groundingdino", + "description": "GroundingDINO SwinT OGC Model", + "reference": "https://huggingface.co/ShilongLiu/GroundingDINO", + "filename": "groundingdino_swint_ogc.pth", + "url": "https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/groundingdino_swint_ogc.pth", + "size": "694.0MB" + }, + { + "name": "GroundingDINO SwinT OGC - CFG File", + "type": "GroundingDINO", + "base": "DINO", + "save_path": "groundingdino", + "description": "GroundingDINO SwinT OGC CFG File", + "reference": "https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/GroundingDINO_SwinT_OGC.cfg.py", + "filename": "GroundingDINO_SwinT_OGC.cfg.py", + "url": "https://huggingface.co/ShilongLiu/GroundingDINO/raw/main/GroundingDINO_SwinT_OGC.cfg.py", + "size": "1.01KB" + }, + { + "name": "ViT-H SAM model", + "type": "sam", + "base": "SAM", + "save_path": "sams", + "description": "Segmenty Anything SAM model (ViT-H)", + "reference": "https://github.com/facebookresearch/segment-anything#model-checkpoints", + "filename": "sam_vit_h_4b8939.pth", + "url": "https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth", + "size": "2.56GB" + }, + { + "name": "ViT-L SAM model", + "type": "sam", + "base": "SAM", + "save_path": "sams", + "description": "Segmenty Anything SAM model (ViT-L)", + "reference": "https://github.com/facebookresearch/segment-anything#model-checkpoints", + "filename": "sam_vit_l_0b3195.pth", + "url": "https://dl.fbaipublicfiles.com/segment_anything/sam_vit_l_0b3195.pth", + "size": "1.25GB" + }, + { + "name": "MobileSAM", + "type": "sam", + "base": "SAM", + "save_path": "sams", + "description": "MobileSAM", + "reference": "https://github.com/ChaoningZhang/MobileSAM/", + "filename": "mobile_sam.pt", + "url": "https://github.com/ChaoningZhang/MobileSAM/blob/master/weights/mobile_sam.pt", + "size": "38.8MB" + }, + { + "name": "DynamiCrafter 1024 bf16 safetensors", + "type": "checkpoints", + "base": "DynamiCrafter", + "save_path": "checkpoints/dynamicrafter", + "description": "DynamiCrafter image2video model 1024x575", + "reference": "https://huggingface.co/Kijai/DynamiCrafter_pruned/", + "filename": "dynamicrafter_1024_v1_bf16.safetensors", + "url": "https://huggingface.co/Kijai/DynamiCrafter_pruned/resolve/main/dynamicrafter_1024_v1_bf16.safetensors", + "size": "5.22GB" + }, + { + "name": "DynamiCrafter 512 interpolation bf16 safetensors", + "type": "checkpoints", + "base": "DynamiCrafter", + "save_path": "checkpoints/dynamicrafter", + "description": "DynamiCrafter image2video interpolation model 512", + "reference": "https://huggingface.co/Kijai/DynamiCrafter_pruned/", + "filename": "dynamicrafter_512_interp_v1_bf16.safetensors", + "url": "https://huggingface.co/Kijai/DynamiCrafter_pruned/resolve/main/dynamicrafter_512_interp_v1_bf16.safetensors", + "size": "5.22GB" + }, + { + "name": "monster-labs - Controlnet QR Code Monster v1 For SDXL", + "type": "controlnet", + "base": "SDXL", + "save_path": "default", + "description": "monster-labs - Controlnet QR Code Monster v1 For SDXL", + "reference": "https://huggingface.co/monster-labs/control_v1p_sdxl_qrcode_monster", + "filename": "control_v1p_sdxl_qrcode_monster.safetensors", + "url": "https://huggingface.co/monster-labs/control_v1p_sdxl_qrcode_monster/resolve/main/diffusion_pytorch_model.safetensors", + "size": "5.00GB" + }, + { + "name": "Depth-FM-v1 fp16 safetensors", + "type": "checkpoints", + "base": "Depth-FM", + "save_path": "checkpoints/depthfm", + "description": "Depth-FM monocular depth estimation model", + "reference": "https://huggingface.co/Kijai/depth-fm-pruned", + "filename": "depthfm-v1_fp16.safetensors", + "url": "https://huggingface.co/Kijai/depth-fm-pruned/resolve/main/depthfm-v1_fp16.safetensors", + "size": "1.73GB" + }, + { + "name": "Depth-FM-v1 fp32 safetensors", + "type": "checkpoints", + "base": "Depth-FM", + "save_path": "checkpoints/depthfm", + "description": "Depth-FM monocular depth estimation model", + "reference": "https://huggingface.co/Kijai/depth-fm-pruned", + "filename": "depthfm-v1_fp32.safetensors", + "url": "https://huggingface.co/Kijai/depth-fm-pruned/resolve/main/depthfm-v1_fp32.safetensors", + "size": "3.46GB" + }, + { + "name": "SUPIR-v0F.ckpt", + "type": "checkpoints", + "base": "SUPIR", + "save_path": "checkpoints/SUPIR", + "description": "SUPIR checkpoint model", + "reference": "https://huggingface.co/camenduru/SUPIR/tree/main", + "filename": "SUPIR-v0F.ckpt", + "url": "https://huggingface.co/camenduru/SUPIR/resolve/main/SUPIR-v0F.ckpt", + "size": "5.33GB" + }, + { + "name": "SUPIR-v0Q.ckpt", + "type": "checkpoints", + "base": "SUPIR", + "save_path": "checkpoints/SUPIR", + "description": "SUPIR checkpoint model", + "reference": "https://huggingface.co/camenduru/SUPIR/tree/main", + "filename": "SUPIR-v0Q.ckpt", + "url": "https://huggingface.co/camenduru/SUPIR/resolve/main/SUPIR-v0Q.ckpt", + "size": "5.33GB" + }, + { + "name": "Kijai/SUPIR-v0F_fp16.safetensors (pruned)", + "type": "checkpoints", + "base": "SUPIR", + "save_path": "checkpoints/SUPIR", + "description": "SUPIR checkpoint model", + "reference": "https://huggingface.co/Kijai/SUPIR_pruned/tree/main", + "filename": "SUPIR-v0F_fp16.safetensors", + "url": "https://huggingface.co/Kijai/SUPIR_pruned/resolve/main/SUPIR-v0F_fp16.safetensors", + "size": "2.66GB" + }, + { + "name": "Kijai/SUPIR-v0Q_fp16.safetensors (pruned)", + "type": "checkpoints", + "base": "SUPIR", + "save_path": "checkpoints/SUPIR", + "description": "SUPIR checkpoint model", + "reference": "https://huggingface.co/Kijai/SUPIR_pruned/tree/main", + "filename": "SUPIR-v0Q_fp16.safetensors", + "url": "https://huggingface.co/Kijai/SUPIR_pruned/resolve/main/SUPIR-v0Q_fp16.safetensors", + "size": "2.66GB" + }, + { + "name": "RAM", + "type": "RAM", + "base": "RAM", + "save_path": "rams", + "description": "RAM Recognize Anything Model", + "reference": "https://huggingface.co/xinyu1205/recognize_anything_model", + "filename": "ram_swin_large_14m.pth", + "url": "https://huggingface.co/xinyu1205/recognize_anything_model/resolve/main/ram_swin_large_14m.pth", + "size": "5.63GB" + }, + { + "name": "RAM++", + "type": "RAM", + "base": "RAM", + "save_path": "rams", + "description": "RAM++ Recognize Anything Model", + "reference": "https://huggingface.co/xinyu1205/recognize-anything-plus-model", + "filename": "ram_plus_swin_large_14m.pth", + "url": "https://huggingface.co/xinyu1205/recognize-anything-plus-model/resolve/main/ram_plus_swin_large_14m.pth", + "size": "3.01GB" + }, + { + "name": "tag2text", + "type": "RAM", + "base": "RAM", + "save_path": "rams", + "description": "tag2text Recognize Anything Model", + "reference": "https://huggingface.co/xinyu1205/recognize_anything_model", + "filename": "tag2text_swin_14m.pth", + "url": "https://huggingface.co/xinyu1205/recognize_anything_model/resolve/main/tag2text_swin_14m.pth", + "size": "4.48GB" + }, + { + "name": "Zero123 3D object Model", + "type": "Zero123", + "base": "Zero123", + "save_path": "checkpoints/zero123", + "description": "model that been trained on 10M+ 3D objects from Objaverse-XL, used for generated rotated CamView", + "reference": "https://objaverse.allenai.org/docs/zero123-xl/", + "filename": "zero123-xl.ckpt", + "url": "https://huggingface.co/kealiu/zero123-xl/resolve/main/zero123-xl.ckpt", + "size": "15.5GB" + }, + { + "name": "Zero123 3D object Model", + "type": "Zero123", + "base": "Zero123", + "save_path": "checkpoints/zero123", + "description": "Stable Zero123 is a model for view-conditioned image generation based on [a/Zero123](https://github.com/cvlab-columbia/zero123).", + "reference": "https://huggingface.co/stabilityai/stable-zero123", + "filename": "stable_zero123.ckpt", + "url": "https://huggingface.co/stabilityai/stable-zero123/resolve/main/stable_zero123.ckpt", + "size": "8.58GB" + }, + { + "name": "Zero123 3D object Model", + "type": "Zero123", + "base": "Zero123", + "save_path": "checkpoints/zero123", + "description": "Zero123 original checkpoints in 105000 steps.", + "reference": "https://huggingface.co/cvlab/zero123-weights", + "filename": "zero123-105000.ckpt", + "url": "https://huggingface.co/cvlab/zero123-weights/resolve/main/105000.ckpt", + "size": "15.5GB" + }, + { + "name": "Zero123 3D object Model", + "type": "Zero123", + "base": "Zero123", + "save_path": "checkpoints/zero123", + "description": "Zero123 original checkpoints in 165000 steps.", + "reference": "https://huggingface.co/cvlab/zero123-weights", + "filename": "zero123-165000.ckpt", + "url": "https://huggingface.co/cvlab/zero123-weights/resolve/main/165000.ckpt", + "size": "15.5GB" + }, + { + "name": "InstantID/ip-adapter", + "type": "instantid", + "base": "SDXL", + "save_path": "instantid/SDXL", + "description": "ip-adapter model for cubiq/InstantID", + "reference": "https://huggingface.co/InstantX/InstantID", + "filename": "ip-adapter.bin", + "url": "https://huggingface.co/InstantX/InstantID/resolve/main/ip-adapter.bin", + "size": "1.69GB" + }, + { + "name": "InstantID/ControlNet", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/instantid", + "description": "instantid controlnet model for cubiq/InstantID", + "reference": "https://huggingface.co/InstantX/InstantID", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "MonsterMMORPG/insightface (for InstantID)", + "type": "insightface", + "base": "SDXL", + "save_path": "insightface/models", + "description": "MonsterMMORPG insightface model for cubiq/InstantID", + "reference": "https://huggingface.co/MonsterMMORPG/tools/tree/main", + "filename": "antelopev2.zip", + "url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/antelopev2.zip", + "size": "360.7MB" + }, + { + "name": "IC-Light/fc", + "type": "IC-Light", + "base": "SD1.5", + "save_path": "unet/IC-Light", + "description": "The default relighting model, conditioned on text and foreground", + "reference": "https://huggingface.co/lllyasviel/ic-light", + "filename": "iclight_sd15_fc.safetensors", + "url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fc.safetensors", + "size": "1.72GB" + }, + { + "name": "IC-Light/fbc", + "type": "IC-Light", + "base": "SD1.5", + "save_path": "unet/IC-Light", + "description": "Relighting model conditioned with text, foreground, and background", + "reference": "https://huggingface.co/lllyasviel/ic-light", + "filename": "iclight_sd15_fbc.safetensors", + "url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fbc.safetensors", + "size": "1.72GB" + }, + { + "name": "IC-Light/fcon", + "type": "IC-Light", + "base": "SD1.5", + "save_path": "unet/IC-Light", + "description": "Same as iclight_sd15_fc.safetensors, but trained with offset noise", + "reference": "https://huggingface.co/lllyasviel/ic-light", + "filename": "iclight_sd15_fcon.safetensors", + "url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fcon.safetensors", + "size": "1.72GB" + }, + { + "name": "ID-Animator/animator.ckpt", + "type": "ID-Animator", + "base": "SD1.5", + "save_path": "custom_nodes/ComfyUI_ID_Animator/models", + "description": "ID-Animator checkpoint", + "reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator", + "filename": "animator.ckpt", + "url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/animator.ckpt", + "size": "247.3MB" + }, + { + "name": "ID-Animator/mm_sd_v15_v2.ckpt", + "type": "ID-Animator", + "base": "SD1.5", + "save_path": "custom_nodes/ComfyUI_ID_Animator/models/animatediff_models", + "description": "AnimateDiff checkpoint for ID-Animator", + "reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator", + "filename": "mm_sd_v15_v2.ckpt", + "url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/mm_sd_v15_v2.ckpt", + "size": "1.82GB" + }, + { + "name": "ID-Animator/image_encoder", + "type": "ID-Animator", + "base": "SD1.5", + "save_path": "custom_nodes/ComfyUI_ID_Animator/models/image_encoder", + "description": "CLIP Image encoder for ID-Animator", + "reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator", + "filename": "model.safetensors", + "url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/image_encoder/model.safetensors", + "size": "2.53GB" + }, + { + "name": "TencentARC/CustomNet", + "type": "CustomNet", + "base": "CustomNet", + "save_path": "custom_nodes/ComfyUI_CustomNet/pretrain", + "description": "CustomNet pretrained model for ComfyUI_CustomNet", + "reference": "https://huggingface.co/TencentARC/CustomNet/tree/main", + "filename": "customnet_v1.pt", + "url": "https://huggingface.co/TencentARC/CustomNet/resolve/main/customnet_v1.pt", + "size": "5.71GB" + }, + { + "name": "TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic v2 (fp16)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "Controlnet SDXL Tile model realistic version.", + "reference": "https://huggingface.co/TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic", + "filename": "TTPLANET_Controlnet_Tile_realistic_v2_fp16.safetensors", + "url": "https://huggingface.co/TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic/resolve/main/TTPLANET_Controlnet_Tile_realistic_v2_fp16.safetensors", + "size": "2.50GB" + }, + { + "name": "TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic v2 (rank256)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "Controlnet SDXL Tile model realistic version.", + "reference": "https://huggingface.co/TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic", + "filename": "TTPLANET_Controlnet_Tile_realistic_v2_rank256.safetensors", + "url": "https://huggingface.co/TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic/resolve/main/TTPLANET_Controlnet_Tile_realistic_v2_rank256.safetensors", + "size": "774.4MB" + }, + { + "name": "ViperYX/RGT_x2.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT", + "description": "RGT x2 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_x2.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT/RGT_x2.pth", + "size": "179.8MB" + }, + { + "name": "ViperYX/RGT_x3.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT", + "description": "RGT x3 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_x3.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT/RGT_x3.pth", + "size": "180.5MB" + }, + { + "name": "ViperYX/RGT_x4.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT", + "description": "RGT_S x4 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_x4.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT/RGT_x4.pth", + "size": "180.4MB" + }, + { + "name": "ViperYX/RGT_S_x2.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT_S", + "description": "RGT_S x2 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_S_x2.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT_S/RGT_S_x2.pth", + "size": "135.4MB" + }, + { + "name": "ViperYX/RGT_S_x3.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT_S", + "description": "RGT_S x3 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_S_x3.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT_S/RGT_S_x3.pth", + "size": "136.1MB" + }, + { + "name": "ViperYX/RGT_S_x4.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT_S", + "description": "RGT_S x4 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_S_x4.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT_S/RGT_S_x4.pth", + "size": "136.0MB" + }, + { + "name": "Doubiiu/ToonCrafter model checkpoint", + "type": "checkpoint", + "base": "ToonCrafter", + "save_path": "custom_nodes/ComfyUI-ToonCrafter/ToonCrafter/checkpoints/tooncrafter_512_interp_v1", + "description": "ToonCrafter checkpoint model for ComfyUI-ToonCrafter", + "reference": "https://huggingface.co/Doubiiu/ToonCrafter/tree/main", + "filename": "model.ckpt", + "url": "https://huggingface.co/Doubiiu/ToonCrafter/resolve/main/model.ckpt", + "size": "10.5GB" + }, + + { + "name": "xinsir/ControlNet++: All-in-one ControlNet", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-union-sdxl-1.0", + "description": "All-in-one ControlNet for image generations and editing!", + "reference": "https://huggingface.co/xinsir/controlnet-union-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-union-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/Controlnet-Scribble-Sdxl-1.0", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-scribble-sdxl-1.0", + "description": "Controlnet SDXL Scribble model.", + "reference": "https://huggingface.co/xinsir/controlnet-scribble-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-scribble-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/Controlnet-Canny-Sdxl-1.0 (V2)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-canny-sdxl-1.0", + "description": "Controlnet SDXL Canny model.", + "reference": "https://huggingface.co/xinsir/controlnet-canny-sdxl-1.0", + "filename": "diffusion_pytorch_model_V2.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-canny-sdxl-1.0/resolve/main/diffusion_pytorch_model_V2.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/Controlnet-Openpose-Sdxl-1.0", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-openpose-sdxl-1.0", + "description": "Controlnet SDXL Openpose model.", + "reference": "https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/Controlnet-Openpose-Sdxl-1.0 (Ver. twins)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-openpose-sdxl-1.0", + "description": "Controlnet SDXL Openpose model. (Ver. twins)", + "reference": "https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0", + "filename": "diffusion_pytorch_model_twins.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0/resolve/main/diffusion_pytorch_model_twins.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/Controlnet-Scribble-Sdxl-1.0-Anime", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-scribble-sdxl-1.0-anime", + "description": "Controlnet SDXL Scribble model. (Ver. anime)", + "reference": "https://huggingface.co/xinsir/anime-painter", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/anime-painter/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/ControlNet Depth SDXL, support zoe, midias", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-depth-sdxl-1.0", + "description": "Controlnet SDXL Depth model.", + "reference": "https://huggingface.co/xinsir/controlnet-depth-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-depth-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/ControlNet Tile SDXL", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-tile-sdxl-1.0", + "description": "Controlnet SDXL Tile model.", + "reference": "https://huggingface.co/xinsir/controlnet-tile-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-tile-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + + { + "name": "InstantX/SD3-Controlnet-Canny", + "type": "controlnet", + "base": "SD3", + "save_path": "controlnet/SD3/InstantX-Controlnet-Canny", + "description": "Controlnet SD3 Canny model.", + "reference": "https://huggingface.co/InstantX/SD3-Controlnet-Canny", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/InstantX/SD3-Controlnet-Canny/resolve/main/diffusion_pytorch_model.safetensors", + "size": "1.19GB" + }, + { + "name": "InstantX/SD3-Controlnet-Pose", + "type": "controlnet", + "base": "SD3", + "save_path": "controlnet/SD3/InstantX-Controlnet-Pose", + "description": "Controlnet SD3 Pose model.", + "reference": "https://huggingface.co/InstantX/SD3-Controlnet-Pose", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/InstantX/SD3-Controlnet-Pose/resolve/main/diffusion_pytorch_model.safetensors", + "size": "1.19GB" + }, + { + "name": "InstantX/SD3-Controlnet-Tile", + "type": "controlnet", + "base": "SD3", + "save_path": "controlnet/SD3/InstantX-Controlnet-Tile", + "description": "Controlnet SD3 Tile model.", + "reference": "https://huggingface.co/InstantX/SD3-Controlnet-Tile", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/InstantX/SD3-Controlnet-Tile/resolve/main/diffusion_pytorch_model.safetensors", + "size": "1.19GB" + }, + + { + "name": "Kijai/ToonCrafter model checkpoint (interpolation fp16)", + "type": "checkpoint", + "base": "ToonCrafter", + "save_path": "checkpoints/ToonCrafter", + "description": "ToonCrafter checkpoint model for ComfyUI-DynamiCrafterWrapper", + "reference": "https://huggingface.co/Kijai/DynamiCrafter_pruned", + "filename": "tooncrafter_512_interp-fp16.safetensors", + "url": "https://huggingface.co/Kijai/DynamiCrafter_pruned/resolve/main/tooncrafter_512_interp-fp16.safetensors", + "size": "5.25GB" + }, + { + "name": "CN-anytest_v4-marged.safetensors", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged.safetensors", + "size": "2.50GB" + }, + { + "name": "CN-anytest_v4-marged_am_dim256.safetensors (dim256/Animagine)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet Lora (dim256) for Animagine. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged_am_dim256.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged_am_dim256.safetensors", + "size": "774.4MB" + }, + { + "name": "CN-anytest_v4-marged_am_dim128.safetensors (dim128/Animagine)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet Lora (dim128) for Animagine. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged_am_dim128.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged_am_dim128.safetensors", + "size": "395.7MB" + }, + { + "name": "CN-anytest_v4-marged_pn_dim256.safetensors (dim256/Pony)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet Lora (dim256) for Pony. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged_pn_dim256.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged_pn_dim256.safetensors", + "size": "774.4MB" + }, + { + "name": "CN-anytest_v4-marged_pn_dim128.safetensors (dim128/Pony)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet Lora (dim128) for Pony. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged_pn_dim128.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged_pn_dim128.safetensors", + "size": "395.7MB" + }, + { + "name": "CN-anytest_v3-50000_fp16.safetensors (fp16)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_fp16.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_fp16.safetensors", + "size": "2.50GB" + }, + { + "name": "CN-anytest_v3-50000_am_dim256.safetensors (dim256/Animagine)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet Lora (dim256) for Animagine. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_am_dim256.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_am_dim256.safetensors", + "size": "774.4MB" + }, + { + "name": "CN-anytest_v3-50000_am_dim128.safetensors (dim128/Animagine)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet Lora (dim128) for Animagine. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_am_dim128.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_am_dim128.safetensors", + "size": "395.7MB" + }, + { + "name": "CN-anytest_v3-50000_pn_dim256.safetensors (dim256/Pony)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet Lora (dim256) for Pony. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_pn_dim256.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_pn_dim256.safetensors", + "size": "774.4MB" + }, + { + "name": "CN-anytest_v3-50000_pn_dim128.safetensors (dim128/Pony)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "AnyTest Controlnet Lora (dim128) for Pony. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_pn_dim128.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_pn_dim128.safetensors", + "size": "395.7MB" + }, + { + "name": "kijai/DepthAnythingV2 (vitb/fp16)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vitb_fp16.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vitb_fp16.safetensors", + "size": "195.0MB" + }, + { + "name": "kijai/DepthAnythingV2 (vitb/fp32)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vitb_fp32.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vitb_fp32.safetensors", + "size": "389.9MB" + }, + { + "name": "kijai/DepthAnythingV2 (vitl/fp16)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vitl_fp16.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vitl_fp16.safetensors", + "size": "670.7MB" + }, + { + "name": "kijai/DepthAnythingV2 (vitl/fp32)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vitl_fp32.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vitl_fp32.safetensors", + "size": "1.34GB" + }, + { + "name": "kijai/DepthAnythingV2 (vits/fp16)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vits_fp16.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vits_fp16.safetensors", + "size": "49.6MB" + }, + { + "name": "kijai/DepthAnythingV2 (vitb/fp32)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vits_fp32.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vits_fp32.safetensors", + "size": "99.2MB" + }, + { + "name": "PixArt-Sigma-XL-2-1024-MS.pth", + "type": "checkpoint", + "base": "pixart-sigma", + "save_path": "checkpoints/PixArt-Sigma", + "description": "PixArt-Sigma Checkpoint model", + "reference": "https://huggingface.co/PixArt-alpha/PixArt-Sigma/tree/main", + "filename": "PixArt-Sigma-XL-2-1024-MS.pth", + "url": "https://huggingface.co/PixArt-alpha/PixArt-Sigma/resolve/main/PixArt-Sigma-XL-2-1024-MS.pth", + "size": "2.47GB" + } + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/dev/custom-node-list.json b/custom_nodes/ComfyUI-Manager/node_db/dev/custom-node-list.json new file mode 100644 index 000000000..6478121c1 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/dev/custom-node-list.json @@ -0,0 +1,1750 @@ +{ + "custom_nodes": [ + { + "author": "#NOTICE_1.13", + "title": "NOTICE: This channel is not the default channel.", + "reference": "https://github.com/ltdrdata/ComfyUI-Manager", + "files": [], + "install_type": "git-clone", + "description": "If you see this message, your ComfyUI-Manager is outdated.\nDev channel provides only the list of the developing nodes. If you want to find the complete node list, please go to the Default channel." + }, + + + { + "author": "tom-doerr", + "title": "DSPy Nodes [WIP]", + "reference": "https://github.com/tom-doerr/dspy_nodes", + "files": [ + "https://github.com/tom-doerr/dspy_nodes" + ], + "install_type": "git-clone", + "description": "This is an attempt to make all DSPy features available in ComfyUI. Using an UI to devlop DSPy programs should be way faster since it makes it easier to see what is happening and allows to quickly iterate on the DSPy program structure." + }, + { + "author": "Grant-CP", + "title": "ComfyUI-LivePortraitKJ-MPS", + "reference": "https://github.com/Grant-CP/ComfyUI-LivePortraitKJ-MPS", + "files": [ + "https://github.com/Grant-CP/ComfyUI-LivePortraitKJ-MPS" + ], + "install_type": "git-clone", + "description": "If you wish to incorporate these changes into your repo, feel free to open an issue and ask. The commits should be pretty clear, and I also label almost all changes with #HACK so a full text search will work too.\nPlease let me know if you decide to incorporate any of these changes into your LivePortrait implementation so I can direct people to you repository. I do not intend to maintain this repo.\nSome operations are simply not supported on MPS and I didn't rewrite them. Most of my changes are just to .cuda calls and that sort of thing. Many operations are still done on CPU, so don't expect awesome performance." + }, + { + "author": "justUmen", + "title": "Bjornulf_custom_nodes [WIP]", + "reference": "https://github.com/justUmen/Bjornulf_custom_nodes", + "files": [ + "https://github.com/justUmen/Bjornulf_custom_nodes" + ], + "install_type": "git-clone", + "description": "Nodes: ollamaLoader, ShowText, ShowInt, LoopTexts, LoopFloat, LoopInteger, ..." + }, + { + "author": "807502278", + "title": "ComfyUI-3D-MeshTool [WIP]", + "reference": "https://github.com/807502278/ComfyUI-3D-MeshTool", + "files": [ + "https://github.com/807502278/ComfyUI-3D-MeshTool" + ], + "install_type": "git-clone", + "description": "Introduction: A simple 3D model processing tool within ComfyUI" + }, + { + "author": "thderoo", + "title": "_topfun_s_nodes", + "reference": "https://github.com/thderoo/ComfyUI-_topfun_s_nodes", + "files": [ + "https://github.com/thderoo/ComfyUI-_topfun_s_nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Conditioning Perturbation" + }, + { + "author": "willblaschko", + "title": "ComfyUI-Unload-Models", + "reference": "https://github.com/willblaschko/ComfyUI-Unload-Models", + "files": [ + "https://github.com/willblaschko/ComfyUI-Unload-Models" + ], + "install_type": "git-clone", + "description": "This repository provides developers with a way to better manage their ComfyUI model memory. It includes nodes that allow developers to either unload all models or unload one model at a time. These nodes are designed as pass-through nodes, so they can be used anywhere in the flow. The nodes can be found in the 'Unload Model' section.[w/These are massive hammers, and it could be possible to break things, please don't use them if you need finesse.]" + }, + { + "author": "GeekyGhost", + "title": "ComfyUI-GeekyRemB v2", + "reference": "https://github.com/GeekyGhost/ComfyUI-GeekyRemB", + "files": [ + "https://github.com/GeekyGhost/ComfyUI-GeekyRemB/raw/SketchUITest/GeekyRembv2.py" + ], + "install_type": "copy", + "description": "GeekyRemB Node Description: GeekyRemB is a powerful and versatile image processing node for ComfyUI, designed to remove backgrounds from images with advanced customization options. This node leverages the rembg library and offers a wide range of features for fine-tuning the background removal process and enhancing the resulting images." + }, + { + "author": "AIFSH", + "title": "ComfyUI-OpenDIT [WIP]", + "id": "opendit", + "reference": "https://github.com/AIFSH/ComfyUI-OpenDIT", + "files": [ + "https://github.com/AIFSH/ComfyUI-OpenDIT" + ], + "install_type": "git-clone", + "description": "make [a/OpenDIT](https://github.com/NUS-HPC-AI-Lab/OpenDiT) avaliable in ComfyUI" + }, + { + "author": "alexisrolland", + "title": "alexisrolland/ComfyUI-AuraSR", + "id": "aurasr-alexisrolland", + "reference": "https://github.com/alexisrolland/ComfyUI-AuraSR", + "files": [ + "https://github.com/alexisrolland/ComfyUI-AuraSR" + ], + "install_type": "git-clone", + "description": "Custom ComfyUI nodes to run [a/fal-ai/AuraSR](https://huggingface.co/fal-ai/AuraSR) model.[w/This node cannot be installed simultaneously with AIFSH/ComfyUI-AuraSR due to overlapping repository names.]" + }, + { + "author": "mingqizhang", + "title": "ComfyUI_AEMatter_zmq", + "id": "aematter", + "reference": "https://github.com/mingqizhang/ComfyUI_AEMatter_zmq", + "files": [ + "https://github.com/mingqizhang/ComfyUI_AEMatter_zmq" + ], + "install_type": "git-clone", + "description": "Nodes:AEMatter_ModelLoader, Create_Trimap, AEMatter_Apply, Mask_Transfor, Replace_Background, Gaussian_Filter, Guide_Filter, Improved_Aplha_Composite" + }, + { + "author": "m-ai-studio", + "title": "mai-prompt-progress", + "reference": "https://github.com/m-ai-studio/mai-prompt-progress", + "files": [ + "https://github.com/m-ai-studio/mai-prompt-progress" + ], + "install_type": "git-clone", + "description": "mai-prompt-progress" + }, + { + "author": "linhusyung", + "title": "ComfyUI Build and Train Your Network [WIP]", + "id": "cfgpp", + "reference": "https://github.com/linhusyung/comfyui-Build-and-train-your-network", + "files": [ + "https://github.com/linhusyung/comfyui-Build-and-train-your-network" + ], + "install_type": "git-clone", + "description": "Stable Diffusion is an image generation technique based on diffusion models. Its core idea involves simulating diffusion processes by iteratively adding noise and using neural networks to predict and remove the noise, thereby generating high-quality images. This approach is not limited to image generation; with appropriate network architecture and training data, it can be adapted for various other tasks. The application of neural networks extends beyond image generation. By adjusting network structures and loss functions, neural networks can also perform tasks such as classification and regression. This flexibility makes neural networks a powerful tool for handling a wide range of machine learning tasks. This project aims to expand custom neural network layers (such as linear layers, convolutional layers, etc.) within ComfyUI and provide simplified task training functionalities. Through this project, users can easily construct custom neural network layers and perform training in ComfyUI using a graphical interface." + }, + { + "author": "alexgenovese", + "title": "comfyui_CfgPlusPlus [WIP]", + "id": "cfgpp", + "reference": "https://gitea.com/NotEvilGirl/cfgpp", + "files": [ + "https://gitea.com/NotEvilGirl/cfgpp" + ], + "install_type": "git-clone", + "description": "CFG++ implemented according to [a/https://cfgpp-diffusion.github.io](https://cfgpp-diffusion.github.io). Basically modified DDIM sampler that makes sampling work at low CFG values (0 ~ 2). Read the CFG++ paper for more details" + }, + { + "author": "Fucci-Mateo", + "title": "ComfyUI-Airtable [WIP]", + "id": "airtable", + "reference": "https://github.com/Fucci-Mateo/ComfyUI-Airtable", + "files": [ + "https://github.com/Fucci-Mateo/ComfyUI-Airtable" + ], + "install_type": "git-clone", + "description": "A simple node to load image from local path or http url. You can find this node from 'image' category." + }, + { + "author": "mingqizhang", + "title": "ComfyUI_AEMatter_zmq", + "id": "aematter-zmq", + "reference": "https://github.com/mingqizhang/ComfyUI_AEMatter_zmq", + "files": [ + "https://github.com/mingqizhang/ComfyUI_AEMatter_zmq" + ], + "install_type": "git-clone", + "description": "Nodes:AEMatter_ModelLoader, Create_Trimap, AEMatter_Apply, Mask_Transfor, Replace_Background, Gaussian_Filter, Guide_Filter" + }, + { + "author": "majorsauce", + "title": "comfyui_indieTools [WIP]", + "id": "indie-tools", + "reference": "https://github.com/majorsauce/comfyui_indieTools", + "files": [ + "https://github.com/majorsauce/comfyui_indieTools" + ], + "install_type": "git-clone", + "description": "Nodes:[Indie] Cut by Mask, [Indie] Paste Image, [Indie] Local Scale, [Indie] Solidify, [Indie] Yolo Detector.[w/Install may fail due to invliad requirements.txt file]" + }, + { + "author": "AIFSH", + "title": "ComfyUI-ViViD", + "id": "vivid", + "reference": "https://github.com/AIFSH/ComfyUI-ViViD", + "files": [ + "https://github.com/AIFSH/ComfyUI-ViViD" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for ViViD" + }, + { + "author": "NeuralNotW0rk", + "title": "ComfyUI-Waveform-Extensions", + "reference": "https://github.com/NeuralNotW0rk/ComfyUI-Waveform-Extensions", + "files": [ + "https://github.com/NeuralNotW0rk/ComfyUI-Waveform-Extensions/raw/main/EXT_VariationUtils.py", + "https://github.com/NeuralNotW0rk/ComfyUI-Waveform-Extensions/raw/main/EXT_AudioManipulation.py" + ], + "install_type": "copy", + "description": "Some additional audio utilites for use on top of Sample Diffusion ComfyUI Extension" + }, + { + "author": "mingqizhang", + "title": "ComfyUI_AEMatter_zmq", + "reference": "https://github.com/mingqizhang/ComfyUI_AEMatter_zmq", + "files": [ + "https://github.com/mingqizhang/ComfyUI_AEMatter_zmq" + ], + "install_type": "git-clone", + "description": "Nodes:AEMatter_ModelLoader, Create_Trimap, AEMatter_Apply, Mask_Transfor, Replace_Background, Gaussian_Filter, Guide_Filter." + }, + { + "author": "nat-chan", + "title": "comfyui-paint", + "reference": "https://github.com/nat-chan/comfyui-paint", + "files": [ + "https://github.com/nat-chan/comfyui-paint" + ], + "install_type": "git-clone", + "description": "comfyui-paint\n[w/You need to clone submodule manually after clone. There is permission issue.]" + }, + { + "author": "prabinpebam", + "title": "anyPython [UNSAFE]", + "reference": "https://github.com/prabinpebam/anyPython", + "files": [ + "https://github.com/prabinpebam/anyPython" + ], + "install_type": "git-clone", + "description": "This node was inspired by AnyNode. I wanted to have a node where I can paste any python script and execute it. That way I can use this node in combination with a Custom node like the Ollama node that can generate the python code and feed into this node. This also makes it much easier to debug or modify the code iteratively. As of the current version, I've created separate nodes for no input, 1 input and 2 inputs. The input also currently takes only sting as input. Let me know in the discussion how you would use this node.\n[w/This extension allows the execution of arbitrary Python code from a workflow.]" + }, + { + "author": "kijai", + "title": "ComfyUI DiffSynth wrapper nodes", + "id": "diffsynth-wrapper", + "reference": "https://github.com/kijai/ComfyUI-DiffSynthWrapper", + "files": [ + "https://github.com/kijai/ComfyUI-DiffSynthWrapper" + ], + "install_type": "git-clone", + "description": "Currently only the new extended SVD model 'ExVideo' is supported.\nOriginal repo:[a/https://github.com/modelscope/DiffSynth-Studio](https://github.com/modelscope/DiffSynth-Studio)" + }, + { + "author": "AllenEdgarPoe", + "title": "ComfyUI-Xorbis-nodes", + "id": "xorbis", + "reference": "https://github.com/AllenEdgarPoe/ComfyUI-Xorbis-nodes", + "files": [ + "https://github.com/AllenEdgarPoe/ComfyUI-Xorbis-nodes" + ], + "install_type": "git-clone", + "description": "This repository is for MuseumX Update. We use ComfyUI as our framework, and the nodes are built for my comfort." + }, + { + "author": "mikeymcfish", + "title": "LaserCutterFull and Deptherize Nodes", + "id": "fishtools", + "reference": "https://github.com/mikeymcfish/FishTools", + "files": [ + "https://github.com/mikeymcfish/FishTools" + ], + "install_type": "git-clone", + "description": "This repository contains two custom nodes, LaserCutterFull and Deptherize, designed for use in image processing workflows. The LaserCutterFull node processes input images to generate layers for laser cutting, while the Deptherize node converts SVG data into a depth map image." + }, + { + "author": "pzzmyc", + "title": "comfyui-sd3-simple-simpletuner", + "id": "simpletuner", + "reference": "https://github.com/pzzmyc/comfyui-sd3-simple-simpletuner", + "files": [ + "https://github.com/pzzmyc/comfyui-sd3-simple-simpletuner" + ], + "install_type": "git-clone", + "description": "Nodes:sd3 simple simpletuner by hhy." + }, + { + "author": "horidream", + "title": "ComfyUI-Horidream", + "id": "horidream", + "reference": "https://github.com/horidream/ComfyUI-Horidream", + "files": [ + "https://github.com/horidream/ComfyUI-Horidream" + ], + "install_type": "git-clone", + "description": "Nodes:Pass Through With Sound." + }, + { + "author": "kijai", + "title": "ComfyUI-DiffusersSD3Wrapper", + "id": "diffusers-sd3-wrapper", + "reference": "https://github.com/kijai/ComfyUI-DiffusersSD3Wrapper", + "files": [ + "https://github.com/kijai/ComfyUI-DiffusersSD3Wrapper" + ], + "install_type": "git-clone", + "description": "Nodes:Load SD3DiffusersPipeline, SD3 ControlNet Sampler" + }, + { + "author": "AustinMroz", + "title": "ComfyUI-SD3-Medium-CN-Diffusers [WIP]", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SD3-Medium-CN-Diffusers", + "files": [ + "https://github.com/AustinMroz/ComfyUI-WorkflowCheckpointing" + ], + "install_type": "git-clone", + "description": "ComfyUI SD3-Medium ControlNet (Diffusers)" + }, + { + "author": "redhottensors", + "title": "ComfyUI-ODE", + "id": "ode", + "reference": "https://github.com/redhottensors/ComfyUI-ODE", + "files": [ + "https://github.com/redhottensors/ComfyUI-ODE" + ], + "install_type": "git-clone", + "description": "ODE Solvers for ComfyUI\nThis node enables use of torchdiffeq ODE solvers with models. Intended for use with Stable Diffusion 3 and similar flow models." + }, + { + "author": "maruhidd", + "title": "Transparent Background for ComfyUI", + "id": "transparent-bg", + "reference": "https://github.com/maruhidd/ComfyUI_Transparent-Background", + "files": [ + "https://github.com/maruhidd/ComfyUI_Transparent-Background" + ], + "install_type": "git-clone", + "description": "Nodes:Remove Background, Fill Transparent" + }, + { + "author": "baicai99", + "title": "ComfyUI-FrameSkipping", + "id": "frame-skipping", + "reference": "https://github.com/baicai99/ComfyUI-FrameSkipping", + "files": [ + "https://github.com/baicai99/ComfyUI-FrameSkipping" + ], + "install_type": "git-clone", + "description": "This plugin can precisely control the rendering between frames, completing the synthesis of multiple frames in a single load. My homepage includes my attached workflow." + }, + { + "author": "ejektaflex", + "title": "ComfyUI - Ty", + "id": "ty-nodes", + "reference": "https://github.com/ejektaflex/ComfyUI-Ty", + "files": [ + "https://github.com/ejektaflex/ComfyUI-Ty" + ], + "install_type": "git-clone", + "description": "Nodes:Lora Block Weight Regex Loader" + }, + { + "author": "jtydhr88", + "title": "ComfyUI-Unique3D [WIP]", + "id": "unique3d", + "reference": "https://github.com/jtydhr88/ComfyUI-Unique3D", + "files": [ + "https://github.com/jtydhr88/ComfyUI-Unique3D" + ], + "install_type": "git-clone", + "description": "ComfyUI Unique3D is custom nodes that running [a/AiuniAI/Unique3D](https://github.com/AiuniAI/Unique3D) into ComfyUI." + }, + { + "author": "kycg", + "title": "comfyui-Kwtoolset", + "id": "kwtoolset", + "reference": "https://github.com/kycg/comfyui-Kwtoolset", + "files": [ + "https://github.com/kycg/comfyui-Kwtoolset" + ], + "install_type": "git-clone", + "description": "Nodes:KwtoolsetLoraLoaderwithpreview, KwtoolsetCheckpointLoaderwithpreview, KwtoolsetLoadCheckpointsBatch, KwtoolsetGrowMaskPlus, KwtoolsetGetHipMask, KwtoolsetGetHipMasktest, KwtoolsetGetImageSize, KWPositiveString, KWNagetiveString, KWanywhereString, KwtoolsetChangeOpenpose, ..." + }, + { + "author": "mashb1t", + "title": "ComfyUI mashb1t nodes", + "id": "mashb1t", + "reference": "https://github.com/mashb1t/comfyui-nodes-mashb1t", + "files": [ + "https://github.com/mashb1t/comfyui-nodes-mashb1t" + ], + "install_type": "git-clone", + "description": "This Python script is an optional add-on to the Comfy UI stable diffusion client." + }, + { + "author": "immersiveexperience", + "title": "ie-comfyui-color-nodes", + "reference": "https://github.com/immersiveexperience/ie-comfyui-color-nodes", + "files": [ + "https://github.com/immersiveexperience/ie-comfyui-color-nodes" + ], + "install_type": "git-clone", + "description": "Custom ComfyUI nodes for simple color correction." + }, + { + "author": "LZpenguin", + "title": "ComfyUI-Text", + "id": "comfy-text", + "reference": "https://github.com/LZpenguin/ComfyUI-Text", + "files": [ + "https://github.com/LZpenguin/ComfyUI-Text" + ], + "install_type": "git-clone", + "description": "Nodes:Add_text_by_mask.[w/This custom node cannot be installed simultaneously as it has the same repository name as MarkoCa1/ComfyUI-Text.]" + }, + { + "author": "yushan777", + "title": "Y7 Nodes for ComfyUI", + "id": "y7nodes", + "reference": "https://github.com/yushan777/ComfyUI-Y7Nodes", + "files": [ + "https://github.com/yushan777/ComfyUI-Y7Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Count_Tokens_(Y7)" + }, + { + "author": "norgeous", + "title": "UI Builder [WIP]", + "id": "norgeous", + "reference": "https://github.com/norgeous/ComfyUI-UI-Builder", + "files": [ + "https://github.com/norgeous/ComfyUI-UI-Builder" + ], + "install_type": "git-clone", + "description": "Alternative configurable React UI overlay for Comfy UI." + }, + { + "author": "Shinsplat", + "title": "ComfyUI-Shinsplat [UNSAFE]", + "id": "shinsplat", + "reference": "https://github.com/Shinsplat/ComfyUI-Shinsplat", + "files": [ + "https://github.com/Shinsplat/ComfyUI-Shinsplat" + ], + "install_type": "git-clone", + "description": "Nodes: Clip Text Encode (Shinsplat), Clip Text Encode SDXL (Shinsplat), Lora Loader (Shinsplat).\n[w/This extension poses a risk of executing arbitrary commands through workflow execution. Please be cautious.]" + }, + { + "author": "NitramDom", + "title": "ComfyUI_FacialFlip", + "id": "facialflip", + "reference": "https://github.com/NitramDom/ComfyUI_FacialFlip", + "files": [ + "https://github.com/NitramDom/ComfyUI_FacialFlip" + ], + "install_type": "git-clone", + "description": "Nodes:Swapper" + }, + { + "author": "hy134300", + "title": "comfyui-hydit", + "reference": "https://github.com/hy134300/comfyui-hydit", + "files": [ + "https://github.com/hy134300/comfyui-hydit" + ], + "install_type": "git-clone", + "description": "This repository contains a customized node and workflow designed specifically for HunYuan DIT. The official tests conducted on DDPM, DDIM, and DPMMS have consistently yielded results that align with those obtained through the Diffusers library. However, it's important to note that we cannot assure the consistency of results from other ComfyUI native samplers with the Diffusers inference. We cordially invite users to explore our workflow and are open to receiving any inquiries or suggestions you may have." + }, + { + "author": "corbin-hayden13", + "title": "ComfyUI-Better-Dimensions", + "id": "better-dim", + "reference": "https://github.com/corbin-hayden13/ComfyUI-Better-Dimensions", + "files": [ + "https://github.com/corbin-hayden13/ComfyUI-Better-Dimensions" + ], + "install_type": "git-clone", + "description": "Nodes:BetterImageDimensions, SDXLDimensions, PureRatio" + }, + { + "author": "endman100", + "title": "ComfyUI Nodes: SaveConditioning and LoadConditioning", + "id": "save-load-conditioning", + "reference": "https://github.com/endman100/ComfyUI-SaveAndLoadPromptCondition", + "files": [ + "https://github.com/endman100/ComfyUI-SaveAndLoadPromptCondition" + ], + "install_type": "git-clone", + "description": "The SaveConditioning node is designed to save conditioning data to binary files. This is useful for storing and reusing conditioning information across different sessions or applications.\n[w/This node can only handle very limited conditioning at the text prompt level.]" + }, + { + "author": "marduk191", + "title": "comfyui-marnodes", + "id": "marnodes", + "reference": "https://github.com/marduk191/comfyui-marnodes", + "files": [ + "https://github.com/marduk191/comfyui-marnodes" + ], + "install_type": "git-clone", + "description": "Nodes:marduk191_workflow_settings" + }, + { + "author": "kijai", + "title": "ComfyUI-CV-VAE", + "id": "cv-vae", + "reference": "https://github.com/kijai/ComfyUI-CV-VAE", + "files": [ + "https://github.com/kijai/ComfyUI-CV-VAE" + ], + "install_type": "git-clone", + "description": "Nodes:CV_VAE_Load, CV_VAE_Encode, CV_VAE_Decode" + }, + { + "author": "GentlemanHu", + "title": "ComfyUI Notifier", + "id": "notifier", + "reference": "https://github.com/GentlemanHu/ComfyUI-Notifier", + "files": [ + "https://github.com/GentlemanHu/ComfyUI-Notifier" + ], + "install_type": "git-clone", + "description": "Nodes:GentlemanHu_Notifier" + }, + { + "author": "jimmm-ai", + "title": "TimeUi a ComfyUI Timeline Node System [WIP]", + "id": "timeline", + "reference": "https://github.com/jimmm-ai/TimeUi-a-ComfyUi-Timeline-Node", + "files": [ + "https://github.com/jimmm-ai/TimeUi-a-ComfyUi-Timeline-Node" + ], + "install_type": "git-clone", + "description": "I've been working on the UX/UI of a timeline custom node system for ComfyUI over the past two weeks. The goal is to create a timeline similar to video/animation editing tools, without relying on traditional timeframe code. You can effortlessly add, delete, or rearrange rows, providing a streamlined user experience." + }, + { + "author": "jh-leon-kim", + "title": "ComfyUI-JHK-utils", + "id": "jhk", + "reference": "https://github.com/jh-leon-kim/ComfyUI-JHK-utils", + "files": [ + "https://github.com/jh-leon-kim/ComfyUI-JHK-utils" + ], + "install_type": "git-clone", + "description": "Nodes:JHK_Utils_LoadEmbed, JHK_Utils_string_merge, JHK_Utils_ImageRemoveBackground" + }, + { + "author": "StartHua", + "title": "Comfyui_CXH_CRM", + "id": "cxh-crm", + "reference": "https://github.com/StartHua/Comfyui_CXH_CRM", + "files": [ + "https://github.com/StartHua/Comfyui_CXH_CRM" + ], + "install_type": "git-clone", + "description": "Nodes:CRM" + }, + { + "author": "comfypod", + "title": "ComfyUI-Comflow", + "id": "comflow", + "reference": "https://github.com/comfypod/ComfyUI-Comflow", + "files": [ + "https://github.com/comfypod/ComfyUI-Comflow" + ], + "install_type": "git-clone", + "description": "ComfyUI-Comflow." + }, + { + "author": "pamparamm", + "title": "ComfyUI-ppm", + "id": "ppm", + "reference": "https://github.com/pamparamm/ComfyUI-ppm", + "files": [ + "https://github.com/pamparamm/ComfyUI-ppm" + ], + "install_type": "git-clone", + "description": "Nodes:Empty Latent Image (Aspect Ratio), Token Counter, Random Prompt Generator, StableCascade_AutoCompLatent, CLIPTextEncode, CLIPMicroConditioning, CLIPNegPip" + }, + { + "author": "Scorpinaus", + "title": "ComfyUI-DiffusersLoader", + "id": "diffusersloader", + "reference": "https://github.com/Scorpinaus/ComfyUI-DiffusersLoader", + "files": [ + "https://github.com/Scorpinaus/ComfyUI-DiffusersLoader" + ], + "install_type": "git-clone", + "description": "The purpose of this package is to understand how loading of diffusers format checkpoints are done in comfyUI and to create a loader that works for SDXL." + }, + { + "author": "FoundD-oka", + "title": "ComfyUI KISEKAE-OOTD", + "id": "kisekae-ootd", + "reference": "https://github.com/FoundD-oka/ComfyUI-kisekae-OOTD", + "files": [ + "https://github.com/FoundD-oka/ComfyUI-kisekae-OOTD" + ], + "install_type": "git-clone", + "description": "Nodes:LoadOOTDPipeline, LoadOOTDPipelineHub, LoadOOTDPipelineHub." + }, + { + "author": "bruce007lee", + "title": "comfyui-tiny-utils", + "id": "tiny-utils", + "reference": "https://github.com/bruce007lee/comfyui-tiny-utils", + "files": [ + "https://github.com/bruce007lee/comfyui-tiny-utils" + ], + "install_type": "git-clone", + "description": "Nodes:FaceAlign, FaceAlignImageProcess, FaceAlignMaskProcess" + }, + { + "author": "zmwv823", + "title": "ComfyUI-AnyText [UNSTABLE]", + "id": "anytext", + "reference": "https://github.com/zmwv823/ComfyUI-AnyText", + "files": [ + "https://github.com/zmwv823/ComfyUI-AnyText" + ], + "install_type": "git-clone", + "description": "Unofficial Simple And Rough Implementation Of [a/AnyText](https://github.com/tyxsspa/AnyText)" + }, + { + "author": "brycegoh", + "title": "brycegoh/comfyui-custom-nodes", + "reference": "https://github.com/brycegoh/comfyui-custom-nodes", + "files": [ + "https://github.com/brycegoh/comfyui-custom-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:MaskAreaComparisonSegment, FillMaskedArea, OCRAndMask, CombineTwoImageIntoOne" + }, + { + "author": "LykosAI", + "title": "ComfyUI Nodes for Inference.Core", + "id": "inference-core", + "reference": "https://github.com/LykosAI/ComfyUI-Inference-Core-Nodes", + "files": [ + "https://github.com/LykosAI/ComfyUI-Inference-Core-Nodes" + ], + "install_type": "git-clone", + "description": "Primary Nodes for Inference.Core and Stability Matrix. With a focus on not impacting startup performance and using fully qualified Node names. [w/This custom node is likely to conflict with many other nodes.]" + }, + { + "author": "blepping", + "title": "comfyui_overly_complicated_sampling", + "reference": "https://github.com/blepping/comfyui_overly_complicated_sampling", + "files": [ + "https://github.com/blepping/comfyui_overly_complicated_sampling" + ], + "install_type": "git-clone", + "description": "Very unstable, experimental and mathematically unsound sampling for ComfyUI.\nCurrent status: In flux, not suitable for general use." + }, + { + "author": "tracerstar", + "title": "comfyui-p5js-node", + "id": "p5js", + "reference": "https://github.com/tracerstar/comfyui-p5js-node", + "files": [ + "https://github.com/tracerstar/comfyui-p5js-node" + ], + "install_type": "git-clone", + "description": "A simple proof of concept node to pass a p5js canvas through ComfyUI for img2img generation use." + }, + { + "author": "chaojie", + "title": "ComfyUI-mobvoi-openapi", + "id": "mobvoi-openapi", + "reference": "https://github.com/chaojie/ComfyUI-mobvoi-openapi", + "files": [ + "https://github.com/chaojie/ComfyUI-mobvoi-openapi" + ], + "install_type": "git-clone", + "description": "Nodes:MobvoiOpenapiMetamanText, MobvoiOpenapiMetamanAudio, MobvoiOpenapiTts, HtmlViewer, OssUploadImage, OssUploadAudio" + }, + { + "author": "immersiveexperience", + "title": "ie-comfyui-color-nodes", + "id": "ie-color-nodes", + "reference": "https://github.com/immersiveexperience/ie-comfyui-color-nodes", + "files": [ + "https://github.com/immersiveexperience/ie-comfyui-color-nodes" + ], + "install_type": "git-clone", + "description": "Custom ComfyUI nodes for simple color correction." + }, + { + "author": "beyastard", + "title": "ComfyUI_BeySoft", + "reference": "https://github.com/beyastard/ComfyUI_BeySoft", + "files": [ + "https://github.com/beyastard/ComfyUI_BeySoft" + ], + "install_type": "git-clone", + "description": "Nodes:BeySoft" + }, + { + "author": "christian-byrne", + "title": "🌌 Infinite Parallax Nodes [WIP]", + "reference": "https://github.com/christian-byrne/infinite-zoom-parallax-nodes", + "files": [ + "https://github.com/christian-byrne/infinite-zoom-parallax-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Parallax Config, Load Parallax Frame, Save Parallax Object Layers, Layer Shifter for Parallax Outpainting, Save Parallax Frame, Shrink and Pad for Outpainting, Create Infinite Zoom Video" + }, + { + "author": "flyingdogsoftware", + "title": "Gyre for ComfyUI", + "id": "gyre", + "reference": "https://github.com/flyingdogsoftware/gyre_for_comfyui", + "files": [ + "https://github.com/flyingdogsoftware/gyre_for_comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:GyreLoopStart, GyreLoopEnd, GyreIfElse" + }, + { + "author": "githubYiheng", + "title": "comfyui_median_filter", + "id": "median-filter", + "reference": "https://github.com/githubYiheng/comfyui_median_filter", + "files": [ + "https://github.com/githubYiheng/comfyui_median_filter" + ], + "install_type": "git-clone", + "description": "Nodes:Apply Median Filter. [w/This has been updated to be equivalent to the comfyui_kmeans_filter node. Mistake?]" + }, + { + "author": "nat-chan", + "title": "comfyui-eval [UNSAFE]", + "id": "evalnode", + "reference": "https://github.com/nat-chan/comfyui-eval", + "files": [ + "https://github.com/nat-chan/comfyui-eval" + ], + "install_type": "git-clone", + "description": "Nodes:EvalNode [w/Please do not use the node that executes arbitrary code and outputs in any type, as it is dangerous.]" + }, + { + "author": "haofanwang", + "title": "ComfyUI-InstantStyle", + "id": "instantstyle", + "reference": "https://github.com/haofanwang/ComfyUI-InstantStyle", + "files": [ + "https://github.com/haofanwang/ComfyUI-InstantStyle" + ], + "install_type": "git-clone", + "description": "Nodes:PromptLoader, BaseModelLoader, InstantStyleLoader, InstantStyleGenerationNode" + }, + { + "author": "jp0215", + "title": "comfyUI_padding-resize_node", + "reference": "https://github.com/jp0215/comfyUI_padding-resize_node", + "files": [ + "https://github.com/jp0215/comfyUI_padding-resize_node/raw/main/PaddingNode.py", + "https://github.com/jp0215/comfyUI_padding-resize_node/raw/main/ResizeNode.py" + ], + "install_type": "copy", + "description": "Padding image to 8x: input image and mask, if the side length is not an integer multiple of 8, expand the side length to the smallest multiple of 8 greater than the original side length. Output padding image and mask. Resize to the origin: input the generated image and the original image, crop the generated image to the size of the original image, output the cropped image." + }, + { + "author": "Quasimondo", + "title": "ComfyUI-QuasimondoNodes [WIP]", + "id": "quasimondo-nodes", + "reference": "https://github.com/Quasimondo/ComfyUI-QuasimondoNodes", + "files": [ + "https://github.com/Quasimondo/ComfyUI-QuasimondoNodes" + ], + "install_type": "git-clone", + "description": "Nodes:Custom Shader, Spring Mesh" + }, + { + "author": "TSFSean", + "title": "ComfyUI-TSFNodes", + "id": "tsfnodes", + "reference": "https://github.com/TSFSean/ComfyUI-TSFNodes", + "files": [ + "https://github.com/TSFSean/ComfyUI-TSFNodes" + ], + "install_type": "git-clone", + "description": "Nodes:GyroOSC" + }, + { + "author": "blib-la", + "title": "ComfyUI-Captain-Extensions", + "id": "captain", + "reference": "https://github.com/blib-la/ComfyUI-Captain-Extensions", + "files": [ + "https://github.com/blib-la/ComfyUI-Captain-Extensions" + ], + "install_type": "git-clone", + "description": "ComfyUI extensions for better [a/Captain](https://github.com/blib-la/captain) integration." + }, + { + "author": "ejektaflex", + "title": "ComfyUI-Ty", + "reference": "https://github.com/ejektaflex/ComfyUI-Ty", + "files": [ + "https://github.com/ejektaflex/ComfyUI-Ty" + ], + "install_type": "git-clone", + "description": "Nodes:Lora Block Weight Regex Loader" + }, + { + "author": "christian-byrne", + "title": "Python Interpreter ComfyUI Node [UNSAFE]", + "reference": "https://github.com/christian-byrne/python-interpreter-node", + "files": [ + "https://github.com/christian-byrne/python-interpreter-node" + ], + "install_type": "git-clone", + "description": "For debugging, parsing data, generating random values, converting types, testing custom nodes faster.\nReference and use variables in the code using the same names as the inputs in the UI\nWrapper class around tensors with operator overloading for doing common image manipulation tasks.I might remove this aspect\n[w/This extension allows you to run programs through Python code in your workflow, which may not be secure. Use with caution.]" + }, + { + "author": "sofakid", + "title": "dandy [UNSAFE]", + "reference": "https://github.com/sofakid/dandy", + "files": [ + "https://github.com/sofakid/dandy" + ], + "install_type": "git-clone", + "description": "Dandy is a JavaScript bridge for ComfyUI. It includes everything you need to make JavaScript enabled extensions, or just load and code in little editor nodes right in ComfyUI.[w/This code can cause security issues because it allows for the execution of arbitrary JavaScript input.]" + }, + { + "author": "tachyon-beep", + "title": "comfyui-simplefeed [UNSAFE]", + "reference": "https://github.com/tachyon-beep/comfyui-simplefeed", + "files": [ + "https://github.com/tachyon-beep/comfyui-simplefeed" + ], + "install_type": "git-clone", + "description": "A simple image feed for comfyUI which is easily configurable and easily extensible.\nUse the filter button to select which nodes write to the feed. Under settings, there are options that allow you: Position the feed. Set a max iamge count for the feed. Set oldest to newest or newest to oldest." + }, + { + "author": "shadowcz007", + "title": "ComfyUI-PuLID [TEST]", + "reference": "https://github.com/shadowcz007/ComfyUI-PuLID-Test", + "files": [ + "https://github.com/shadowcz007/ComfyUI-PuLID-Test" + ], + "install_type": "git-clone", + "description": "[a/PuLID](https://github.com/ToTheBeginning/PuLID) ComfyUI native implementation." + }, + { + "author": "sangeet", + "title": "comfyui-testui [TEST]", + "reference": "https://github.com/sangeet/comfyui-testui", + "files": [ + "https://github.com/sangeet/comfyui-testui" + ], + "install_type": "git-clone", + "description": "Simple Frontend For ComfyUI workflow" + }, + { + "author": "Elawphant", + "title": "ComfyUI-MusicGen [WIP]", + "id": "musicgen", + "reference": "https://github.com/Elawphant/ComfyUI-MusicGen", + "files": [ + "https://github.com/Elawphant/ComfyUI-MusicGen" + ], + "install_type": "git-clone", + "description": "ComfyUI for Meta MusicGen." + }, + { + "author": "jtscmw01", + "title": "ComfyUI-DiffBIR", + "id": "diffbir", + "reference": "https://github.com/jtscmw01/ComfyUI-DiffBIR", + "files": [ + "https://github.com/jtscmw01/ComfyUI-DiffBIR" + ], + "install_type": "git-clone", + "description": "This extension provides [a/DiffBIR](https://github.com/XPixelGroup/DiffBIR) feature." + }, + { + "author": "ericbeyer", + "title": "guidance_interval", + "reference": "https://github.com/ericbeyer/guidance_interval", + "files": [ + "https://github.com/ericbeyer/guidance_interval" + ], + "install_type": "git-clone", + "description": "Nodes:Guidance Interval\nNOTE: Because the sampling function is replaced, you must restart after executing this custom node to restore the original state." + }, + { + "author": "GraftingRayman", + "title": "ComfyUI-GR", + "reference": "https://github.com/GraftingRayman/ComfyUI_GR_PromptSelector", + "files": [ + "https://github.com/GraftingRayman/ComfyUI_GR_PromptSelector" + ], + "install_type": "git-clone", + "description": "Nodes:GR Prompt Selector" + }, + { + "author": "oztrkoguz", + "title": "Kosmos2_BBox_Cutter Models", + "reference": "https://github.com/oztrkoguz/ComfyUI_Kosmos2_BBox_Cutter", + "files": [ + "https://github.com/oztrkoguz/ComfyUI_Kosmos2_BBox_Cutter" + ], + "install_type": "git-clone", + "description": "Nodes:KosmosLoader, Kosmos2SamplerSimple, Write" + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-PuLID-ZHO [WIP]", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PuLID-ZHO", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PuLID-ZHO" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/PuLID](https://github.com/ToTheBeginning/PuLID)(diffusers) for ComfyUI" + }, + { + "author": "longgui0318", + "title": "comfyui-one-more-step [WIP]", + "reference": "https://github.com/longgui0318/comfyui-one-more-step", + "files": [ + "https://github.com/longgui0318/comfyui-one-more-step" + ], + "install_type": "git-clone", + "description": "[a/(OMS)mhh0318/OneMoreStep](https://github.com/mhh0318/OneMoreStep) comfyui support ." + }, + { + "author": "unknown", + "title": "CLIPTextEncodeAndEnhancev4 (shirazdesigner)", + "reference": "https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4", + "files": [ + "https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4" + ], + "install_type": "git-clone", + "description": "Nodes:CLIPTextEncodeAndEnhance.\nNOTE:Translation:This is a wrapper that simply makes it easy to install an existing node via git." + }, + { + "author": "umisetokikaze", + "title": "comfyui_mergekit [WIP]", + "reference": "https://github.com/umisetokikaze/comfyui_mergekit", + "files": [ + "https://github.com/umisetokikaze/comfyui_mergekit" + ], + "install_type": "git-clone", + "description": "Nodes:DefineSaveName, SetModels, get_skip, LoadLR, LoadTarget, SetTokenizer, Merge, SetLayer, SetModels" + }, + { + "author": "Video3DGenResearch", + "title": "ComfyUI Batch Input Node", + "reference": "https://github.com/Video3DGenResearch/comfyui-batch-input-node", + "files": [ + "https://github.com/Video3DGenResearch/comfyui-batch-input-node" + ], + "install_type": "git-clone", + "description": "Nodes:BatchInputText" + }, + { + "author": "kijai", + "title": "ComfyUI nodes to use DeepSeek-VL", + "reference": "https://github.com/kijai/ComfyUI-DeepSeek-VL", + "files": [ + "https://github.com/kijai/ComfyUI-DeepSeek-VL" + ], + "install_type": "git-clone", + "description": "[a/https://huggingface.co/deepseek-ai](https://huggingface.co/deepseek-ai)" + }, + { + "author": "GentlemanHu", + "title": "ComfyUI-Notifier", + "reference": "https://github.com/GentlemanHu/ComfyUI-Notifier", + "files": [ + "https://github.com/GentlemanHu/ComfyUI-Notifier" + ], + "install_type": "git-clone", + "description": "Nodes:GentlemanHu_Notifier" + }, + { + "author": "nat-chan", + "title": "comfyui-in-memory-transceiver", + "reference": "https://github.com/nat-chan/comfyui-in-memory-transceiver", + "files": [ + "https://github.com/nat-chan/comfyui-in-memory-transceiver" + ], + "install_type": "git-clone", + "description": "Why? When processing a large number of requests, the SaveImage and LoadImage nodes may be IO-limited, and using shared memory improves performance by passing images only through memory access, not through IO." + }, + { + "author": "DrMWeigand", + "title": "ComfyUI_LineBreakInserter", + "reference": "https://github.com/DrMWeigand/ComfyUI_LineBreakInserter", + "files": [ + "https://github.com/DrMWeigand/ComfyUI_LineBreakInserter" + ], + "install_type": "git-clone", + "description": "Nodes:Line Break Inserter" + }, + { + "author": "WilliamStanford", + "title": "visuallabs_comfyui_nodes", + "reference": "https://github.com/WilliamStanford/visuallabs_comfyui_nodes", + "files": [ + "https://github.com/WilliamStanford/visuallabs_comfyui_nodes" + ], + "install_type": "git-clone", + "description": "Nodes:PointStringFromFloatArray" + }, + { + "author": "bruce007lee", + "title": "comfyui-cleaner", + "reference": "https://github.com/bruce007lee/comfyui-cleaner", + "files": [ + "https://github.com/bruce007lee/comfyui-cleaner" + ], + "install_type": "git-clone", + "description": "Nodes:cleaner" + }, + { + "author": "ExponentialML", + "title": "ComfyUI_LiveDirector (WIP)", + "reference": "https://github.com/ExponentialML/ComfyUI_LiveDirector", + "files": [ + "https://github.com/ExponentialML/ComfyUI_LiveDirector" + ], + "install_type": "git-clone", + "description": "Experimental method to use reference video to drive motion in generations without training in ComfyUI." + }, + { + "author": "logtd", + "title": "ComfyUI-MotionThiefExperiment", + "reference": "https://github.com/logtd/ComfyUI-MotionThiefExperiment", + "files": [ + "https://github.com/logtd/ComfyUI-MotionThiefExperiment" + ], + "install_type": "git-clone", + "description": "Nodes:This is an experimental node pack to test using reference videos for their motion.\nIt isn't compatible with a lot of things as this is a hacky implementation for experiments only." + }, + { + "author": "hy134300", + "title": "comfyui-hb-node", + "reference": "https://github.com/hy134300/comfyui-hb-node", + "files": [ + "https://github.com/hy134300/comfyui-hb-node" + ], + "install_type": "git-clone", + "description": "Nodes:sound voice, text concat, latent to list, movie generate, movie batch, hy save image, generate story" + }, + { + "author": "gameltb", + "title": "io_comfyui", + "reference": "https://github.com/gameltb/io_comfyui", + "files": [ + "https://github.com/gameltb/io_comfyui" + ], + "install_type": "git-clone", + "description": "Let Blender work with ComfyUI by ComfyScript. This addon is still in development." + }, + { + "author": "ALatentPlace", + "title": "YANC- Yet Another Node Collection", + "reference": "https://github.com/ALatentPlace/ComfyUI_yanc", + "files": [ + "https://github.com/ALatentPlace/ComfyUI_yanc" + ], + "install_type": "git-clone", + "description": "This is another node collection for ComfyUI. It includes some basic nodes that I find useful, and I've also created them to meet my personal needs." + }, + { + "author": "Jiffies-64", + "title": "ComfyUI-SaveImagePlus", + "reference": "https://github.com/Jiffies-64/ComfyUI-SaveImagePlus", + "files": [ + "https://github.com/Jiffies-64/ComfyUI-SaveImagePlus" + ], + "install_type": "git-clone", + "description": "Nodes:SaveImagePlus" + }, + { + "author": "kadirnar", + "title": "ComfyUI-Adapter [WIP]", + "reference": "https://github.com/kadirnar/ComfyUI-Adapter", + "files": [ + "https://github.com/kadirnar/ComfyUI-Adapter" + ], + "install_type": "git-clone", + "description": "WIP" + }, + { + "author": "Beinsezii", + "title": "comfyui-amd-go-fast", + "reference": "https://github.com/Beinsezii/comfyui-amd-go-fast", + "files": [ + "https://github.com/Beinsezii/comfyui-amd-go-fast" + ], + "install_type": "git-clone", + "description": "This contains all-in-one 'principled' nodes for T2I, I2I, refining, and scaling. Additionally it has many tools for directly manipulating the color of latents, high res fix math, and scripted image post-processing." + }, + { + "author": "sugarkwork", + "title": "comfyui_psd [WIP]", + "reference": "https://github.com/sugarkwork/comfyui_psd", + "files": [ + "https://github.com/sugarkwork/comfyui_psd" + ], + "install_type": "git-clone", + "description": "Not working yet." + }, + { + "author": "SadaleNet", + "title": "ComfyUI Port for Google's Prompt-to-Prompt", + "reference": "https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt", + "files": [ + "https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt" + ], + "install_type": "git-clone", + "description": "This is a PoC port of [a/Google's Prompt-to-Prompt](https://github.com/google/prompt-to-prompt/) to ComfyUI. It isn't feature complete. But it's good enough for evaluating if prompt-to-prompt is of any good." + }, + { + "author": "MushroomFleet", + "title": "DJZ-Nodes", + "reference": "https://github.com/MushroomFleet/DJZ-Nodes", + "files": [ + "https://github.com/MushroomFleet/DJZ-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Aspect Size. Drift Johnsons Custom nodes for ComfyUI" + }, + { + "author": "stavsap", + "title": "ComfyUI Ollama [WIP]", + "reference": "https://github.com/stavsap/ComfyUI-React-SDK", + "files": [ + "https://github.com/stavsap/ComfyUI-React-SDK" + ], + "install_type": "git-clone", + "description": "This project is for building React application as an overlay upon ComfyUI.\nProviding and ability to provide desired UI with ComfyUI API and workflows.\nInspired by: [a/https://github.com/cubiq/Comfy_Dungeon](https://github.com/cubiq/Comfy_Dungeon)" + }, + { + "author": "chaojie", + "title": "ComfyUI DynamiCrafter", + "reference": "https://github.com/chaojie/ComfyUI-DynamiCrafter", + "files": [ + "https://github.com/chaojie/ComfyUI-DynamiCrafter" + ], + "install_type": "git-clone", + "description": "ComfyUI [a/DynamiCrafter](https://github.com/Doubiiu/DynamiCrafter)" + }, + { + "author": "cubiq", + "title": "Comfy Dungeon [WIP]", + "reference": "https://github.com/cubiq/Comfy_Dungeon", + "files": [ + "https://github.com/cubiq/Comfy_Dungeon" + ], + "install_type": "git-clone", + "description": "Build D&D Character Portraits with ComfyUI.\nIMPORTANT: At the moment this is mostly a tech demo to show how to build a web app on top of ComfyUI. The code is very messy and the application doesn't guaratee consistent results." + }, + { + "author": "dfl", + "title": "comfyui-stylegan", + "reference": "https://github.com/dfl/comfyui-stylegan", + "files": [ + "https://github.com/dfl/comfyui-stylegan" + ], + "install_type": "git-clone", + "description": "Generator for StyleGAN 3" + }, + { + "author": "A719689614", + "title": "ComfyUI_AC_FUNV8Beta1", + "reference": "https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1", + "files": [ + "https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1" + ], + "install_type": "git-clone", + "description": "Nodes:AC_Super_Controlnet/Checkpoint/Loras/Lora&LCM/KSampler/UpKSampler/SaveImage/PreviewImage/CKPT&LCM/CLIPEN/EmptLatent, AC_FUN_SUPER_LARGE, AC_Super_Come_Ckpt, AC_Super_Come_Lora" + }, + { + "author": "houdinii", + "title": "comfy-magick [WIP]", + "reference": "https://github.com/houdinii/comfy-magick", + "files": [ + "https://github.com/houdinii/comfy-magick" + ], + "install_type": "git-clone", + "description": "This is a way to implement ImageMagick functionality in ComfyUI, which is generally PIL (pillow) based. I'm not sure the best way to handle this, as batch images make it a lot more complex, but the general idea will be two nodes to translate the IMAGE type, a torch.tensor of shape [batch, height, width, channels], or [1, 600, 800, 3] for a single 800x600 image, into/from a wand Image object." + }, + { + "author": "tjorbogarden", + "title": "my-useful-comfyui-custom-nodes", + "reference": "https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes", + "files": [ + "https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:My-Image Sizer, KSamplerSDXLAdvanced." + }, + { + "author": "DeTK", + "title": "ComfyUI Node Switcher", + "reference": "https://github.com/DeTK/ComfyUI-Switch", + "files": [ + "https://github.com/DeTK/ComfyUI-Switch" + ], + "install_type": "git-clone", + "description": "Nodes:NodeSwitch." + }, + { + "author": "GrindHouse66", + "title": "GH Tools for ComfyUI", + "reference": "https://github.com/GrindHouse66/ComfyUI-GH_Tools", + "files": [ + "https://github.com/GrindHouse66/ComfyUI-GH_Tools" + ], + "install_type": "git-clone", + "description": "Nodes:GH Tools Image Sizer, GH Tools Simple Scale. Simple quality of life Tools for ComfyUI. Basically, If it makes my life easier, it will be here. The list will grow over time." + }, + { + "author": "sdfxai", + "title": "SDFXBridgeForComfyUI - ComfyUI Custom Node for SDFX Integration", + "reference": "https://github.com/sdfxai/SDFXBridgeForComfyUI", + "files": [ + "https://github.com/sdfxai/SDFXBridgeForComfyUI" + ], + "install_type": "git-clone", + "description": "SDFXBridgeForComfyUI is a custom node designed for seamless integration between ComfyUI and the SDFX solution. This custom node allows users to make ComfyUI compatible with SDFX when running the ComfyUI instance on their local machines." + }, + { + "author": "Beinsezii", + "title": "comfyui-amd-go-fast", + "reference": "https://github.com/Beinsezii/comfyui-amd-go-fast", + "files": [ + "https://github.com/Beinsezii/comfyui-amd-go-fast" + ], + "install_type": "git-clone", + "description": "See details: [a/link](https://github.com/Beinsezii/comfyui-amd-go-fast?tab=readme-ov-file)" + }, + { + "author": "SeedV", + "title": "ComfyUI-SeedV-Nodes [UNSAFE]", + "reference": "https://github.com/SeedV/ComfyUI-SeedV-Nodes", + "files": [ + "https://github.com/SeedV/ComfyUI-SeedV-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Script.\n[w/This extension poses a risk of executing arbitrary commands through workflow execution. Please be cautious.]" + }, + { + "author": "mut-ex", + "title": "ComfyUI GLIGEN GUI Node", + "reference": "https://github.com/mut-ex/comfyui-gligengui-node", + "files": [ + "https://github.com/mut-ex/comfyui-gligengui-node" + ], + "install_type": "git-clone", + "description": "This is a simple, straightforward ComfyUI node to be used along with the [a/GLIGEN GUI](https://github.com/mut-ex/gligen-gui) I developed.\nNOTE:[a/Make sure you have the GLIGEN GUI up and running](https://github.com/mut-ex/gligen-gui/tree/main)" + }, + { + "author": "unanan", + "title": "ComfyUI-Dist [WIP]", + "reference": "https://github.com/unanan/ComfyUI-Dist", + "files": [ + "https://github.com/unanan/ComfyUI-Dist" + ], + "install_type": "git-clone", + "description": "For distributed processing ComfyUI workflows within a local area network.\nNot Finished Yet." + }, + { + "author": "NicholasKao1029", + "title": "comfyui-hook", + "reference": "https://github.com/NicholasKao1029/comfyui-hook", + "files": [ + "https://github.com/NicholasKao1029/comfyui-hook" + ], + "install_type": "git-clone", + "description": "This extension provides additional API" + }, + { + "author": "Extraltodeus", + "title": "Conditioning-token-experiments-for-ComfyUI", + "reference": "https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI", + "files": [ + "https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI" + ], + "install_type": "git-clone", + "description": "I made these nodes for experimenting so it's far from perfect but at least it is entertaining!\nIt uses cosine similarities or smallest euclidean distances to find the closest tokens." + }, + { + "author": "shadowcz007", + "title": "comfyui-llamafile [WIP]", + "reference": "https://github.com/shadowcz007/comfyui-llamafile", + "files": [ + "https://github.com/shadowcz007/comfyui-llamafile" + ], + "install_type": "git-clone", + "description": "This node is an experimental node aimed at exploring the collaborative way of human-machine creation." + }, + { + "author": "gameltb", + "title": "ComfyUI paper playground", + "reference": "https://github.com/gameltb/ComfyUI_paper_playground", + "files": [ + "https://github.com/gameltb/ComfyUI_paper_playground" + ], + "install_type": "git-clone", + "description": "Evaluate some papers in ComfyUI, just playground.\nNOTE: Various models need to be installed, so please visit the repository to check." + }, + { + "author": "huizhang0110", + "title": "ComfyUI_Easy_Nodes_hui", + "reference": "https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui", + "files": [ + "https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui" + ], + "install_type": "git-clone", + "description": "Nodes:EasyEmptyLatentImage" + }, + { + "author": "tuckerdarby", + "title": "ComfyUI-TDNodes [WIP]", + "reference": "https://github.com/tuckerdarby/ComfyUI-TDNodes", + "files": [ + "https://github.com/tuckerdarby/ComfyUI-TDNodes" + ], + "install_type": "git-clone", + "description": "Nodes:KSampler (RAVE), KSampler (TF), Object Tracker, KSampler Batched, Video Tracker Prompt, TemporalNet Preprocessor, Instance Tracker Prompt, Instance Diffusion Loader, Hand Tracker Node" + }, + { + "author": "shadowcz007", + "title": "comfyui-musicgen", + "reference": "https://github.com/shadowcz007/comfyui-musicgen", + "files": [ + "https://github.com/shadowcz007/comfyui-musicgen" + ], + "install_type": "git-clone", + "description": "Nodes:Musicgen" + }, + { + "author": "shadowcz007", + "title": "comfyui-CLIPSeg", + "reference": "https://github.com/shadowcz007/comfyui-CLIPSeg", + "files": [ + "https://github.com/shadowcz007/comfyui-CLIPSeg" + ], + "install_type": "git-clone", + "description": "Download [a/CLIPSeg](https://huggingface.co/CIDAS/clipseg-rd64-refined/tree/main), move to : models/clipseg" + }, + { + "author": "stutya", + "title": "ComfyUI-Terminal [UNSAFE]", + "reference": "https://github.com/stutya/ComfyUI-Terminal", + "files": [ + "https://github.com/stutya/ComfyUI-Terminal" + ], + "install_type": "git-clone", + "description": "Run Terminal Commands from ComfyUI.\n[w/This extension poses a risk of executing arbitrary commands through workflow execution. Please be cautious.]" + }, + { + "author": "marcueberall", + "title": "ComfyUI-BuildPath", + "reference": "https://github.com/marcueberall/ComfyUI-BuildPath", + "files": [ + "https://github.com/marcueberall/ComfyUI-BuildPath" + ], + "install_type": "git-clone", + "description": "Nodes: Build Path Adv." + }, + { + "author": "LotzF", + "title": "ComfyUI simple ChatGPT completion [UNSAFE]", + "reference": "https://github.com/LotzF/ComfyUI-Simple-Chat-GPT-completion", + "files": [ + "https://github.com/LotzF/ComfyUI-Simple-Chat-GPT-completion" + ], + "install_type": "git-clone", + "description": "A simple node to request ChatGPT completions. [w/Do not share your workflows including the API key! I'll take no responsibility for your leaked keys.]" + }, + { + "author": "kappa54m", + "title": "ComfyUI_Usability (WIP)", + "reference": "https://github.com/kappa54m/ComfyUI_Usability", + "files": [ + "https://github.com/kappa54m/ComfyUI_Usability" + ], + "install_type": "git-clone", + "description": "Nodes: Load Image Dedup, Load Image By Path." + }, + { + "author": "17Retoucher", + "title": "ComfyUI_Fooocus", + "reference": "https://github.com/17Retoucher/ComfyUI_Fooocus", + "files": [ + "https://github.com/17Retoucher/ComfyUI_Fooocus" + ], + "install_type": "git-clone", + "description": "Custom nodes that help reproduce image generation in Fooocus." + }, + { + "author": "nkchocoai", + "title": "ComfyUI-PromptUtilities", + "reference": "https://github.com/nkchocoai/ComfyUI-PromptUtilities", + "files": [ + "https://github.com/nkchocoai/ComfyUI-PromptUtilities" + ], + "install_type": "git-clone", + "description": "Nodes: Format String, Join String List, Load Preset, Load Preset (Advanced), Const String, Const String (multi line). Add useful nodes related to prompt." + }, + { + "author": "BadCafeCode", + "title": "execution-inversion-demo-comfyui", + "reference": "https://github.com/BadCafeCode/execution-inversion-demo-comfyui", + "files": [ + "https://github.com/BadCafeCode/execution-inversion-demo-comfyui" + ], + "install_type": "git-clone", + "description": "execution-inversion-demo-comfyui" + }, + { + "author": "unanan", + "title": "ComfyUI-clip-interrogator [WIP]", + "reference": "https://github.com/unanan/ComfyUI-clip-interrogator", + "files": [ + "https://github.com/unanan/ComfyUI-clip-interrogator" + ], + "install_type": "git-clone", + "description": "Unofficial ComfyUI extension of clip-interrogator" + }, + { + "author": "prismwastaken", + "title": "prism-tools", + "reference": "https://github.com/prismwastaken/comfyui-tools", + "files": [ + "https://github.com/prismwastaken/comfyui-tools" + ], + "install_type": "git-clone", + "description": "prism-tools" + }, + { + "author": "poisenbery", + "title": "NudeNet-Detector-Provider [WIP]", + "reference": "https://github.com/poisenbery/NudeNet-Detector-Provider", + "files": [ + "https://github.com/poisenbery/NudeNet-Detector-Provider" + ], + "install_type": "git-clone", + "description": "BBOX Detector Provider for NudeNet. Bethesda version of NudeNet V3 detector provider to work with Impact Pack ComfyUI." + }, + { + "author": "LarryJane491", + "title": "ComfyUI-ModelUnloader", + "reference": "https://github.com/LarryJane491/ComfyUI-ModelUnloader", + "files": [ + "https://github.com/LarryJane491/ComfyUI-ModelUnloader" + ], + "install_type": "git-clone", + "description": "A simple custom node that unloads all models. Useful for developers or users who want to free some memory." + }, + { + "author": "AIGODLIKE", + "title": "AIGODLIKE/ComfyUI-Model-Manager [WIP]", + "reference": "https://github.com/AIGODLIKE/ComfyUI-Studio", + "files": [ + "https://github.com/AIGODLIKE/ComfyUI-Studio" + ], + "install_type": "git-clone", + "description": "WIP" + }, + { + "author": "MrAdamBlack", + "title": "CheckProgress [WIP]", + "reference": "https://github.com/MrAdamBlack/CheckProgress", + "files": [ + "https://github.com/MrAdamBlack/CheckProgress" + ], + "install_type": "git-clone", + "description": "I was looking for a node to put in place to ensure my prompt etc where going as expected before the rest of the flow executed. To end the session, I just return the input image as None (see expected error). Recommend using it alongside PreviewImage, then output to the rest of the flow and Save Image." + }, + { + "author": "birnam", + "title": "Gen Data Tester [WIP]", + "reference": "https://github.com/birnam/ComfyUI-GenData-Pack", + "files": [ + "https://github.com/birnam/ComfyUI-GenData-Pack" + ], + "install_type": "git-clone", + "description": "This answers the itch for being able to easily paste [a/CivitAI.com](https://civitai.com/) generated data (or other simple metadata) into Comfy in a way that makes it easy to test with multiple checkpoints." + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "ComfyUI-AnyText [WIP]", + "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText", + "files": [ + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/AnyText](https://github.com/tyxsspa/AnyText/tree/825bcc54687206b15bd7e28ba1a8b095989d58e3) for ComfyUI(EXP)" + }, + { + "author": "nidefawl", + "title": "ComfyUI-nidefawl [UNSAFE]", + "reference": "https://github.com/nidefawl/ComfyUI-nidefawl", + "files": [ + "https://github.com/nidefawl/ComfyUI-nidefawl" + ], + "install_type": "git-clone", + "description": "Nodes:PythonScript, BlendImagesWithBoundedMasks, CropImagesWithMasks, VAELoaderDataType, ModelSamplerTonemapNoiseTest, gcLatentTunnel, ReferenceOnlySimple, EmptyImageWithColor, MaskFromColor, SetLatentCustomNoise, LatentToImage, ImageToLatent, LatentScaledNoise, DisplayAnyType, SamplerCustomCallback, CustomCallback, SplitCustomSigmas, SamplerDPMPP_2M_SDE_nidefawl, LatentPerlinNoise.
      [w/This node is an unsafe node that includes the capability to execute arbitrary python script.]" + }, + { + "author": "kadirnar", + "title": "comfyui_helpers", + "reference": "https://github.com/kadirnar/comfyui_helpers", + "files": [ + "https://github.com/kadirnar/comfyui_helpers" + ], + "install_type": "git-clone", + "description": "A collection of nodes randomly selected and gathered, related to noise. NOTE: SD-Advanced-Noise, noise_latent_perlinpinpin, comfy-plasma" + }, + { + "author": "foglerek", + "title": "comfyui-cem-tools", + "reference": "https://github.com/foglerek/comfyui-cem-tools", + "files": [ + "https://github.com/foglerek/comfyui-cem-tools" + ], + "install_type": "git-clone", + "description": "Nodes:ProcessImageBatch" + }, + { + "author": "komojini", + "title": "ComfyUI_Prompt_Template_CustomNodes", + "reference": "https://github.com/komojini/ComfyUI_Prompt_Template_CustomNodes", + "files": [ + "https://github.com/komojini/ComfyUI_Prompt_Template_CustomNodes/raw/main/prompt_with_template.py" + ], + "install_type": "copy", + "description": "Nodes:Prompt with Template" + }, + { + "author": "talesofai", + "title": "comfyui-supersave [WIP]", + "reference": "https://github.com/talesofai/comfyui-supersave", + "files": [ + "https://github.com/talesofai/comfyui-supersave" + ], + "install_type": "git-clone", + "description": "WIP" + }, + { + "author": "Sai-ComfyUI", + "title": "ComfyUI-MS-Nodes [WIP]", + "reference": "https://github.com/Sai-ComfyUI/ComfyUI-MS-Nodes", + "files": [ + "https://github.com/Sai-ComfyUI/ComfyUI-MS-Nodes" + ], + "install_type": "git-clone", + "description": "WIP" + }, + { + "author": "eigenpunk", + "title": "ComfyUI-audio", + "reference": "https://github.com/eigenpunk/ComfyUI-audio", + "files": [ + "https://github.com/eigenpunk/ComfyUI-audio" + ], + "install_type": "git-clone", + "description": "generative audio tools for ComfyUI. highly experimental-expect things to break." + }, + { + "author": "Jaxkr", + "title": "comfyui-terminal-command [UNSAFE]", + "reference": "https://github.com/Jaxkr/comfyui-terminal-command", + "files": [ + "https://github.com/Jaxkr/comfyui-terminal-command" + ], + "install_type": "git-clone", + "description": "Nodes: Run Terminal Command. [w/This node is an unsafe node that includes the capability to execute terminal commands.]" + }, + { + "author": "BlueDangerX", + "title": "ComfyUI-BDXNodes [WIP]", + "reference": "https://github.com/BlueDangerX/ComfyUI-BDXNodes", + "files": [ + "https://github.com/BlueDangerX/ComfyUI-BDXNodes" + ], + "install_type": "git-clone", + "description": "Nodes: Node Jumper. Various quality of life testing nodes" + }, + { + "author": "ilovejohnwhite", + "title": "TatToolkit", + "reference": "https://github.com/ilovejohnwhite/UncleBillyGoncho", + "files": [ + "https://github.com/ilovejohnwhite/UncleBillyGoncho" + ], + "install_type": "git-clone", + "description": "Nodes:UWU TTK Preprocessor, Pixel Perfect Resolution, Generation Resolution From Image, Generation Resolution From Latent, Enchance And Resize Hint Images, ..." + }, + { + "author": "IvanZhd", + "title": "comfyui-codeformer [WIP]", + "reference": "https://github.com/IvanZhd/comfyui-codeformer", + "files": [ + "https://github.com/IvanZhd/comfyui-codeformer" + ], + "install_type": "git-clone", + "description": "Nodes:Image Inverter" + }, + { + "author": "alt-key-project", + "title": "Dream Project Video Batches [WIP]", + "reference": "https://github.com/alt-key-project/comfyui-dream-video-batches", + "files": [ + "https://github.com/alt-key-project/comfyui-dream-video-batches" + ], + "install_type": "git-clone", + "description": "NOTE: This is currently work in progress. Expect nodes to break (or be broken) until 1.0 release." + }, + { + "author": "oyvindg", + "title": "ComfyUI-TrollSuite", + "reference": "https://github.com/oyvindg/ComfyUI-TrollSuite", + "files": [ + "https://github.com/oyvindg/ComfyUI-TrollSuite" + ], + "install_type": "git-clone", + "description": "Nodes: BinaryImageMask, ImagePadding, LoadLastCreatedImage, RandomMask, TransparentImage." + }, + { + "author": "romeobuilderotti", + "title": "ComfyUI-EZ-Pipes", + "reference": "https://github.com/romeobuilderotti/ComfyUI-EZ-Pipes", + "files": [ + "https://github.com/romeobuilderotti/ComfyUI-EZ-Pipes" + ], + "install_type": "git-clone", + "description": "ComfyUI-EZ-Pipes is a set of custom pipe nodes for ComfyUI. It provides a set of Input/Edit/Output nodes for each pipe type." + }, + { + "author": "wormley", + "title": "comfyui-wormley-nodes", + "reference": "https://github.com/wormley/comfyui-wormley-nodes", + "files": [ + "https://github.com/wormley/comfyui-wormley-nodes" + ], + "install_type": "git-clone", + "description": "Nodes: CheckpointVAELoaderSimpleText, CheckpointVAESelectorText, LoRA_Tag_To_Stack" + }, + { + "author": "dnl13", + "title": "ComfyUI-dnl13-seg", + "reference": "https://github.com/dnl13/ComfyUI-dnl13-seg", + "files": [ + "https://github.com/dnl13/ComfyUI-dnl13-seg" + ], + "install_type": "git-clone", + "description": "After discovering @storyicon implementation here of Segment Anything, I realized its potential as a powerful tool for ComfyUI if implemented correctly. I delved into the SAM and Dino models. The following is my own adaptation of sam_hq for ComfyUI." + }, + { + "author": "Brandelan", + "title": "ComfyUI_bd_customNodes", + "reference": "https://github.com/Brandelan/ComfyUI_bd_customNodes", + "files": [ + "https://github.com/Brandelan/ComfyUI_bd_customNodes" + ], + "install_type": "git-clone", + "description": "Nodes: BD Random Range, BD Settings, BD Sequencer." + }, + { + "author": "Jordach", + "title": "comfy-consistency-vae", + "reference": "https://github.com/Jordach/comfy-consistency-vae", + "files": [ + "https://github.com/Jordach/comfy-consistency-vae" + ], + "install_type": "git-clone", + "description": "Nodes: Comfy_ConsistencyVAE" + }, + { + "author": "gameltb", + "title": "ComfyUI_stable_fast", + "reference": "https://github.com/gameltb/ComfyUI_stable_fast", + "files": [ + "https://github.com/gameltb/ComfyUI_stable_fast" + ], + "install_type": "git-clone", + "description": "Nodes:ApplyStableFastUnet. Experimental usage of stable-fast." + }, + { + "author": "jn-jairo", + "title": "jn_node_suite_comfyui [WIP]", + "reference": "https://github.com/jn-jairo/jn_node_suite_comfyui", + "files": [ + "https://github.com/jn-jairo/jn_node_suite_comfyui" + ], + "install_type": "git-clone", + "description": "Image manipulation nodes, Temperature control nodes, Tiling nodes, Primitive and operation nodes, ..." + }, + { + "author": "PluMaZero", + "title": "ComfyUI-SpaceFlower", + "reference": "https://github.com/PluMaZero/ComfyUI-SpaceFlower", + "files": [ + "https://github.com/PluMaZero/ComfyUI-SpaceFlower" + ], + "install_type": "git-clone", + "description": "Nodes: SpaceFlower_Prompt, SpaceFlower_HangulPrompt, ..." + }, + { + "author": "laksjdjf", + "title": "ssd-1b-comfyui", + "reference": "https://github.com/laksjdjf/ssd-1b-comfyui", + "files": [ + "https://github.com/laksjdjf/ssd-1b-comfyui" + ], + "install_type": "git-clone", + "description": "Experimental node for SSD-1B. This node is not need for latest comfyui." + }, + { + "author": "flowtyone", + "title": "comfyui-flowty-lcm", + "reference": "https://github.com/flowtyone/comfyui-flowty-lcm", + "files": [ + "https://github.com/flowtyone/comfyui-flowty-lcm" + ], + "install_type": "git-clone", + "description": "This is a comfyui early testing node for LCM, adapted from [a/https://github.com/0xbitches/sd-webui-lcm](https://github.com/0xbitches/sd-webui-lcm). It uses the diffusers backend unfortunately and not comfy's model loading mechanism. But the intention here is just to be able to execute lcm inside comfy.\nNOTE: 0xbitches's 'Latent Consistency Model for ComfyUI' is original implementation." + }, + { + "author": "doucx", + "title": "ComfyUI_WcpD_Utility_Kit", + "reference": "https://github.com/doucx/ComfyUI_WcpD_Utility_Kit", + "files": [ + "https://github.com/doucx/ComfyUI_WcpD_Utility_Kit" + ], + "install_type": "git-clone", + "description": "Nodes: MergeStrings, ExecStrAsCode, RandnLatentImage. [w/NOTE: This extension includes the ability to execute code as a string in nodes. Be cautious during installation, as it can pose a security risk.]" + }, + { + "author": "WSJUSA", + "title": "pre-comfyui-stablsr", + "reference": "https://github.com/WSJUSA/Comfyui-StableSR", + "files": [ + "https://github.com/WSJUSA/Comfyui-StableSR" + ], + "install_type": "git-clone", + "description": "This is a development respository for debugging migration of StableSR to Comfyui" + }, + { + "author": "Dr.Lt.Data", + "title": "ComfyUI-Workflow-Component [WIP]", + "reference": "https://github.com/ltdrdata/ComfyUI-Workflow-Component", + "files": [ + "https://github.com/ltdrdata/ComfyUI-Workflow-Component" + ], + "install_type": "git-clone", + "description": "This extension provides the capability to use ComfyUI Workflow as a component and the ability to use the Image Refiner functionality based on components. NOTE: This is an experimental extension feature with no consideration for backward compatibility and can be highly unstable." + } + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/dev/extension-node-map.json b/custom_nodes/ComfyUI-Manager/node_db/dev/extension-node-map.json new file mode 100644 index 000000000..b6f2a587d --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/dev/extension-node-map.json @@ -0,0 +1,2119 @@ +{ + "https://github.com/17Retoucher/ComfyUI_Fooocus": [ + [ + "BasicScheduler", + "CLIPLoader", + "CLIPMergeSimple", + "CLIPSave", + "CLIPSetLastLayer", + "CLIPTextEncode", + "CLIPTextEncodeSDXL", + "CLIPTextEncodeSDXLRefiner", + "CLIPVisionEncode", + "CLIPVisionLoader", + "Canny", + "CheckpointLoader", + "CheckpointLoaderSimple", + "CheckpointSave", + "ConditioningAverage", + "ConditioningCombine", + "ConditioningConcat", + "ConditioningSetArea", + "ConditioningSetAreaPercentage", + "ConditioningSetMask", + "ConditioningSetTimestepRange", + "ConditioningZeroOut", + "ControlNetApply", + "ControlNetApplyAdvanced", + "ControlNetLoader", + "CropMask", + "DiffControlNetLoader", + "DiffusersLoader", + "DualCLIPLoader", + "EmptyImage", + "EmptyLatentImage", + "ExponentialScheduler", + "FeatherMask", + "FlipSigmas", + "Fooocus Controlnet", + "Fooocus Hirefix", + "Fooocus KSampler", + "Fooocus Loader", + "Fooocus LoraStack", + "Fooocus PreKSampler", + "Fooocus negative", + "Fooocus positive", + "Fooocus stylesSelector", + "FreeU", + "FreeU_V2", + "GLIGENLoader", + "GLIGENTextBoxApply", + "GrowMask", + "HyperTile", + "HypernetworkLoader", + "ImageBatch", + "ImageBlend", + "ImageBlur", + "ImageColorToMask", + "ImageCompositeMasked", + "ImageCrop", + "ImageInvert", + "ImageOnlyCheckpointLoader", + "ImagePadForOutpaint", + "ImageQuantize", + "ImageScale", + "ImageScaleBy", + "ImageScaleToTotalPixels", + "ImageSharpen", + "ImageToMask", + "ImageUpscaleWithModel", + "InvertMask", + "JoinImageWithAlpha", + "KSampler", + "KSamplerAdvanced", + "KSamplerSelect", + "KarrasScheduler", + "LatentAdd", + "LatentBatch", + "LatentBlend", + "LatentComposite", + "LatentCompositeMasked", + "LatentCrop", + "LatentFlip", + "LatentFromBatch", + "LatentInterpolate", + "LatentMultiply", + "LatentRotate", + "LatentSubtract", + "LatentUpscale", + "LatentUpscaleBy", + "LoadImage", + "LoadImageMask", + "LoadLatent", + "LoraLoader", + "LoraLoaderModelOnly", + "MaskComposite", + "MaskToImage", + "ModelMergeAdd", + "ModelMergeBlocks", + "ModelMergeSimple", + "ModelMergeSubtract", + "ModelSamplingContinuousEDM", + "ModelSamplingDiscrete", + "PatchModelAddDownscale", + "PerpNeg", + "PolyexponentialScheduler", + "PorterDuffImageComposite", + "PreviewImage", + "RebatchImages", + "RebatchLatents", + "RepeatImageBatch", + "RepeatLatentBatch", + "RescaleCFG", + "SDTurboScheduler", + "SVD_img2vid_Conditioning", + "SamplerCustom", + "SamplerDPMPP_2M_SDE", + "SamplerDPMPP_SDE", + "SaveAnimatedPNG", + "SaveAnimatedWEBP", + "SaveImage", + "SaveLatent", + "SelfAttentionGuidance", + "SetLatentNoiseMask", + "SolidMask", + "SplitImageWithAlpha", + "SplitSigmas", + "StableZero123_Conditioning", + "StyleModelApply", + "StyleModelLoader", + "TomePatchModel", + "UNETLoader", + "UpscaleModelLoader", + "VAEDecode", + "VAEDecodeTiled", + "VAEEncode", + "VAEEncodeForInpaint", + "VAEEncodeTiled", + "VAELoader", + "VAESave", + "VPScheduler", + "VideoLinearCFGGuidance", + "unCLIPCheckpointLoader", + "unCLIPConditioning" + ], + { + "title_aux": "ComfyUI_Fooocus" + } + ], + "https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1": [ + [ + "\u2b1b(TODO)AC_Super_Come_Ckpt", + "\u2b1c(TODO)AC_Super_Come_Lora", + "\u2b55AC_FUN_SUPER_LARGE", + "\ud83c\ude35AC_Super_Checkpoint", + "\ud83c\ude35AC_Super_Loras", + "\ud83c\udfabAC_Super_PreviewImage", + "\ud83c\udfb0AC_Super_Controlnet", + "\ud83d\udcb6AC_Super_EmptLatent", + "\ud83d\udcbcAC_Super_Lora&LCM", + "\ud83d\udcbeAC_Super_SaveImage", + "\ud83d\udcc4AC_Super_CLIPEN", + "\ud83d\udcc8AC_Super_UpKSampler", + "\ud83d\udcdfAC_Super_CKPT&LCM", + "\ud83d\ude80AC_Super_KSampler" + ], + { + "title_aux": "ComfyUI_AC_FUNV8Beta1" + } + ], + "https://github.com/ALatentPlace/ComfyUI_yanc": [ + [ + "> Clear Text", + "> Float to Int", + "> Get Mean Color", + "> Int", + "> Int to Text", + "> Light Source Mask", + "> Load Image", + "> Load Image From Folder", + "> Mask Curves", + "> NIKSampler", + "> Noise From Image", + "> Normal Map Lighting", + "> RGB Color", + "> Resolution by Aspect Ratio", + "> Rotate Image", + "> Save Image", + "> Scale Image to Side", + "> Text", + "> Text Combine", + "> Text Pick Random Line", + "> Text Random Weights", + "> Text Replace" + ], + { + "title_aux": "YANC- Yet Another Node Collection" + } + ], + "https://github.com/AllenEdgarPoe/ComfyUI-Xorbis-nodes": [ + [ + "Add Human Styler", + "Save Log Info" + ], + { + "title_aux": "ComfyUI-Xorbis-nodes" + } + ], + "https://github.com/BadCafeCode/execution-inversion-demo-comfyui": [ + [ + "AccumulateNode", + "AccumulationGetItemNode", + "AccumulationGetLengthNode", + "AccumulationHeadNode", + "AccumulationSetItemNode", + "AccumulationTailNode", + "AccumulationToListNode", + "BoolOperationNode", + "ComponentInput", + "ComponentMetadata", + "ComponentOutput", + "DebugPrint", + "ExecutionBlocker", + "FloatConditions", + "ForLoopClose", + "ForLoopOpen", + "IntConditions", + "IntMathOperation", + "InversionDemoAdvancedPromptNode", + "InversionDemoFakeAdvancedPromptNode", + "InversionDemoLazyConditional", + "InversionDemoLazyIndexSwitch", + "InversionDemoLazyMixImages", + "InversionDemoLazySwitch", + "ListToAccumulationNode", + "MakeListNode", + "StringConditions", + "ToBoolNode", + "WhileLoopClose", + "WhileLoopOpen" + ], + { + "title_aux": "execution-inversion-demo-comfyui" + } + ], + "https://github.com/BlueDangerX/ComfyUI-BDXNodes": [ + [ + "BDXTestInt", + "ColorMatch", + "ColorToMask", + "ConditioningMultiCombine", + "ConditioningSetMaskAndCombine", + "ConditioningSetMaskAndCombine3", + "ConditioningSetMaskAndCombine4", + "ConditioningSetMaskAndCombine5", + "CreateAudioMask", + "CreateFadeMask", + "CreateFluidMask", + "CreateGradientMask", + "CreateTextMask", + "CrossFadeImages", + "EmptyLatentImagePresets", + "GrowMaskWithBlur", + "SomethingToString", + "VRAM_Debug" + ], + { + "author": "BlueDangerX", + "title": "BDXNodes", + "title_aux": "ComfyUI-BDXNodes [WIP]" + } + ], + "https://github.com/Brandelan/ComfyUI_bd_customNodes": [ + [ + "BD Random Range", + "BD Random Settings", + "BD Sequencer", + "BD Settings" + ], + { + "title_aux": "ComfyUI_bd_customNodes" + } + ], + "https://github.com/DeTK/ComfyUI-Switch": [ + [ + "NodeSwitch" + ], + { + "title_aux": "ComfyUI Node Switcher" + } + ], + "https://github.com/DrMWeigand/ComfyUI_LineBreakInserter": [ + [ + "LineBreakInserter" + ], + { + "title_aux": "ComfyUI_LineBreakInserter" + } + ], + "https://github.com/Elawphant/ComfyUI-MusicGen": [ + [ + "AudioLoader", + "MusicGen" + ], + { + "title_aux": "ComfyUI-MusicGen [WIP]" + } + ], + "https://github.com/ExponentialML/ComfyUI_LiveDirector": [ + [ + "LiveDirector" + ], + { + "title_aux": "ComfyUI_LiveDirector (WIP)" + } + ], + "https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI": [ + [ + "Automatic wildcards", + "Conditioning (Cosine similarities)", + "Conditioning (Maximum absolute)", + "Conditioning (Maximum absolute) text inputs", + "Conditioning (Scale by absolute sum)", + "Conditioning merge clip g/l", + "Conditioning similar tokens recombine", + "Conditioning to text", + "Quick and dirty text encode", + "encode_all_tokens_SDXL" + ], + { + "title_aux": "Conditioning-token-experiments-for-ComfyUI" + } + ], + "https://github.com/GentlemanHu/ComfyUI-Notifier": [ + [ + "GentlemanHu_Notifier" + ], + { + "title_aux": "ComfyUI-Notifier" + } + ], + "https://github.com/GraftingRayman/ComfyUI_GR_PromptSelector": [ + [ + "GR Checkered Board", + "GR Flip Tile Random Inverted", + "GR Flip Tile Random Red Ring", + "GR Image Details Displayer", + "GR Image Details Saver", + "GR Image Resize", + "GR Image Resize Methods", + "GR Image Size", + "GR Image/Depth Mask", + "GR Mask Create", + "GR Mask Create Random", + "GR Mask Resize", + "GR Multi Mask Create", + "GR Onomatopoeia", + "GR Prompt Selector", + "GR Prompt Selector Multi", + "GR Stack Image", + "GR Text Overlay", + "GR Tile and Border Image", + "GR Tile and Border Image Random Flip" + ], + { + "title_aux": "ComfyUI-GR" + } + ], + "https://github.com/GrindHouse66/ComfyUI-GH_Tools": [ + [ + "GHImg_Sizer", + "GHSimple_Scale" + ], + { + "title_aux": "GH Tools for ComfyUI" + } + ], + "https://github.com/IvanZhd/comfyui-codeformer": [ + [ + "RedBeanie_CustomImageInverter" + ], + { + "title_aux": "comfyui-codeformer [WIP]" + } + ], + "https://github.com/Jaxkr/comfyui-terminal-command": [ + [ + "Terminal" + ], + { + "title_aux": "comfyui-terminal-command [UNSAFE]" + } + ], + "https://github.com/Jiffies-64/ComfyUI-SaveImagePlus": [ + [ + "SaveImagePlus" + ], + { + "title_aux": "ComfyUI-SaveImagePlus" + } + ], + "https://github.com/Jordach/comfy-consistency-vae": [ + [ + "Comfy_ConsistencyVAE" + ], + { + "title_aux": "comfy-consistency-vae" + } + ], + "https://github.com/LZpenguin/ComfyUI-Text": [ + [ + "Add_text_by_mask" + ], + { + "title_aux": "ComfyUI-Text" + } + ], + "https://github.com/LarryJane491/ComfyUI-ModelUnloader": [ + [ + "Model Unloader" + ], + { + "title_aux": "ComfyUI-ModelUnloader" + } + ], + "https://github.com/LotzF/ComfyUI-Simple-Chat-GPT-completion": [ + [ + "ChatGPTCompletion" + ], + { + "title_aux": "ComfyUI simple ChatGPT completion [UNSAFE]" + } + ], + "https://github.com/LykosAI/ComfyUI-Inference-Core-Nodes": [ + [ + "AIO_Preprocessor", + "AnimalPosePreprocessor", + "AnimeFace_SemSegPreprocessor", + "AnimeLineArtPreprocessor", + "BAE-NormalMapPreprocessor", + "BinaryPreprocessor", + "CannyEdgePreprocessor", + "ColorPreprocessor", + "DWPreprocessor", + "DensePosePreprocessor", + "DepthAnythingPreprocessor", + "DiffusionEdge_Preprocessor", + "FacialPartColoringFromPoseKps", + "FakeScribblePreprocessor", + "HEDPreprocessor", + "HintImageEnchance", + "ImageGenResolutionFromImage", + "ImageGenResolutionFromLatent", + "ImageIntensityDetector", + "ImageLuminanceDetector", + "InpaintPreprocessor", + "LayeredDiffusionApply", + "LayeredDiffusionCondApply", + "LayeredDiffusionCondJointApply", + "LayeredDiffusionDecode", + "LayeredDiffusionDecodeRGBA", + "LayeredDiffusionDecodeSplit", + "LayeredDiffusionDiffApply", + "LayeredDiffusionJointApply", + "LeReS-DepthMapPreprocessor", + "LineArtPreprocessor", + "LineartStandardPreprocessor", + "M-LSDPreprocessor", + "Manga2Anime_LineArt_Preprocessor", + "MaskOptFlow", + "MediaPipe-FaceMeshPreprocessor", + "MeshGraphormer-DepthMapPreprocessor", + "MiDaS-DepthMapPreprocessor", + "MiDaS-NormalMapPreprocessor", + "ModelMergeBlockNumber", + "ModelMergeSDXL", + "ModelMergeSDXLDetailedTransformers", + "ModelMergeSDXLTransformers", + "ModelSamplerTonemapNoiseTest", + "OneFormer-ADE20K-SemSegPreprocessor", + "OneFormer-COCO-SemSegPreprocessor", + "OpenposePreprocessor", + "PiDiNetPreprocessor", + "PixelPerfectResolution", + "PromptExpansion", + "ReferenceOnlySimple", + "RescaleClassifierFreeGuidanceTest", + "SAMPreprocessor", + "SavePoseKpsAsJsonFile", + "ScribblePreprocessor", + "Scribble_XDoG_Preprocessor", + "SemSegPreprocessor", + "ShufflePreprocessor", + "TEEDPreprocessor", + "TilePreprocessor", + "TonemapNoiseWithRescaleCFG", + "UniFormer-SemSegPreprocessor", + "Unimatch_OptFlowPreprocessor", + "Zoe-DepthMapPreprocessor", + "Zoe_DepthAnythingPreprocessor" + ], + { + "author": "tstandley", + "title_aux": "ComfyUI Nodes for Inference.Core" + } + ], + "https://github.com/MrAdamBlack/CheckProgress": [ + [ + "CHECK_PROGRESS" + ], + { + "title_aux": "CheckProgress [WIP]" + } + ], + "https://github.com/MushroomFleet/DJZ-Nodes": [ + [ + "AspectSize" + ], + { + "title_aux": "DJZ-Nodes" + } + ], + "https://github.com/NeuralNotW0rk/ComfyUI-Waveform-Extensions/raw/main/EXT_VariationUtils.py": [ + [ + "BatchToList", + "ConcatAudioList", + "SequenceVariation", + "SliceAudio" + ], + { + "title_aux": "ComfyUI-Waveform-Extensions" + } + ], + "https://github.com/NitramDom/ComfyUI_FacialFlip": [ + [ + "Swapper" + ], + { + "title_aux": "ComfyUI_FacialFlip" + } + ], + "https://github.com/PluMaZero/ComfyUI-SpaceFlower": [ + [ + "SpaceFlower_HangulPrompt", + "SpaceFlower_Prompt" + ], + { + "title_aux": "ComfyUI-SpaceFlower" + } + ], + "https://github.com/Quasimondo/ComfyUI-QuasimondoNodes": [ + [ + "CPPN Generator", + "Color Match", + "Custom Shader", + "Folder Queue Manager", + "Image Blend by Mask (Batch)", + "Image Noise Generator", + "Perlin Noise Generator", + "Random Image Generator", + "Spring Mesh", + "Video Queue Manager" + ], + { + "title_aux": "ComfyUI-QuasimondoNodes [WIP]" + } + ], + "https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt": [ + [ + "CLIPTextEncodePromptToPrompt", + "KSamplerPromptToPrompt", + "KSamplerPromptToPromptAttentionMapLogger", + "LocalBlendLayerPresetPromptToPrompt" + ], + { + "title_aux": "ComfyUI Port for Google's Prompt-to-Prompt" + } + ], + "https://github.com/Sai-ComfyUI/ComfyUI-MS-Nodes": [ + [ + "FloatMath", + "MS_Boolean", + "MS_Float", + "MS_GenerateSeed", + "MS_NP_Vector3", + "PowerFractalCrossHatchNode", + "PowerFractalNoiseNode", + "VectorMath" + ], + { + "title_aux": "ComfyUI-MS-Nodes [WIP]" + } + ], + "https://github.com/Scorpinaus/ComfyUI-DiffusersLoader": [ + [ + "CombinedDiffusersLoader", + "DiffusersClipLoader", + "DiffusersUNETLoader", + "DiffusersVAELoader" + ], + { + "title_aux": "ComfyUI-DiffusersLoader" + } + ], + "https://github.com/SeedV/ComfyUI-SeedV-Nodes": [ + [ + "CheckpointLoaderSimpleShared //SeedV", + "ControlNetLoaderAdvancedShared", + "LoraLoader //SeedV", + "Script" + ], + { + "title_aux": "ComfyUI-SeedV-Nodes [UNSAFE]" + } + ], + "https://github.com/Shinsplat/ComfyUI-Shinsplat": [ + [ + "Clip Text Encode (Shinsplat)", + "Clip Text Encode SD3 (Shinsplat)", + "Clip Text Encode SDXL (Shinsplat)", + "Clip Text Encode T5 (Shinsplat)", + "Clip Tokens Encode (Shinsplat)", + "Green Box (Shinsplat)", + "Hex To Other (Shinsplat)", + "Lora Loader (Shinsplat)", + "Python (Shinsplat)", + "Python - More Inputs (Shinsplat)", + "String Interpolated (Shinsplat)", + "Sum Wrap (Shinsplat)", + "Test Node (Shinsplat)", + "Text To Tokens (Shinsplat)", + "Variables (Shinsplat)" + ], + { + "author": "Shinsplat", + "description": "", + "nickname": "shinsplat", + "title": "ComfyUI-Shinsplat", + "title_aux": "ComfyUI-Shinsplat [UNSAFE]" + } + ], + "https://github.com/StartHua/Comfyui_CXH_CRM": [ + [ + "CRM" + ], + { + "title_aux": "Comfyui_CXH_CRM" + } + ], + "https://github.com/TSFSean/ComfyUI-TSFNodes": [ + [ + "GyroOSC" + ], + { + "title_aux": "ComfyUI-TSFNodes" + } + ], + "https://github.com/Video3DGenResearch/comfyui-batch-input-node": [ + [ + "BatchImageAndPrompt", + "BatchInputCSV", + "BatchInputText" + ], + { + "title_aux": "ComfyUI Batch Input Node" + } + ], + "https://github.com/WSJUSA/Comfyui-StableSR": [ + [ + "ColorFix", + "StableSRUpscalerPipe" + ], + { + "author": "WSJUSA", + "description": "This module enables StableSR in Comgfyui. Ported work of sd-webui-stablesr. Original work for Auotmaatic1111 version of this module and StableSR credit to LIightChaser and Jianyi Wang.", + "nickname": "StableSR", + "title": "StableSR", + "title_aux": "pre-comfyui-stablsr" + } + ], + "https://github.com/WilliamStanford/visuallabs_comfyui_nodes": [ + [ + "CreateFadeMaskAdvancedVL", + "PointStringFromFloatArray", + "RescaleFloatArray", + "StringFromFloatArray" + ], + { + "title_aux": "visuallabs_comfyui_nodes" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText": [ + [ + "AnyTextNode_Zho" + ], + { + "title_aux": "ComfyUI-AnyText [WIP]" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PuLID-ZHO": [ + [ + "PuLID_Zho" + ], + { + "title_aux": "ComfyUI-PuLID-ZHO [WIP]" + } + ], + "https://github.com/alt-key-project/comfyui-dream-video-batches": [ + [ + "Blended Transition [DVB]", + "Calculation [DVB]", + "Create Frame Set [DVB]", + "Divide [DVB]", + "Fade From Black [DVB]", + "Fade To Black [DVB]", + "Float Input [DVB]", + "For Each Done [DVB]", + "For Each Filename [DVB]", + "Frame Set Append [DVB]", + "Frame Set Frame Dimensions Scaled [DVB]", + "Frame Set Index Offset [DVB]", + "Frame Set Merger [DVB]", + "Frame Set Reindex [DVB]", + "Frame Set Repeat [DVB]", + "Frame Set Reverse [DVB]", + "Frame Set Split Beginning [DVB]", + "Frame Set Split End [DVB]", + "Frame Set Splitter [DVB]", + "Generate Inbetween Frames [DVB]", + "Int Input [DVB]", + "Linear Camera Pan [DVB]", + "Linear Camera Roll [DVB]", + "Linear Camera Zoom [DVB]", + "Load Image From Path [DVB]", + "Multiply [DVB]", + "Sine Camera Pan [DVB]", + "Sine Camera Roll [DVB]", + "Sine Camera Zoom [DVB]", + "String Input [DVB]", + "Text Input [DVB]", + "Trace Memory Allocation [DVB]", + "Unwrap Frame Set [DVB]" + ], + { + "title_aux": "Dream Project Video Batches [WIP]" + } + ], + "https://github.com/baicai99/ComfyUI-FrameSkipping": [ + [ + "FrameSelector", + "FrameSkipping", + "FrameTruncating", + "IntOperationsNode", + "MaskFrameSkipping", + "MaskGenerator", + "MaskSelector" + ], + { + "title_aux": "ComfyUI-FrameSkipping" + } + ], + "https://github.com/beyastard/ComfyUI_BeySoft": [ + [ + "BeySoft" + ], + { + "title_aux": "ComfyUI_BeySoft" + } + ], + "https://github.com/birnam/ComfyUI-GenData-Pack": [ + [ + "Checkpoint From String \ud83d\udc69\u200d\ud83d\udcbb", + "Checkpoint Rerouter \ud83d\udc69\u200d\ud83d\udcbb", + "Checkpoint Selector Stacker \ud83d\udc69\u200d\ud83d\udcbb", + "Checkpoint Selector \ud83d\udc69\u200d\ud83d\udcbb", + "Checkpoint to String \ud83d\udc69\u200d\ud83d\udcbb", + "Crop Recombine \ud83d\udc69\u200d\ud83d\udcbb", + "Crop|IP|Inpaint \ud83d\udc69\u200d\ud83d\udcbb", + "Crop|IP|Inpaint|SDXL \ud83d\udc69\u200d\ud83d\udcbb", + "Decode GenData \ud83d\udc69\u200d\ud83d\udcbb", + "Encode GenData \ud83d\udc69\u200d\ud83d\udcbb", + "GenData Stacker \ud83d\udc69\u200d\ud83d\udcbb", + "IPAdapterApply", + "IPAdapterApplyEncoded", + "IPAdapterApplyFaceID", + "IPAdapterBatchEmbeds", + "IPAdapterEncoder", + "IPAdapterLoadEmbeds", + "IPAdapterModelLoader", + "IPAdapterSaveEmbeds", + "IPAdapterTilesMasked", + "InsightFaceLoader", + "LoRA Stack to String \ud83d\udc69\u200d\ud83d\udcbb", + "LoRA Stacker From Prompt \ud83d\udc69\u200d\ud83d\udcbb", + "Load Checkpoints From File \ud83d\udc69\u200d\ud83d\udcbb", + "Load GenData From Dir \ud83d\udc69\u200d\ud83d\udcbb", + "Parse GenData \ud83d\udc69\u200d\ud83d\udcbb", + "PrepImageForClipVision", + "PrepImageForInsightFace", + "Provide GenData \ud83d\udc69\u200d\ud83d\udcbb", + "Save Image From GenData \ud83d\udc69\u200d\ud83d\udcbb", + "VAE From String \ud83d\udc69\u200d\ud83d\udcbb", + "VAE to String \ud83d\udc69\u200d\ud83d\udcbb", + "\u00d7 Product CheckpointXGenDatas \ud83d\udc69\u200d\ud83d\udcbb" + ], + { + "title_aux": "Gen Data Tester [WIP]" + } + ], + "https://github.com/blepping/comfyui_overly_complicated_sampling": [ + [ + "ComposableSampler", + "ComposableStepSampler" + ], + { + "title_aux": "comfyui_overly_complicated_sampling" + } + ], + "https://github.com/bruce007lee/comfyui-cleaner": [ + [ + "cleaner" + ], + { + "title_aux": "comfyui-cleaner" + } + ], + "https://github.com/bruce007lee/comfyui-tiny-utils": [ + [ + "CropImageByMask", + "FaceAlign", + "FaceAlignImageProcess", + "FaceAlignMaskProcess", + "ImageFillColorByMask" + ], + { + "title_aux": "comfyui-tiny-utils" + } + ], + "https://github.com/brycegoh/comfyui-custom-nodes": [ + [ + "CombineTwoImageIntoOne", + "FillMaskedArea", + "MaskAreaComparisonSegment", + "OCRAndMask" + ], + { + "title_aux": "brycegoh/comfyui-custom-nodes" + } + ], + "https://github.com/chaojie/ComfyUI-DynamiCrafter": [ + [ + "DynamiCrafter Simple", + "DynamiCrafterInterp Simple", + "DynamiCrafterInterpLoader", + "DynamiCrafterLoader" + ], + { + "title_aux": "ComfyUI DynamiCrafter" + } + ], + "https://github.com/chaojie/ComfyUI-mobvoi-openapi": [ + [ + "HtmlViewer", + "MobvoiOpenapiMetamanAudio", + "MobvoiOpenapiMetamanText", + "MobvoiOpenapiTts", + "OssUploadAudio", + "OssUploadImage" + ], + { + "title_aux": "ComfyUI-mobvoi-openapi" + } + ], + "https://github.com/christian-byrne/infinite-zoom-parallax-nodes": [ + [ + "Create Parallax Video", + "Layer Shifter for Parallax Outpainting", + "Load Most Recent Image in Folder", + "Load Parallax Frame", + "Load Random Image-Pose Pair", + "Parallax Config", + "Save Parallax Frame", + "Shrink and Pad for Outpainting" + ], + { + "title_aux": "\ud83c\udf0c Infinite Parallax Nodes [WIP]" + } + ], + "https://github.com/christian-byrne/python-interpreter-node": [ + [ + "Exec Python Code Script" + ], + { + "title_aux": "Python Interpreter ComfyUI Node [UNSAFE]" + } + ], + "https://github.com/comfyanonymous/ComfyUI": [ + [ + "AddNoise", + "AlignYourStepsScheduler", + "BasicGuider", + "BasicScheduler", + "CFGGuider", + "CLIPAttentionMultiply", + "CLIPLoader", + "CLIPMergeAdd", + "CLIPMergeSimple", + "CLIPMergeSubtract", + "CLIPSave", + "CLIPSetLastLayer", + "CLIPTextEncode", + "CLIPTextEncodeControlnet", + "CLIPTextEncodeSD3", + "CLIPTextEncodeSDXL", + "CLIPTextEncodeSDXLRefiner", + "CLIPVisionEncode", + "CLIPVisionLoader", + "Canny", + "CheckpointLoader", + "CheckpointLoaderSimple", + "CheckpointSave", + "ConditioningAverage", + "ConditioningCombine", + "ConditioningConcat", + "ConditioningSetArea", + "ConditioningSetAreaPercentage", + "ConditioningSetAreaStrength", + "ConditioningSetMask", + "ConditioningSetTimestepRange", + "ConditioningZeroOut", + "ControlNetApply", + "ControlNetApplyAdvanced", + "ControlNetLoader", + "CropMask", + "DiffControlNetLoader", + "DifferentialDiffusion", + "DiffusersLoader", + "DisableNoise", + "DualCFGGuider", + "DualCLIPLoader", + "EmptyImage", + "EmptyLatentAudio", + "EmptyLatentImage", + "EmptySD3LatentImage", + "ExponentialScheduler", + "FeatherMask", + "FlipSigmas", + "FreeU", + "FreeU_V2", + "GITSScheduler", + "GLIGENLoader", + "GLIGENTextBoxApply", + "GrowMask", + "HyperTile", + "HypernetworkLoader", + "ImageBatch", + "ImageBlend", + "ImageBlur", + "ImageColorToMask", + "ImageCompositeMasked", + "ImageCrop", + "ImageFromBatch", + "ImageInvert", + "ImageOnlyCheckpointLoader", + "ImageOnlyCheckpointSave", + "ImagePadForOutpaint", + "ImageQuantize", + "ImageScale", + "ImageScaleBy", + "ImageScaleToTotalPixels", + "ImageSharpen", + "ImageToMask", + "ImageUpscaleWithModel", + "InpaintModelConditioning", + "InstructPixToPixConditioning", + "InvertMask", + "JoinImageWithAlpha", + "KSampler", + "KSamplerAdvanced", + "KSamplerSelect", + "KarrasScheduler", + "LatentAdd", + "LatentBatch", + "LatentBatchSeedBehavior", + "LatentBlend", + "LatentComposite", + "LatentCompositeMasked", + "LatentCrop", + "LatentFlip", + "LatentFromBatch", + "LatentInterpolate", + "LatentMultiply", + "LatentRotate", + "LatentSubtract", + "LatentUpscale", + "LatentUpscaleBy", + "LoadAudio", + "LoadImage", + "LoadImageMask", + "LoadLatent", + "LoraLoader", + "LoraLoaderModelOnly", + "MaskComposite", + "MaskToImage", + "ModelMergeAdd", + "ModelMergeBlocks", + "ModelMergeSD1", + "ModelMergeSD2", + "ModelMergeSD3_2B", + "ModelMergeSDXL", + "ModelMergeSimple", + "ModelMergeSubtract", + "ModelSamplingContinuousEDM", + "ModelSamplingContinuousV", + "ModelSamplingDiscrete", + "ModelSamplingSD3", + "ModelSamplingStableCascade", + "Morphology", + "PatchModelAddDownscale", + "PerpNeg", + "PerpNegGuider", + "PerturbedAttentionGuidance", + "PhotoMakerEncode", + "PhotoMakerLoader", + "PolyexponentialScheduler", + "PorterDuffImageComposite", + "PreviewImage", + "RandomNoise", + "RebatchImages", + "RebatchLatents", + "RepeatImageBatch", + "RepeatLatentBatch", + "RescaleCFG", + "SDTurboScheduler", + "SD_4XUpscale_Conditioning", + "SV3D_Conditioning", + "SVD_img2vid_Conditioning", + "SamplerCustom", + "SamplerCustomAdvanced", + "SamplerDPMAdaptative", + "SamplerDPMPP_2M_SDE", + "SamplerDPMPP_3M_SDE", + "SamplerDPMPP_SDE", + "SamplerEulerAncestral", + "SamplerEulerCFGpp", + "SamplerLCMUpscale", + "SamplerLMS", + "SaveAnimatedPNG", + "SaveAnimatedWEBP", + "SaveAudio", + "SaveImage", + "SaveImageWebsocket", + "SaveLatent", + "SelfAttentionGuidance", + "SetLatentNoiseMask", + "SolidMask", + "SplitImageWithAlpha", + "SplitSigmas", + "SplitSigmasDenoise", + "StableCascade_EmptyLatentImage", + "StableCascade_StageB_Conditioning", + "StableCascade_StageC_VAEEncode", + "StableCascade_SuperResolutionControlnet", + "StableZero123_Conditioning", + "StableZero123_Conditioning_Batched", + "StyleModelApply", + "StyleModelLoader", + "ThresholdMask", + "TomePatchModel", + "TripleCLIPLoader", + "UNETLoader", + "UNetCrossAttentionMultiply", + "UNetSelfAttentionMultiply", + "UNetTemporalAttentionMultiply", + "UpscaleModelLoader", + "VAEDecode", + "VAEDecodeAudio", + "VAEDecodeTiled", + "VAEEncode", + "VAEEncodeAudio", + "VAEEncodeForInpaint", + "VAEEncodeTiled", + "VAELoader", + "VAESave", + "VPScheduler", + "VideoLinearCFGGuidance", + "VideoTriangleCFGGuidance", + "WebcamCapture", + "unCLIPCheckpointLoader", + "unCLIPConditioning" + ], + { + "title_aux": "ComfyUI" + } + ], + "https://github.com/comfypod/ComfyUI-Comflow": [ + [ + "ComflowInputBoolean", + "ComflowInputCheckpoint", + "ComflowInputImage", + "ComflowInputImageAlpha", + "ComflowInputImageBatch", + "ComflowInputLora", + "ComflowInputNumber", + "ComflowInputNumberInt", + "ComflowInputNumberSlider", + "ComflowInputText", + "ComflowInputVid", + "ComflowInputVideo", + "ComflowWebsocketImageInput", + "ComflowWebsocketImageOutput" + ], + { + "description": "", + "nickname": "Comflow", + "title": "comflow", + "title_aux": "ComfyUI-Comflow" + } + ], + "https://github.com/corbin-hayden13/ComfyUI-Better-Dimensions": [ + [ + "BetterImageDimensions", + "PureRatio", + "SDXLDimensions" + ], + { + "title_aux": "ComfyUI-Better-Dimensions" + } + ], + "https://github.com/dfl/comfyui-stylegan": [ + [ + "StyleGAN Generator", + "StyleGAN ModelLoader" + ], + { + "title_aux": "comfyui-stylegan" + } + ], + "https://github.com/dnl13/ComfyUI-dnl13-seg": [ + [ + "Automatic Segmentation (dnl13)", + "BatchSelector (dnl13)", + "Combine Images By Mask (dnl13)", + "Dinov1 Model Loader (dnl13)", + "Mask with prompt (dnl13)", + "RGB (dnl13)", + "SAM Model Loader (dnl13)" + ], + { + "title_aux": "ComfyUI-dnl13-seg" + } + ], + "https://github.com/doucx/ComfyUI_WcpD_Utility_Kit": [ + [ + "BlackImage", + "CopyImage(Wayland)", + "ExecStrAsCode", + "MergeStrings", + "YamlToPrompt" + ], + { + "title_aux": "ComfyUI_WcpD_Utility_Kit" + } + ], + "https://github.com/eigenpunk/ComfyUI-audio": [ + [ + "ApplyVoiceFixer", + "BatchAudio", + "BlendAudio", + "ClipAudioRegion", + "CombineImageWithAudio", + "ConcatAudio", + "ConvertAudio", + "FilterAudio", + "FlattenAudioBatch", + "HifiGANApply", + "HifiGANLoader", + "HifiGANModelParams", + "InvertAudioPhase", + "LoadAudio", + "MusicgenGenerate", + "MusicgenHFGenerate", + "MusicgenHFLoader", + "MusicgenLoader", + "NormalizeAudio", + "PreviewAudio", + "ResampleAudio", + "SaveAudio", + "SpectrogramImage", + "Tacotron2Generate", + "Tacotron2Loader", + "ToMelSpectrogram", + "TortoiseTTSGenerate", + "TortoiseTTSLoader", + "TrimAudio", + "TrimAudioSamples", + "TrimSilence", + "VALLEXGenerator", + "VALLEXLoader", + "VALLEXVoicePromptFromAudio", + "VALLEXVoicePromptLoader", + "WaveGlowApply", + "WaveGlowLoader" + ], + { + "title_aux": "ComfyUI-audio" + } + ], + "https://github.com/ejektaflex/ComfyUI-Ty": [ + [ + "Lora Block Weight Regex Loader // Ty" + ], + { + "title_aux": "ComfyUI-Ty" + } + ], + "https://github.com/endman100/ComfyUI-SaveAndLoadPromptCondition": [ + [ + "LoadContditioning", + "SaveConditioning" + ], + { + "title_aux": "ComfyUI Nodes: SaveConditioning and LoadConditioning" + } + ], + "https://github.com/ericbeyer/guidance_interval": [ + [ + "Guidance Interval" + ], + { + "title_aux": "guidance_interval" + } + ], + "https://github.com/flowtyone/comfyui-flowty-lcm": [ + [ + "LCMSampler" + ], + { + "title_aux": "comfyui-flowty-lcm" + } + ], + "https://github.com/flyingdogsoftware/gyre_for_comfyui": [ + [ + "BackgroundRemoval", + "GyreIfElse", + "GyreLoopEnd", + "GyreLoopStart" + ], + { + "title_aux": "Gyre for ComfyUI" + } + ], + "https://github.com/foglerek/comfyui-cem-tools": [ + [ + "ProcessImageBatch" + ], + { + "title_aux": "comfyui-cem-tools" + } + ], + "https://github.com/gameltb/ComfyUI_stable_fast": [ + [ + "ApplyStableFastUnet", + "ApplyTensorRTControlNet", + "ApplyTensorRTUnet", + "ApplyTensorRTVaeDecoder" + ], + { + "title_aux": "ComfyUI_stable_fast" + } + ], + "https://github.com/githubYiheng/comfyui_median_filter": [ + [ + "ImageMedianFilter" + ], + { + "title_aux": "comfyui_median_filter" + } + ], + "https://github.com/haofanwang/ComfyUI-InstantStyle": [ + [ + "BaseModelLoader", + "InstantStyleGenerationNode", + "InstantStyleLoader", + "PromptLoader" + ], + { + "title_aux": "ComfyUI-InstantStyle" + } + ], + "https://github.com/horidream/ComfyUI-Horidream": [ + [ + "PassThroughWithSound" + ], + { + "title_aux": "ComfyUI-Horidream" + } + ], + "https://github.com/houdinii/comfy-magick": [ + [ + "AdaptiveBlur", + "AdaptiveSharpen", + "AddNoise", + "BlueShift", + "Blur", + "Charcoal", + "Colorize", + "CropByAspectRatio", + "Despeckle", + "Edge", + "Emboss", + "FX", + "GaussianBlur", + "Implode", + "Kuwahara", + "MotionBlur", + "RotationalBlur", + "SelectiveBlur", + "Sepia", + "Shade", + "Sharpen", + "Sketch", + "Solarize", + "Spread", + "Stereogram", + "Swirl", + "Tint", + "UnsharpMask", + "Vignette", + "WaveletDenoise" + ], + { + "title_aux": "comfy-magick [WIP]" + } + ], + "https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui": [ + [ + "EasyBgRemover", + "EasyBgRemover_ModelLoader", + "EasyControlNetApply", + "EasyControlNetLoader", + "EasyEmptyLatentImage", + "EasyLatentToCondition", + "EasyLoadImage" + ], + { + "title_aux": "ComfyUI_Easy_Nodes_hui" + } + ], + "https://github.com/hy134300/comfyui-hb-node": [ + [ + "generate story", + "hy save image", + "latent to list", + "movie batch", + "movie generate", + "sound voice", + "text concat" + ], + { + "title_aux": "comfyui-hb-node" + } + ], + "https://github.com/hy134300/comfyui-hydit": [ + [ + "DiffusersClipTextEncode", + "DiffusersModelMakeup", + "DiffusersPipelineLoader", + "DiffusersSampler", + "DiffusersSchedulerLoader" + ], + { + "title_aux": "comfyui-hydit" + } + ], + "https://github.com/ilovejohnwhite/UncleBillyGoncho": [ + [ + "CannyEdgePreprocessor", + "DiffusionEdge_Preprocessor", + "HintImageEnchance", + "ImageGenResolutionFromImage", + "ImageGenResolutionFromLatent", + "LineArtPreprocessor", + "LinkMasterNode", + "PiDiNetPreprocessor", + "PixelPerfectResolution", + "SuckerPunch", + "UWU_Preprocessor", + "VooDooNode", + "VooDooNode2" + ], + { + "title_aux": "TatToolkit" + } + ], + "https://github.com/immersiveexperience/ie-comfyui-color-nodes": [ + [ + "Average Color", + "Complementary Color", + "Hex Color to Image", + "Hex to Color Name", + "Random String" + ], + { + "title_aux": "ie-comfyui-color-nodes" + } + ], + "https://github.com/jh-leon-kim/ComfyUI-JHK-utils": [ + [ + "JHK_Utils_ImageRemoveBackground", + "JHK_Utils_LoadEmbed", + "JHK_Utils_string_merge" + ], + { + "title_aux": "ComfyUI-JHK-utils" + } + ], + "https://github.com/jimmm-ai/TimeUi-a-ComfyUi-Timeline-Node": [ + [ + "utils/TimelineUI" + ], + { + "title_aux": "TimeUi a ComfyUI Timeline Node System [WIP]" + } + ], + "https://github.com/jn-jairo/jn_node_suite_comfyui": [ + [ + "JN_AreaInfo", + "JN_AreaNormalize", + "JN_AreaWidthHeight", + "JN_AreaXY", + "JN_Blip", + "JN_BlipLoader", + "JN_BooleanOperation", + "JN_Condition", + "JN_CoolDown", + "JN_CoolDownOutput", + "JN_CropFace", + "JN_DatetimeFormat", + "JN_DatetimeInfo", + "JN_DatetimeNow", + "JN_Dump", + "JN_DumpOutput", + "JN_FaceRestoreModelLoader", + "JN_FaceRestoreWithModel", + "JN_FirstActive", + "JN_ImageAddMask", + "JN_ImageBatch", + "JN_ImageCenterArea", + "JN_ImageCrop", + "JN_ImageGrid", + "JN_ImageInfo", + "JN_ImageSharpness", + "JN_ImageSquare", + "JN_ImageUncrop", + "JN_KSampler", + "JN_KSamplerAdvancedParams", + "JN_KSamplerFaceRestoreParams", + "JN_KSamplerResizeInputParams", + "JN_KSamplerResizeMaskAreaParams", + "JN_KSamplerResizeOutputParams", + "JN_KSamplerSeamlessParams", + "JN_KSamplerTileParams", + "JN_LoadImageDirectory", + "JN_LogicOperation", + "JN_MaskInfo", + "JN_MathOperation", + "JN_MathOperationArray", + "JN_PrimitiveArrayInfo", + "JN_PrimitiveBatchToArray", + "JN_PrimitiveBoolean", + "JN_PrimitiveFloat", + "JN_PrimitiveInt", + "JN_PrimitivePrompt", + "JN_PrimitiveString", + "JN_PrimitiveStringMultiline", + "JN_PrimitiveStringToArray", + "JN_PrimitiveToArray", + "JN_PrimitiveToBoolean", + "JN_PrimitiveToFloat", + "JN_PrimitiveToInt", + "JN_PrimitiveToString", + "JN_RemoveBackground", + "JN_Seamless", + "JN_SeamlessBorder", + "JN_SeamlessBorderCrop", + "JN_SelectItem", + "JN_Sleep", + "JN_SleepOutput", + "JN_SliceOperation", + "JN_StopIf", + "JN_StopIfOutput", + "JN_TextConcatenation", + "JN_TextReplace", + "JN_TimedeltaFormat", + "JN_TimedeltaInfo", + "JN_VAEPatch" + ], + { + "title_aux": "jn_node_suite_comfyui [WIP]" + } + ], + "https://github.com/jp0215/comfyUI_padding-resize_node/raw/main/PaddingNode.py": [ + [ + "function" + ], + { + "title_aux": "comfyUI_padding-resize_node" + } + ], + "https://github.com/jtscmw01/ComfyUI-DiffBIR": [ + [ + "DiffBIR_sample", + "DiffBIR_sample_advanced", + "Simple_load", + "Stage1_load", + "Stage2_load" + ], + { + "title_aux": "ComfyUI-DiffBIR" + } + ], + "https://github.com/jtydhr88/ComfyUI-Unique3D": [ + [ + "Unique3DLoadPipeline", + "Unique3DRun - Geo Reconstruct", + "Unique3DRun - MVPrediction" + ], + { + "title_aux": "ComfyUI-Unique3D [WIP]" + } + ], + "https://github.com/kadirnar/ComfyUI-Adapter": [ + [ + "GarmentSegLoader" + ], + { + "title_aux": "ComfyUI-Adapter [WIP]" + } + ], + "https://github.com/kadirnar/comfyui_helpers": [ + [ + "CircularVAEDecode", + "CustomKSamplerAdvancedTile", + "JDC_AutoContrast", + "JDC_BlendImages", + "JDC_BrownNoise", + "JDC_Contrast", + "JDC_EqualizeGrey", + "JDC_GaussianBlur", + "JDC_GreyNoise", + "JDC_Greyscale", + "JDC_ImageLoader", + "JDC_ImageLoaderMeta", + "JDC_PinkNoise", + "JDC_Plasma", + "JDC_PlasmaSampler", + "JDC_PowerImage", + "JDC_RandNoise", + "JDC_ResizeFactor", + "LatentGaussianNoise", + "LatentToRGB", + "MathEncode", + "NoisyLatentPerlin" + ], + { + "title_aux": "comfyui_helpers" + } + ], + "https://github.com/kappa54m/ComfyUI_Usability": [ + [ + "KLoadImageByPath", + "KLoadImageByPathAdvanced", + "KLoadImageDedup" + ], + { + "title_aux": "ComfyUI_Usability (WIP)" + } + ], + "https://github.com/kijai/ComfyUI-CV-VAE": [ + [ + "CV_VAE_Decode", + "CV_VAE_Encode", + "CV_VAE_Load" + ], + { + "title_aux": "ComfyUI-CV-VAE" + } + ], + "https://github.com/kijai/ComfyUI-DeepSeek-VL": [ + [ + "deepseek_vl_inference", + "deepseek_vl_model_loader" + ], + { + "title_aux": "ComfyUI nodes to use DeepSeek-VL" + } + ], + "https://github.com/kijai/ComfyUI-DiffSynthWrapper": [ + [ + "DiffSynthSampler", + "DownloadAndLoadDiffSynthExVideoSVD" + ], + { + "title_aux": "ComfyUI DiffSynth wrapper nodes [WIP]" + } + ], + "https://github.com/kijai/ComfyUI-DiffusersSD3Wrapper": [ + [ + "LoadSD3DiffusersPipeline", + "SD3ControlNetSampler" + ], + { + "title_aux": "ComfyUI-DiffusersSD3Wrapper" + } + ], + "https://github.com/komojini/ComfyUI_Prompt_Template_CustomNodes/raw/main/prompt_with_template.py": [ + [ + "ObjectPromptWithTemplate", + "PromptWithTemplate" + ], + { + "title_aux": "ComfyUI_Prompt_Template_CustomNodes" + } + ], + "https://github.com/kycg/comfyui-Kwtoolset": [ + [ + "KWNagetiveString", + "KWPositiveString", + "KWanywhereString", + "KwtoolsetChangeOpenpose", + "KwtoolsetCheckpointLoaderwithpreview", + "KwtoolsetGetHipMask", + "KwtoolsetGetHipMasktest", + "KwtoolsetGetImageSize", + "KwtoolsetGrowMaskPlus", + "KwtoolsetLoadCheckpointsBatch", + "KwtoolsetLoraLoaderwithpreview", + "LatentMatch" + ], + { + "title_aux": "comfyui-Kwtoolset" + } + ], + "https://github.com/laksjdjf/ssd-1b-comfyui": [ + [ + "SSD-1B-Loader" + ], + { + "title_aux": "ssd-1b-comfyui" + } + ], + "https://github.com/logtd/ComfyUI-MotionThiefExperiment": [ + [ + "ApplyRefMotionNode", + "MotionRefSettingsCustomNode", + "MotionRefSettingsDefaultNode" + ], + { + "title_aux": "ComfyUI-MotionThiefExperiment" + } + ], + "https://github.com/longgui0318/comfyui-one-more-step": [ + [ + "Calculate More Step Latent", + "Load More Step Model" + ], + { + "title_aux": "comfyui-one-more-step [WIP]" + } + ], + "https://github.com/ltdrdata/ComfyUI-Workflow-Component": [ + [ + "ComboToString", + "ExecutionBlocker", + "ExecutionControlString", + "ExecutionOneOf", + "ExecutionSwitch", + "InputUnzip", + "InputZip", + "LoopControl", + "LoopCounterCondition", + "OptionalTest", + "TensorToCPU" + ], + { + "title_aux": "ComfyUI-Workflow-Component [WIP]" + } + ], + "https://github.com/marcueberall/ComfyUI-BuildPath": [ + [ + "Build Path Adv" + ], + { + "title_aux": "ComfyUI-BuildPath" + } + ], + "https://github.com/marduk191/comfyui-marnodes": [ + [ + "marduk191_5_text_string", + "marduk191_5way_text_switch", + "marduk191_workflow_settings" + ], + { + "author": "\u02f6marduk191", + "description": "A node to set workflow settings.", + "nickname": "marduk191 workflow settings", + "title": "marduk191 workflow settings", + "title_aux": "comfyui-marnodes" + } + ], + "https://github.com/maruhidd/ComfyUI_Transparent-Background": [ + [ + "FillTransparentNode", + "RemoveBackgroundNode" + ], + { + "title_aux": "Transparent Background for ComfyUI" + } + ], + "https://github.com/mashb1t/comfyui-nodes-mashb1t": [ + [ + "mashb1t: LoadImage" + ], + { + "title_aux": "ComfyUI mashb1t nodes" + } + ], + "https://github.com/mikeymcfish/FishTools": [ + [ + "Deptherize", + "LaserCutterFull" + ], + { + "author": "Fish", + "description": "This extension provides tools for generating laser cutter ready files", + "nickname": "FishTools", + "title": "FishTools", + "title_aux": "LaserCutterFull and Deptherize Nodes" + } + ], + "https://github.com/mingqizhang/ComfyUI_AEMatter_zmq": [ + [ + "AEMatter_Apply", + "AEMatter_ModelLoader", + "Create_Trimap", + "Gaussian_Filter", + "Guide_Filter", + "Mask_Transfor", + "Replace_Background" + ], + { + "title_aux": "ComfyUI_AEMatter_zmq" + } + ], + "https://github.com/mut-ex/comfyui-gligengui-node": [ + [ + "GLIGEN_GUI" + ], + { + "title_aux": "ComfyUI GLIGEN GUI Node" + } + ], + "https://github.com/nidefawl/ComfyUI-nidefawl": [ + [ + "BlendImagesWithBoundedMasks", + "CropImagesWithMasks", + "CustomCallback", + "DisplayAnyType", + "EmptyImageWithColor", + "ImageToLatent", + "LatentPerlinNoise", + "LatentScaledNoise", + "LatentToImage", + "MaskFromColor", + "ModelSamplerTonemapNoiseTest", + "PythonScript", + "ReferenceOnlySimple", + "SamplerCustomCallback", + "SamplerDPMPP_2M_SDE_nidefawl", + "SetLatentCustomNoise", + "SplitCustomSigmas", + "VAELoaderDataType", + "gcLatentTunnel" + ], + { + "title_aux": "ComfyUI-nidefawl [UNSAFE]" + } + ], + "https://github.com/nkchocoai/ComfyUI-PromptUtilities": [ + [ + "PromptUtilitiesConstString", + "PromptUtilitiesConstStringMultiLine", + "PromptUtilitiesFormatString", + "PromptUtilitiesJoinStringList", + "PromptUtilitiesLoadPreset", + "PromptUtilitiesLoadPresetAdvanced", + "PromptUtilitiesRandomPreset", + "PromptUtilitiesRandomPresetAdvanced" + ], + { + "title_aux": "ComfyUI-PromptUtilities" + } + ], + "https://github.com/oyvindg/ComfyUI-TrollSuite": [ + [ + "BinaryImageMask", + "ImagePadding", + "LoadLastImage", + "RandomMask", + "TransparentImage" + ], + { + "title_aux": "ComfyUI-TrollSuite" + } + ], + "https://github.com/oztrkoguz/ComfyUI_Kosmos2_BBox_Cutter": [ + [ + "Kosmos2SamplerSimple", + "KosmosLoader", + "Write" + ], + { + "title_aux": "Kosmos2_BBox_Cutter Models" + } + ], + "https://github.com/pamparamm/ComfyUI-ppm": [ + [ + "AttentionCouplePPM", + "CLIPMicroConditioning", + "CLIPNegPip", + "CLIPTextEncodeBREAK", + "CLIPTokenCounter", + "EmptyLatentImageAR", + "EmptyLatentImageARAdvanced", + "LatentToMaskBB", + "LatentToWidthHeight", + "RandomPromptGenerator", + "StableCascade_AutoCompLatent" + ], + { + "title_aux": "ComfyUI-ppm" + } + ], + "https://github.com/poisenbery/NudeNet-Detector-Provider": [ + [ + "NudeNetDetectorProvider" + ], + { + "title_aux": "NudeNet-Detector-Provider [WIP]" + } + ], + "https://github.com/prabinpebam/anyPython": [ + [ + "Any Python" + ], + { + "author": "prabinpebam", + "description": "This node can take any input and use that to run a python script in ComfyUI", + "nickname": "AnyPython", + "title": "AnyPython v0.1", + "title_aux": "anyPython [UNSAFE]" + } + ], + "https://github.com/prismwastaken/comfyui-tools": [ + [ + "Prism-RandomNormal" + ], + { + "title_aux": "prism-tools" + } + ], + "https://github.com/pzzmyc/comfyui-sd3-simple-simpletuner": [ + [ + "sd not very simple simpletuner by hhy" + ], + { + "title_aux": "comfyui-sd3-simple-simpletuner" + } + ], + "https://github.com/redhottensors/ComfyUI-ODE": [ + [ + "Blended Transition [DVB]", + "Calculation [DVB]", + "Create Frame Set [DVB]", + "Divide [DVB]", + "Fade From Black [DVB]", + "Fade To Black [DVB]", + "Float Input [DVB]", + "For Each Done [DVB]", + "For Each Filename [DVB]", + "Frame Set Append [DVB]", + "Frame Set Frame Dimensions Scaled [DVB]", + "Frame Set Index Offset [DVB]", + "Frame Set Merger [DVB]", + "Frame Set Reindex [DVB]", + "Frame Set Repeat [DVB]", + "Frame Set Reverse [DVB]", + "Frame Set Split Beginning [DVB]", + "Frame Set Split End [DVB]", + "Frame Set Splitter [DVB]", + "Generate Inbetween Frames [DVB]", + "Int Input [DVB]", + "Linear Camera Pan [DVB]", + "Linear Camera Roll [DVB]", + "Linear Camera Zoom [DVB]", + "Load Image From Path [DVB]", + "Multiply [DVB]", + "ODESamplerSelect", + "Sine Camera Pan [DVB]", + "Sine Camera Roll [DVB]", + "Sine Camera Zoom [DVB]", + "String Input [DVB]", + "Text Input [DVB]", + "Trace Memory Allocation [DVB]", + "Unwrap Frame Set [DVB]" + ], + { + "author": "RedHotTensors", + "description": "Adaptive ODE Solvers for ComfyUI", + "nickname": "ComfyUI-ODE", + "title": "ComfyUI-ODE", + "title_aux": "ComfyUI-ODE" + } + ], + "https://github.com/sdfxai/SDFXBridgeForComfyUI": [ + [ + "SDFXClipTextEncode" + ], + { + "title_aux": "SDFXBridgeForComfyUI - ComfyUI Custom Node for SDFX Integration" + } + ], + "https://github.com/shadowcz007/ComfyUI-PuLID-Test": [ + [ + "ApplyPulid", + "PulidEvaClipLoader", + "PulidInsightFaceLoader", + "PulidModelLoader" + ], + { + "title_aux": "ComfyUI-PuLID [TEST]" + } + ], + "https://github.com/shadowcz007/comfyui-CLIPSeg": [ + [ + "CLIPSeg_", + "CombineMasks_" + ], + { + "title_aux": "comfyui-CLIPSeg" + } + ], + "https://github.com/shadowcz007/comfyui-musicgen": [ + [ + "AudioPlay", + "Musicgen_", + "StableAudio_" + ], + { + "title_aux": "comfyui-musicgen" + } + ], + "https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4": [ + [ + "CLIPTextEncodeAndEnhance" + ], + { + "title_aux": "CLIPTextEncodeAndEnhancev4 (shirazdesigner)" + } + ], + "https://github.com/sofakid/dandy": [ + [ + "DandyBooleanCollector", + "DandyBooleanPreview", + "DandyBooleanSplitter", + "DandyCss", + "DandyCssLoader", + "DandyEditorSettings", + "DandyFloatCollector", + "DandyFloatPreview", + "DandyFloatSplitter", + "DandyGradient", + "DandyHtml", + "DandyHtmlLoader", + "DandyImageCollector", + "DandyIntCollector", + "DandyIntPreview", + "DandyIntSplitter", + "DandyJs", + "DandyJsLoader", + "DandyJson", + "DandyJsonLoader", + "DandyLand", + "DandyMaskCollector", + "DandyP5JsDraw", + "DandyP5JsLoader", + "DandyP5JsSetup", + "DandyPixelsJs", + "DandyPixiJs", + "DandyPrompt", + "DandyString", + "DandyStringArrayCollector", + "DandyStringArraySplitter", + "DandyStringCatCollector", + "DandyStringPreview", + "DandyUrlLoader", + "DandyWasmLoader", + "DandyYaml", + "DandyYamlLoader" + ], + { + "title_aux": "dandy [UNSAFE]" + } + ], + "https://github.com/stutya/ComfyUI-Terminal": [ + [ + "Terminal" + ], + { + "title_aux": "ComfyUI-Terminal [UNSAFE]" + } + ], + "https://github.com/sugarkwork/comfyui_psd": [ + [ + "SavePSD" + ], + { + "title_aux": "comfyui_psd [WIP]" + } + ], + "https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes": [ + [ + "ImageSizer", + "KSamplerSDXLAdvanced" + ], + { + "title_aux": "my-useful-comfyui-custom-nodes" + } + ], + "https://github.com/tracerstar/comfyui-p5js-node": [ + [ + "HYPE_P5JSImage" + ], + { + "title_aux": "comfyui-p5js-node" + } + ], + "https://github.com/tuckerdarby/ComfyUI-TDNodes": [ + [ + "HandTrackerNode", + "InstanceDiffusionLoader", + "InstanceTrackerPrompt", + "KSamplerBatchedNode", + "KSamplerRAVE", + "KSamplerTF", + "TemporalNetPreprocessor", + "TrackerNode", + "VideoTrackerPromptNode" + ], + { + "title_aux": "ComfyUI-TDNodes [WIP]" + } + ], + "https://github.com/umisetokikaze/comfyui_mergekit": [ + [ + "DefineSaveName", + "LoadLR", + "LoadTarget", + "Merge", + "SetLayer", + "SetModels", + "SetTokenizer", + "get_skip" + ], + { + "title_aux": "comfyui_mergekit [WIP]" + } + ], + "https://github.com/unanan/ComfyUI-Dist": [ + [ + "LoadCheckpointFromLAN", + "LoadCheckpointFromURL", + "LoadImageFromLAN", + "LoadImageFromURL", + "LoadWorkflowFromLAN", + "LoadWorkflowFromURL" + ], + { + "title_aux": "ComfyUI-Dist [WIP]" + } + ], + "https://github.com/unanan/ComfyUI-clip-interrogator": [ + [ + "ComfyUIClipInterrogator", + "ShowText" + ], + { + "title_aux": "ComfyUI-clip-interrogator [WIP]" + } + ], + "https://github.com/wormley/comfyui-wormley-nodes": [ + [ + "CheckpointVAELoaderSimpleText", + "CheckpointVAESelectorText", + "LoRA_Tag_To_Stack" + ], + { + "title_aux": "comfyui-wormley-nodes" + } + ], + "https://github.com/yushan777/ComfyUI-Y7Nodes": [ + [ + "Count_Tokens_(Y7)" + ], + { + "title_aux": "Y7 Nodes for ComfyUI" + } + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/dev/github-stats.json b/custom_nodes/ComfyUI-Manager/node_db/dev/github-stats.json new file mode 100644 index 000000000..8239a1133 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/dev/github-stats.json @@ -0,0 +1,762 @@ +{ + "https://github.com/17Retoucher/ComfyUI_Fooocus": { + "stars": 52, + "last_update": "2024-02-24 07:33:29", + "author_account_age_days": 171 + }, + "https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1": { + "stars": 13, + "last_update": "2024-03-08 10:11:44", + "author_account_age_days": 314 + }, + "https://github.com/AI2lab/comfyUI-tool-2lab": { + "stars": 7, + "last_update": "2024-06-06 16:16:11", + "author_account_age_days": 192 + }, + "https://github.com/AIGODLIKE/ComfyUI-Studio": { + "stars": 203, + "last_update": "2024-06-05 00:52:46", + "author_account_age_days": 501 + }, + "https://github.com/ALatentPlace/ComfyUI_yanc": { + "stars": 18, + "last_update": "2024-06-14 09:04:57", + "author_account_age_days": 1460 + }, + "https://github.com/AllenEdgarPoe/ComfyUI-Xorbis-nodes": { + "stars": 0, + "last_update": "2024-06-21 01:43:13", + "author_account_age_days": 2105 + }, + "https://github.com/AustinMroz/ComfyUI-WorkflowCheckpointing": { + "stars": 5, + "last_update": "2024-06-19 21:19:45", + "author_account_age_days": 4074 + }, + "https://github.com/BadCafeCode/execution-inversion-demo-comfyui": { + "stars": 4, + "last_update": "2024-06-19 06:59:39", + "author_account_age_days": 430 + }, + "https://github.com/Beinsezii/comfyui-amd-go-fast": { + "stars": 9, + "last_update": "2024-05-10 00:48:37", + "author_account_age_days": 2226 + }, + "https://github.com/BlueDangerX/ComfyUI-BDXNodes": { + "stars": 1, + "last_update": "2023-12-10 04:01:19", + "author_account_age_days": 246 + }, + "https://github.com/Brandelan/ComfyUI_bd_customNodes": { + "stars": 1, + "last_update": "2023-10-09 00:40:26", + "author_account_age_days": 4151 + }, + "https://github.com/DeTK/ComfyUI-Switch": { + "stars": 0, + "last_update": "2024-03-04 11:52:04", + "author_account_age_days": 2031 + }, + "https://github.com/DrMWeigand/ComfyUI_LineBreakInserter": { + "stars": 0, + "last_update": "2024-04-19 11:37:19", + "author_account_age_days": 1032 + }, + "https://github.com/Elawphant/ComfyUI-MusicGen": { + "stars": 4, + "last_update": "2024-05-11 13:33:24", + "author_account_age_days": 2588 + }, + "https://github.com/ExponentialML/ComfyUI_LiveDirector": { + "stars": 35, + "last_update": "2024-04-09 19:01:49", + "author_account_age_days": 1623 + }, + "https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI": { + "stars": 13, + "last_update": "2024-03-10 01:04:02", + "author_account_age_days": 3149 + }, + "https://github.com/FoundD-oka/ComfyUI-kisekae-OOTD": { + "stars": 0, + "last_update": "2024-06-02 06:13:42", + "author_account_age_days": 437 + }, + "https://github.com/GentlemanHu/ComfyUI-Notifier": { + "stars": 3, + "last_update": "2024-06-04 10:05:38", + "author_account_age_days": 2383 + }, + "https://github.com/GraftingRayman/ComfyUI_GR_PromptSelector": { + "stars": 17, + "last_update": "2024-06-22 18:22:20", + "author_account_age_days": 163 + }, + "https://github.com/GrindHouse66/ComfyUI-GH_Tools": { + "stars": 0, + "last_update": "2024-03-10 13:27:14", + "author_account_age_days": 624 + }, + "https://github.com/IvanZhd/comfyui-codeformer": { + "stars": 0, + "last_update": "2023-12-02 20:51:52", + "author_account_age_days": 2578 + }, + "https://github.com/Jaxkr/comfyui-terminal-command": { + "stars": 1, + "last_update": "2023-12-03 10:31:40", + "author_account_age_days": 4627 + }, + "https://github.com/Jiffies-64/ComfyUI-SaveImagePlus": { + "stars": 0, + "last_update": "2024-04-01 10:52:59", + "author_account_age_days": 891 + }, + "https://github.com/Jordach/comfy-consistency-vae": { + "stars": 68, + "last_update": "2023-11-06 20:50:40", + "author_account_age_days": 4513 + }, + "https://github.com/LZpenguin/ComfyUI-Text": { + "stars": 9, + "last_update": "2024-06-20 13:38:16", + "author_account_age_days": 1979 + }, + "https://github.com/LarryJane491/ComfyUI-ModelUnloader": { + "stars": 1, + "last_update": "2024-01-14 08:22:39", + "author_account_age_days": 164 + }, + "https://github.com/LotzF/ComfyUI-Simple-Chat-GPT-completion": { + "stars": 0, + "last_update": "2024-02-04 21:15:22", + "author_account_age_days": 929 + }, + "https://github.com/LykosAI/ComfyUI-Inference-Core-Nodes": { + "stars": 16, + "last_update": "2024-04-05 05:11:51", + "author_account_age_days": 378 + }, + "https://github.com/MrAdamBlack/CheckProgress": { + "stars": 1, + "last_update": "2024-01-10 08:02:18", + "author_account_age_days": 2720 + }, + "https://github.com/MushroomFleet/DJZ-Nodes": { + "stars": 4, + "last_update": "2024-03-18 11:18:42", + "author_account_age_days": 3721 + }, + "https://github.com/NicholasKao1029/comfyui-hook": { + "stars": 0, + "last_update": "2024-03-07 05:50:56", + "author_account_age_days": 2030 + }, + "https://github.com/NitramDom/ComfyUI_FacialFlip": { + "stars": 2, + "last_update": "2024-06-07 14:56:55", + "author_account_age_days": 3172 + }, + "https://github.com/PluMaZero/ComfyUI-SpaceFlower": { + "stars": 4, + "last_update": "2023-12-09 05:55:15", + "author_account_age_days": 1058 + }, + "https://github.com/Quasimondo/ComfyUI-QuasimondoNodes": { + "stars": 4, + "last_update": "2024-06-21 19:55:21", + "author_account_age_days": 5275 + }, + "https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt": { + "stars": 20, + "last_update": "2024-03-17 04:30:01", + "author_account_age_days": 4040 + }, + "https://github.com/Sai-ComfyUI/ComfyUI-MS-Nodes": { + "stars": 2, + "last_update": "2024-02-22 08:34:44", + "author_account_age_days": 209 + }, + "https://github.com/Scorpinaus/ComfyUI-DiffusersLoader": { + "stars": 3, + "last_update": "2024-06-23 01:30:57", + "author_account_age_days": 1110 + }, + "https://github.com/SeedV/ComfyUI-SeedV-Nodes": { + "stars": 1, + "last_update": "2024-06-05 10:01:47", + "author_account_age_days": 1126 + }, + "https://github.com/Shinsplat/ComfyUI-Shinsplat": { + "stars": 13, + "last_update": "2024-06-22 14:29:36", + "author_account_age_days": 1024 + }, + "https://github.com/StartHua/Comfyui_CXH_CRM": { + "stars": 26, + "last_update": "2024-06-06 14:15:14", + "author_account_age_days": 2835 + }, + "https://github.com/TSFSean/ComfyUI-TSFNodes": { + "stars": 4, + "last_update": "2024-05-18 00:59:06", + "author_account_age_days": 3472 + }, + "https://github.com/TemryL/ComfyUI-IDM-VTON": { + "stars": 203, + "last_update": "2024-06-22 06:14:19", + "author_account_age_days": 868 + }, + "https://github.com/Video3DGenResearch/comfyui-batch-input-node": { + "stars": 1, + "last_update": "2024-04-28 15:21:17", + "author_account_age_days": 106 + }, + "https://github.com/WSJUSA/Comfyui-StableSR": { + "stars": 38, + "last_update": "2023-10-18 12:40:30", + "author_account_age_days": 1424 + }, + "https://github.com/WilliamStanford/visuallabs_comfyui_nodes": { + "stars": 1, + "last_update": "2024-04-16 21:53:02", + "author_account_age_days": 1769 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText": { + "stars": 45, + "last_update": "2024-05-22 14:30:05", + "author_account_age_days": 340 + }, + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PuLID-ZHO": { + "stars": 184, + "last_update": "2024-05-22 13:38:23", + "author_account_age_days": 340 + }, + "https://github.com/alt-key-project/comfyui-dream-video-batches": { + "stars": 51, + "last_update": "2024-05-22 20:52:05", + "author_account_age_days": 660 + }, + "https://github.com/baicai99/ComfyUI-FrameSkipping": { + "stars": 6, + "last_update": "2024-06-18 10:25:55", + "author_account_age_days": 831 + }, + "https://github.com/beyastard/ComfyUI_BeySoft": { + "stars": 0, + "last_update": "2024-05-26 22:44:55", + "author_account_age_days": 4286 + }, + "https://github.com/birnam/ComfyUI-GenData-Pack": { + "stars": 0, + "last_update": "2024-03-25 01:25:23", + "author_account_age_days": 5009 + }, + "https://github.com/blepping/comfyui_overly_complicated_sampling": { + "stars": 5, + "last_update": "2024-06-12 01:05:41", + "author_account_age_days": 154 + }, + "https://github.com/blib-la/ComfyUI-Captain-Extensions": { + "stars": 0, + "last_update": "2024-05-17 23:27:25", + "author_account_age_days": 273 + }, + "https://github.com/bruce007lee/comfyui-cleaner": { + "stars": 3, + "last_update": "2024-04-20 15:36:03", + "author_account_age_days": 4512 + }, + "https://github.com/bruce007lee/comfyui-tiny-utils": { + "stars": 0, + "last_update": "2024-06-07 03:44:47", + "author_account_age_days": 4512 + }, + "https://github.com/brycegoh/comfyui-custom-nodes": { + "stars": 0, + "last_update": "2024-06-05 09:30:06", + "author_account_age_days": 3108 + }, + "https://github.com/chaojie/ComfyUI-DynamiCrafter": { + "stars": 109, + "last_update": "2024-06-14 10:23:59", + "author_account_age_days": 4833 + }, + "https://github.com/chaojie/ComfyUI-mobvoi-openapi": { + "stars": 2, + "last_update": "2024-05-29 09:02:52", + "author_account_age_days": 4833 + }, + "https://github.com/christian-byrne/infinite-zoom-parallax-nodes": { + "stars": 4, + "last_update": "2024-05-27 01:51:24", + "author_account_age_days": 1348 + }, + "https://github.com/christian-byrne/python-interpreter-node": { + "stars": 20, + "last_update": "2024-06-23 22:22:20", + "author_account_age_days": 1348 + }, + "https://github.com/comfyanonymous/ComfyUI": { + "stars": 39915, + "last_update": "2024-06-24 11:47:40", + "author_account_age_days": 549 + }, + "https://github.com/comfypod/ComfyUI-Comflow": { + "stars": 0, + "last_update": "2024-06-17 08:44:08", + "author_account_age_days": 23 + }, + "https://github.com/corbin-hayden13/ComfyUI-Better-Dimensions": { + "stars": 7, + "last_update": "2024-06-12 17:45:21", + "author_account_age_days": 1815 + }, + "https://github.com/cubiq/Comfy_Dungeon": { + "stars": 174, + "last_update": "2024-04-26 11:00:58", + "author_account_age_days": 5011 + }, + "https://github.com/dezi-ai/ComfyUI-AnimateLCM": { + "stars": 148, + "last_update": "2024-02-07 17:34:39", + "author_account_age_days": 177 + }, + "https://github.com/dfl/comfyui-stylegan": { + "stars": 1, + "last_update": "2024-03-14 14:34:25", + "author_account_age_days": 5974 + }, + "https://github.com/dnl13/ComfyUI-dnl13-seg": { + "stars": 16, + "last_update": "2024-01-08 10:52:13", + "author_account_age_days": 4218 + }, + "https://github.com/doucx/ComfyUI_WcpD_Utility_Kit": { + "stars": 1, + "last_update": "2024-01-06 19:07:45", + "author_account_age_days": 2323 + }, + "https://github.com/eigenpunk/ComfyUI-audio": { + "stars": 59, + "last_update": "2024-03-03 21:14:14", + "author_account_age_days": 925 + }, + "https://github.com/ejektaflex/ComfyUI-Ty": { + "stars": 0, + "last_update": "2024-06-12 16:08:16", + "author_account_age_days": 2772 + }, + "https://github.com/endman100/ComfyUI-SaveAndLoadPromptCondition": { + "stars": 0, + "last_update": "2024-06-06 06:07:49", + "author_account_age_days": 2473 + }, + "https://github.com/ericbeyer/guidance_interval": { + "stars": 2, + "last_update": "2024-04-16 03:24:01", + "author_account_age_days": 2594 + }, + "https://github.com/flowtyone/comfyui-flowty-lcm": { + "stars": 62, + "last_update": "2023-10-23 12:08:55", + "author_account_age_days": 273 + }, + "https://github.com/flyingdogsoftware/gyre_for_comfyui": { + "stars": 0, + "last_update": "2024-06-21 15:35:49", + "author_account_age_days": 2013 + }, + "https://github.com/foglerek/comfyui-cem-tools": { + "stars": 1, + "last_update": "2024-01-13 23:22:07", + "author_account_age_days": 4038 + }, + "https://github.com/gameltb/ComfyUI_paper_playground": { + "stars": 9, + "last_update": "2024-06-20 07:16:06", + "author_account_age_days": 4055 + }, + "https://github.com/gameltb/ComfyUI_stable_fast": { + "stars": 183, + "last_update": "2024-06-06 12:43:16", + "author_account_age_days": 4055 + }, + "https://github.com/gameltb/io_comfyui": { + "stars": 3, + "last_update": "2024-04-06 04:40:05", + "author_account_age_days": 4055 + }, + "https://github.com/githubYiheng/comfyui_median_filter": { + "stars": 0, + "last_update": "2024-05-24 15:21:40", + "author_account_age_days": 3903 + }, + "https://github.com/haofanwang/ComfyUI-InstantStyle": { + "stars": 5, + "last_update": "2024-05-23 16:11:13", + "author_account_age_days": 2977 + }, + "https://github.com/horidream/ComfyUI-Horidream": { + "stars": 0, + "last_update": "2024-06-18 02:09:07", + "author_account_age_days": 5043 + }, + "https://github.com/houdinii/comfy-magick": { + "stars": 4, + "last_update": "2024-03-11 06:40:54", + "author_account_age_days": 3520 + }, + "https://github.com/huchenlei/ComfyUI_densediffusion": { + "stars": 70, + "last_update": "2024-06-11 00:39:28", + "author_account_age_days": 2875 + }, + "https://github.com/huchenlei/ComfyUI_omost": { + "stars": 321, + "last_update": "2024-06-14 12:45:52", + "author_account_age_days": 2875 + }, + "https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui": { + "stars": 2, + "last_update": "2024-02-27 08:22:49", + "author_account_age_days": 2455 + }, + "https://github.com/hy134300/comfyui-hb-node": { + "stars": 0, + "last_update": "2024-04-09 09:56:22", + "author_account_age_days": 1761 + }, + "https://github.com/hy134300/comfyui-hydit": { + "stars": 7, + "last_update": "2024-06-07 09:52:15", + "author_account_age_days": 1761 + }, + "https://github.com/ilovejohnwhite/UncleBillyGoncho": { + "stars": 0, + "last_update": "2024-02-29 00:16:42", + "author_account_age_days": 873 + }, + "https://github.com/immersiveexperience/ie-comfyui-color-nodes": { + "stars": 2, + "last_update": "2024-06-18 10:54:55", + "author_account_age_days": 269 + }, + "https://github.com/jh-leon-kim/ComfyUI-JHK-utils": { + "stars": 0, + "last_update": "2024-06-04 08:57:52", + "author_account_age_days": 172 + }, + "https://github.com/jimmm-ai/TimeUi-a-ComfyUi-Timeline-Node": { + "stars": 194, + "last_update": "2024-06-12 20:10:22", + "author_account_age_days": 20 + }, + "https://github.com/jn-jairo/jn_node_suite_comfyui": { + "stars": 5, + "last_update": "2024-06-08 05:15:33", + "author_account_age_days": 3984 + }, + "https://github.com/jtscmw01/ComfyUI-DiffBIR": { + "stars": 61, + "last_update": "2024-05-21 05:28:34", + "author_account_age_days": 502 + }, + "https://github.com/jtydhr88/ComfyUI-Unique3D": { + "stars": 57, + "last_update": "2024-06-24 00:30:37", + "author_account_age_days": 4753 + }, + "https://github.com/kadirnar/ComfyUI-Adapter": { + "stars": 3, + "last_update": "2024-04-03 12:05:39", + "author_account_age_days": 2329 + }, + "https://github.com/kadirnar/comfyui_helpers": { + "stars": 2, + "last_update": "2024-03-04 16:25:30", + "author_account_age_days": 2329 + }, + "https://github.com/kappa54m/ComfyUI_Usability": { + "stars": 0, + "last_update": "2024-02-05 14:49:45", + "author_account_age_days": 1511 + }, + "https://github.com/kijai/ComfyUI-CV-VAE": { + "stars": 9, + "last_update": "2024-06-03 21:46:49", + "author_account_age_days": 2183 + }, + "https://github.com/kijai/ComfyUI-DeepSeek-VL": { + "stars": 19, + "last_update": "2024-05-21 16:43:40", + "author_account_age_days": 2183 + }, + "https://github.com/kijai/ComfyUI-DiffSynthWrapper": { + "stars": 22, + "last_update": "2024-06-22 00:16:46", + "author_account_age_days": 2183 + }, + "https://github.com/kijai/ComfyUI-DiffusersSD3Wrapper": { + "stars": 7, + "last_update": "2024-06-17 13:03:43", + "author_account_age_days": 2183 + }, + "https://github.com/kycg/comfyui-Kwtoolset": { + "stars": 0, + "last_update": "2024-06-12 17:04:09", + "author_account_age_days": 940 + }, + "https://github.com/laksjdjf/ssd-1b-comfyui": { + "stars": 1, + "last_update": "2023-10-27 20:05:06", + "author_account_age_days": 2831 + }, + "https://github.com/logtd/ComfyUI-MotionThiefExperiment": { + "stars": 36, + "last_update": "2024-05-22 00:12:06", + "author_account_age_days": 122 + }, + "https://github.com/longgui0318/comfyui-one-more-step": { + "stars": 1, + "last_update": "2024-05-07 08:40:56", + "author_account_age_days": 4165 + }, + "https://github.com/ltdrdata/ComfyUI-Workflow-Component": { + "stars": 195, + "last_update": "2024-04-26 01:39:09", + "author_account_age_days": 462 + }, + "https://github.com/marcueberall/ComfyUI-BuildPath": { + "stars": 0, + "last_update": "2024-02-06 07:57:33", + "author_account_age_days": 1782 + }, + "https://github.com/marduk191/comfyui-marnodes": { + "stars": 0, + "last_update": "2024-06-14 10:24:11", + "author_account_age_days": 4415 + }, + "https://github.com/maruhidd/ComfyUI_Transparent-Background": { + "stars": 1, + "last_update": "2024-06-14 07:02:56", + "author_account_age_days": 2255 + }, + "https://github.com/mashb1t/comfyui-nodes-mashb1t": { + "stars": 0, + "last_update": "2024-06-11 15:55:53", + "author_account_age_days": 3535 + }, + "https://github.com/mikeymcfish/FishTools": { + "stars": 12, + "last_update": "2024-06-21 20:35:44", + "author_account_age_days": 3403 + }, + "https://github.com/mingqizhang/ComfyUI_AEMatter_zmq": { + "stars": 0, + "last_update": "2024-06-24 07:22:59", + "author_account_age_days": 2594 + }, + "https://github.com/mut-ex/comfyui-gligengui-node": { + "stars": 30, + "last_update": "2024-02-28 02:46:05", + "author_account_age_days": 2858 + }, + "https://github.com/nat-chan/comfyui-eval": { + "stars": 1, + "last_update": "2024-05-28 11:56:37", + "author_account_age_days": 2993 + }, + "https://github.com/nat-chan/comfyui-in-memory-transceiver": { + "stars": 1, + "last_update": "2024-05-01 10:03:01", + "author_account_age_days": 2993 + }, + "https://github.com/nat-chan/comfyui-paint": { + "stars": 2, + "last_update": "2024-06-14 11:01:38", + "author_account_age_days": 2993 + }, + "https://github.com/nidefawl/ComfyUI-nidefawl": { + "stars": 0, + "last_update": "2024-01-16 18:16:41", + "author_account_age_days": 4868 + }, + "https://github.com/nkchocoai/ComfyUI-PromptUtilities": { + "stars": 6, + "last_update": "2024-06-23 04:58:30", + "author_account_age_days": 160 + }, + "https://github.com/norgeous/ComfyUI-UI-Builder": { + "stars": 2, + "last_update": "2024-06-24 13:55:40", + "author_account_age_days": 4029 + }, + "https://github.com/oyvindg/ComfyUI-TrollSuite": { + "stars": 0, + "last_update": "2024-05-22 21:32:03", + "author_account_age_days": 2329 + }, + "https://github.com/oztrkoguz/ComfyUI_Kosmos2_BBox_Cutter": { + "stars": 13, + "last_update": "2024-05-03 10:52:29", + "author_account_age_days": 841 + }, + "https://github.com/pamparamm/ComfyUI-ppm": { + "stars": 3, + "last_update": "2024-06-15 15:19:13", + "author_account_age_days": 2131 + }, + "https://github.com/phineas-pta/comfy-trt-test": { + "stars": 83, + "last_update": "2024-06-04 21:09:17", + "author_account_age_days": 2288 + }, + "https://github.com/poisenbery/NudeNet-Detector-Provider": { + "stars": 1, + "last_update": "2024-02-26 02:11:27", + "author_account_age_days": 1237 + }, + "https://github.com/prabinpebam/anyPython": { + "stars": 3, + "last_update": "2024-06-21 16:58:16", + "author_account_age_days": 4242 + }, + "https://github.com/prismwastaken/comfyui-tools": { + "stars": 0, + "last_update": "2024-03-05 14:34:56", + "author_account_age_days": 157 + }, + "https://github.com/pzzmyc/comfyui-sd3-simple-simpletuner": { + "stars": 1, + "last_update": "2024-06-19 12:48:18", + "author_account_age_days": 2099 + }, + "https://github.com/redhottensors/ComfyUI-ODE": { + "stars": 12, + "last_update": "2024-06-23 22:16:53", + "author_account_age_days": 139 + }, + "https://github.com/romeobuilderotti/ComfyUI-EZ-Pipes": { + "stars": 3, + "last_update": "2023-11-15 22:00:49", + "author_account_age_days": 290 + }, + "https://github.com/runtime44/comfyui_r44_nodes": { + "stars": 28, + "last_update": "2024-06-11 10:49:02", + "author_account_age_days": 168 + }, + "https://github.com/sangeet/comfyui-testui": { + "stars": 2, + "last_update": "2024-05-15 00:55:17", + "author_account_age_days": 5080 + }, + "https://github.com/sdfxai/SDFXBridgeForComfyUI": { + "stars": 6, + "last_update": "2024-06-14 10:26:56", + "author_account_age_days": 235 + }, + "https://github.com/shadowcz007/ComfyUI-PuLID-Test": { + "stars": 8, + "last_update": "2024-05-12 14:37:28", + "author_account_age_days": 3314 + }, + "https://github.com/shadowcz007/comfyui-CLIPSeg": { + "stars": 1, + "last_update": "2024-02-08 02:16:24", + "author_account_age_days": 3314 + }, + "https://github.com/shadowcz007/comfyui-llamafile": { + "stars": 15, + "last_update": "2024-05-21 19:47:56", + "author_account_age_days": 3314 + }, + "https://github.com/shadowcz007/comfyui-musicgen": { + "stars": 54, + "last_update": "2024-06-20 02:07:31", + "author_account_age_days": 3314 + }, + "https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4": { + "stars": 0, + "last_update": "2024-04-27 13:25:08", + "author_account_age_days": 3962 + }, + "https://github.com/sofakid/dandy": { + "stars": 30, + "last_update": "2024-05-27 21:46:18", + "author_account_age_days": 4053 + }, + "https://github.com/stavsap/ComfyUI-React-SDK": { + "stars": 6, + "last_update": "2024-03-17 21:54:21", + "author_account_age_days": 4084 + }, + "https://github.com/stutya/ComfyUI-Terminal": { + "stars": 0, + "last_update": "2024-02-05 16:47:28", + "author_account_age_days": 3838 + }, + "https://github.com/sugarkwork/comfyui_psd": { + "stars": 1, + "last_update": "2024-03-26 08:24:56", + "author_account_age_days": 875 + }, + "https://github.com/tachyon-beep/comfyui-simplefeed": { + "stars": 3, + "last_update": "2024-05-22 03:30:57", + "author_account_age_days": 4921 + }, + "https://github.com/talesofai/comfyui-supersave": { + "stars": 1, + "last_update": "2023-12-27 02:05:53", + "author_account_age_days": 556 + }, + "https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes": { + "stars": 0, + "last_update": "2024-03-05 13:31:31", + "author_account_age_days": 113 + }, + "https://github.com/tracerstar/comfyui-p5js-node": { + "stars": 28, + "last_update": "2024-05-30 18:33:55", + "author_account_age_days": 5198 + }, + "https://github.com/tuckerdarby/ComfyUI-TDNodes": { + "stars": 3, + "last_update": "2024-02-19 17:00:55", + "author_account_age_days": 2938 + }, + "https://github.com/umisetokikaze/comfyui_mergekit": { + "stars": 0, + "last_update": "2024-04-28 07:21:00", + "author_account_age_days": 1823 + }, + "https://github.com/unanan/ComfyUI-Dist": { + "stars": 5, + "last_update": "2024-02-28 10:03:50", + "author_account_age_days": 2898 + }, + "https://github.com/unanan/ComfyUI-clip-interrogator": { + "stars": 22, + "last_update": "2024-02-01 09:46:57", + "author_account_age_days": 1030 + }, + "https://github.com/wormley/comfyui-wormley-nodes": { + "stars": 0, + "last_update": "2023-11-12 19:05:11", + "author_account_age_days": 2473 + }, + "https://github.com/yushan777/ComfyUI-Y7Nodes": { + "stars": 1, + "last_update": "2024-06-23 22:36:49", + "author_account_age_days": 517 + }, + "https://github.com/zmwv823/ComfyUI-AnyText": { + "stars": 42, + "last_update": "2024-06-23 15:52:12", + "author_account_age_days": 3269 + } +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/dev/model-list.json b/custom_nodes/ComfyUI-Manager/node_db/dev/model-list.json new file mode 100644 index 000000000..8e3e1dc48 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/dev/model-list.json @@ -0,0 +1,3 @@ +{ + "models": [] +} diff --git a/custom_nodes/ComfyUI-Manager/node_db/dev/scan.sh b/custom_nodes/ComfyUI-Manager/node_db/dev/scan.sh new file mode 100644 index 000000000..f9589f3c5 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/dev/scan.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rm ~/.tmp/dev/*.py > /dev/null 2>&1 +python ../../scanner.py ~/.tmp/dev diff --git a/custom_nodes/ComfyUI-Manager/node_db/forked/custom-node-list.json b/custom_nodes/ComfyUI-Manager/node_db/forked/custom-node-list.json new file mode 100644 index 000000000..554591143 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/forked/custom-node-list.json @@ -0,0 +1,54 @@ +{ + "custom_nodes": [ + { + "author": "meimeilook", + "title": "ComfyUI_IPAdapter_plus.old [backward compatbility]", + "reference": "https://github.com/meimeilook/ComfyUI_IPAdapter_plus.old", + "files": [ + "https://github.com/meimeilook/ComfyUI_IPAdapter_plus.old" + ], + "install_type": "git-clone", + "description": "This repo is created to provide backward compatibility for workflows configured with the old IPAdapter." + }, + { + "author": "ZHO-ZHO-ZHO", + "title": "Dr.Lt.Data/ComfyUI-YoloWorld-EfficientSAM", + "reference": "https://github.com/ltdrdata/ComfyUI-YoloWorld-EfficientSAM", + "files": [ + "https://github.com/ltdrdata/ComfyUI-YoloWorld-EfficientSAM" + ], + "install_type": "git-clone", + "description": "This fork includes [a/PR32](https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM/pull/32)" + }, + { + "author": "ertu110", + "title": "sdxl_prompt_style", + "reference": "https://github.com/ertu110/sdxl_prompt_style", + "files": [ + "https://github.com/ertu110/sdxl_prompt_style" + ], + "install_type": "git-clone", + "description": "This project is a complete benchmark [a/https://github.com/twri/sdxl_prompt_styler](https://github.com/twri/sdxl_prompt_styler) A large amount of code inside comes from https://github.com/twri/sdxl_prompt_styler Project and [a/https://www.nodecafe.org/package/pythongosssss_ComfyUI-Custom-Scripts](https://www.nodecafe.org/package/pythongosssss_ComfyUI-Custom-Scripts) project\nThe functionality of this project is related to https://github.com/twri/sdxl_prompt_styler Highly overlapping, the only purpose of creating this project is because there are too many styles when selecting, resulting in a long and inconvenient dropdown box. Therefore, To address this issue, this project has added a secondary menu to the style." + }, + { + "author": "gustproof", + "title": "ComfyUI_IPAdapter_plus_Style_Components", + "reference": "https://github.com/gustproof/ComfyUI_IPAdapter_plus_Style_Components", + "files": [ + "https://github.com/gustproof/ComfyUI_IPAdapter_plus_Style_Components" + ], + "install_type": "git-clone", + "description": "Style Components is an IP-Adapter model conditioned on anime styles. The style embeddings can either be extracted from images or created manually. This repo currently only supports the SDXL model trained on AutismmixPony." + }, + { + "author": "gameltb", + "title": "comfyui-stablsr", + "reference": "https://github.com/gameltb/Comfyui-StableSR", + "files": [ + "https://github.com/gameltb/Comfyui-StableSR" + ], + "install_type": "git-clone", + "description": "This is a development respository for debugging migration of StableSR to ComfyUI\n\nNOTE:Forked from [https://github.com/gameltb/Comfyui-StableSR]\nPut the StableSR [a/webui_786v_139.ckpt](https://huggingface.co/Iceclear/StableSR/resolve/main/webui_768v_139.ckpt) model into Comyfui/models/stablesr/, Put the StableSR [a/stablesr_768v_000139.ckpt](https://huggingface.co/Iceclear/StableSR/resolve/main/stablesr_768v_000139.ckpt) model into Comyfui/models/checkpoints/" + } + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/forked/extension-node-map.json b/custom_nodes/ComfyUI-Manager/node_db/forked/extension-node-map.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/forked/extension-node-map.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/forked/model-list.json b/custom_nodes/ComfyUI-Manager/node_db/forked/model-list.json new file mode 100644 index 000000000..8e3e1dc48 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/forked/model-list.json @@ -0,0 +1,3 @@ +{ + "models": [] +} diff --git a/custom_nodes/ComfyUI-Manager/node_db/forked/scan.sh b/custom_nodes/ComfyUI-Manager/node_db/forked/scan.sh new file mode 100644 index 000000000..5d8d8c48b --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/forked/scan.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source ../../../../venv/bin/activate +rm .tmp/*.py > /dev/null +python ../../scanner.py diff --git a/custom_nodes/ComfyUI-Manager/node_db/legacy/alter-list.json b/custom_nodes/ComfyUI-Manager/node_db/legacy/alter-list.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/legacy/alter-list.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/legacy/custom-node-list.json b/custom_nodes/ComfyUI-Manager/node_db/legacy/custom-node-list.json new file mode 100644 index 000000000..334346935 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/legacy/custom-node-list.json @@ -0,0 +1,587 @@ +{ + "custom_nodes": [ + { + "author": "#NOTICE_1.13", + "title": "NOTICE: This channel is not the default channel.", + "reference": "https://github.com/ltdrdata/ComfyUI-Manager", + "files": [], + "install_type": "git-clone", + "description": "If you see this message, your ComfyUI-Manager is outdated.\nLegacy channel provides only the list of the deprecated nodes. If you want to find the complete node list, please go to the Default channel." + }, + + + { + "author": "turkyden", + "title": "ComfyUI-Sticker [REMOVED]", + "reference": "https://github.com/turkyden/ComfyUI-Sticker", + "files": [ + "https://github.com/turkyden/ComfyUI-Sticker" + ], + "install_type": "git-clone", + "description": "image to sticker" + }, + { + "author": "turkyden", + "title": "ComfyUI-Comic [REMOVED]", + "id": "comic", + "reference": "https://github.com/turkyden/ComfyUI-Comic", + "files": [ + "https://github.com/turkyden/ComfyUI-Comic" + ], + "install_type": "git-clone", + "description": "a comfyui plugin for image to comic" + }, + { + "author": "turkyden", + "title": "ComfyUI-Avatar [REMOVED]", + "id": "avatar", + "reference": "https://github.com/turkyden/ComfyUI-Avatar", + "files": [ + "https://github.com/turkyden/ComfyUI-Avatar" + ], + "install_type": "git-clone", + "description": "a comfyui plugin for image to avatar" + }, + { + "author": "bvhari", + "title": "LatentToRGB [DEPRECATED]", + "id": "latent2rgb", + "reference": "https://github.com/bvhari/ComfyUI_LatentToRGB", + "files": [ + "https://github.com/bvhari/ComfyUI_LatentToRGB" + ], + "install_type": "git-clone", + "description": "ComfyUI custom node to convert latent to RGB.\nNOTE:This repo has been archived because ComfyUI natively has similar functionality now" + }, + { + "author": "Kaharos94", + "title": "ComfyUI-Saveaswebp [DEPRECATED]", + "id": "save-webp", + "reference": "https://github.com/Kaharos94/ComfyUI-Saveaswebp", + "files": [ + "https://github.com/Kaharos94/ComfyUI-Saveaswebp" + ], + "install_type": "git-clone", + "description": "Save a picture as Webp file in Comfy + Workflow loading" + }, + { + "author": "udi0510", + "title": "comfyui-slicer [REMOVED]", + "id": "slicer", + "reference": "https://github.com/udi0510/comfyui-slicer", + "files": [ + "https://github.com/udi0510/comfyui-slicer" + ], + "install_type": "git-clone", + "description": "Nodes:SlicerNode" + }, + { + "author": "logtd", + "title": "ComfyUI-FLATTEN [REMOVED]", + "id": "flatten", + "reference": "https://github.com/logtd/ComfyUI-FlattenFlow", + "files": [ + "https://github.com/logtd/ComfyUI-FlattenFlow" + ], + "install_type": "git-clone", + "description": "An alternate trajectory processor for ComfyUI-FLATTEN\nNOTE:When using this trajectory type FLATTEN will use roughly 1/4 VRAM and be ~20% faster at the cost of some consistency (especially when injection_steps are low)." + }, + { + "author": "MackinationsAi", + "title": "ComfyUi_Stuctured-Outputs [REMOVED]", + "id": "struct-output", + "reference": "https://github.com/MackinationsAi/ComfyUi_Stuctured-Outputs", + "files": [ + "https://github.com/MackinationsAi/ComfyUi_Stuctured-Outputs" + ], + "install_type": "git-clone", + "description": "This repository contains a custom node for ComfyUI that allows users to save generative image outputs with custom filenames and folder structures. The filenames are padded to four digits, and the positive and negative prompts are embedded in the image metadata." + }, + { + "author": "laksjdjf", + "title": "attention-couple-ComfyUI [DEPRECATED]", + "id": "attention-couple", + "reference": "https://github.com/laksjdjf/attention-couple-ComfyUI", + "files": [ + "https://github.com/laksjdjf/attention-couple-ComfyUI" + ], + "install_type": "git-clone", + "description": "Nodes:Attention couple. This is a custom node that manipulates region-specific prompts. While vanilla ComfyUI employs an area specification method based on latent couples, this node divides regions using attention layers within UNet.\nNOTE: This has been integrated with cgem156-ComfyUI." + }, + { + "author": "phineas-pta", + "title": "comfy-trt-test [DEPRECATED]", + "reference": "https://github.com/phineas-pta/comfy-trt-test", + "files": [ + "https://github.com/phineas-pta/comfy-trt-test" + ], + "install_type": "git-clone", + "description": "Test project for ComfyUI TensorRT Support.\nNOT WORKING YET.\nnot automatic yet, do not use ComfyUI-Manager to install !!!.\nnot beginner-friendly yet, still intended to technical users\nNOTE: The reason for registration in the Manager is for guidance, and for detailed installation instructions, please visit the repository.\nNOTE: Use 'TensorRT Node for ComfyUI' instead of this." + }, + { + "author": "dezi-ai", + "title": "ComfyUI Animate LCM [NOT MAINTAINED]", + "reference": "https://github.com/dezi-ai/ComfyUI-AnimateLCM", + "files": [ + "https://github.com/dezi-ai/ComfyUI-AnimateLCM" + ], + "install_type": "git-clone", + "description": "ComfyUI implementation for [a/AnimateLCM](https://animatelcm.github.io/) [[a/paper](https://arxiv.org/abs/2402.00769)].\b[w/This extension includes a large number of nodes imported from the existing custom nodes, increasing the likelihood of conflicts.]" + }, + { + "author": "christian-byrne", + "title": "elimination-nodes [REMOVED]", + "reference": "https://github.com/christian-byrne/elimination-nodes", + "files": [ + "https://github.com/christian-byrne/elimination-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Paste Cutout on Base Image" + }, + { + "author": "Levy1417", + "title": "Universal-Data-Processing-Kit [UNSAFE] [REMOVED]", + "reference": "https://github.com/Levy1417/Universal-Data-Processing-Kit", + "files": [ + "https://github.com/Levy1417/Universal-Data-Processing-Kit" + ], + "install_type": "git-clone", + "description": "Nodes:DPK - Any Eval, DPK - Extract Array, DPK - Run External Program, DPK - Any Literals, DPK - Set Node States, DPK - Realtime Text Preview, DPK - Dynamic Action, DPK - Object To Json, DPK - Json To Object\n[w/This extension includes the ability to execute arbitrary code and programs.]" + }, + { + "author": "liusida", + "title": "ComfyUI-Sida-Remove-Image [UNSAFE] [REMOVED]", + "reference": "https://github.com/liusida/ComfyUI-Sida-Remove-Image", + "files": [ + "https://github.com/liusida/ComfyUI-Sida-Remove-Image" + ], + "install_type": "git-clone", + "description": "Nodes: LoadImageWithPrivacy, RemoveImage.[w/This extension is not secure because it provides the capability to delete files from arbitrary paths.]" + }, + { + "author": "88IO", + "title": "ComfyUI Image Reordering Plugins [REMOVED]", + "reference": "https://github.com/88IO/ComfyUI-ImageReorder", + "files": [ + "https://github.com/88IO/ComfyUI-ImageReorder" + ], + "install_type": "git-clone", + "description": "A custom node reorder multiple image frames based on indexes or curves." + }, + { + "author": "jtydhr88", + "title": "ComfyUI-InstantMesh [DEPRECATED]", + "id": "instant-mesh", + "reference": "https://github.com/jtydhr88/ComfyUI-InstantMesh", + "files": [ + "https://github.com/jtydhr88/ComfyUI-InstantMesh" + ], + "install_type": "git-clone", + "description": "ComfyUI InstantMesh is custom nodes that running TencentARC/InstantMesh into ComfyUI, this extension depends on ComfyUI-3D-Pack. Please refer to Readme carefully to install.\nNOTE: This repo is archived due to ComfyUI-3D-Pack supports InstantMesh, please check 3D-Pack directly if you need it" + }, + { + "author": "biegert", + "title": "CLIPSeg [NOT MAINTAINED]", + "id": "clipseg", + "reference": "https://github.com/biegert/ComfyUI-CLIPSeg", + "files": [ + "https://github.com/biegert/ComfyUI-CLIPSeg/raw/main/custom_nodes/clipseg.py" + ], + "install_type": "copy", + "description": "The CLIPSeg node generates a binary mask for a given input image and text prompt." + }, + { + "author": "tankucc1no", + "title": "ComfyUI-Dragdiffusion [REMOVED]", + "id": "dragdiffusion", + "reference": "https://github.com/tankucc1no/ComfyUI-Dragdiffusion", + "files": [ + "https://github.com/tankucc1no/ComfyUI-Dragdiffusion" + ], + "install_type": "git-clone", + "description": "Implementation of [a/Dragdiffusion](https://github.com/Yujun-Shi/DragDiffusion) in ComfyUI." + }, + { + "author": "wibur0620", + "title": "ComfyUI Ollama (wibur) [REMOVED]", + "id": "ollama-wibur", + "reference": "https://github.com/wibur0620/comfyui-ollama-wibur", + "files": [ + "https://github.com/wibur0620/comfyui-ollama-wibur" + ], + "install_type": "git-clone", + "description": "Custom ComfyUI Nodes for interacting with [a/Ollama](https://ollama.com/) using the ollama python client.\nIntegrate the power of LLMs into ComfyUI workflows easily or just experiment with GPT.\nNOTE: To use this properly, you would need a running Ollama server reachable from the host that is running ComfyUI." + }, + { + "author": "IKHOR", + "title": "ikhor-nodes [REMOVED]", + "reference": "https://github.com/IKHOR/ComfyUI-IKHOR-Jam-Nodes", + "files": [ + "https://github.com/IKHOR/ComfyUI-IKHOR-Jam-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:LoadFromS3, LoadBatchFromS3, SaveToS3, SaveBatchToS3" + }, + { + "author": "kijai", + "title": "ComfyUI wrapper nodes for IC-light [DEPRECATED]", + "reference": "https://github.com/kijai/ComfyUI-IC-Light-Wrapper", + "files": [ + "https://github.com/kijai/ComfyUI-IC-Light-Wrapper" + ], + "install_type": "git-clone", + "description": "Stopped. Original repo: [a/https://github.com/lllyasviel/IC-Light](https://github.com/lllyasviel/IC-Light)" + }, + { + "author": "thedyze", + "title": "Save Image Extended for ComfyUI", + "reference": "https://github.com/thedyze/save-image-extended-comfyui", + "files": [ + "https://github.com/thedyze/save-image-extended-comfyui" + ], + "install_type": "git-clone", + "description": "Customize the information saved in file- and folder names. Use the values of sampler parameters as part of file or folder names. Save your positive & negative prompt as entries in a JSON (text) file, in each folder.\n[w/This custom node has not been maintained for a long time. Please use an alternative node from the default channel.]" + }, + { + "author": "ExponentialML", + "title": "ComfyUI_ELLA [DEPRECATED]", + "reference": "https://github.com/ExponentialML/ComfyUI_ELLA", + "files": [ + "https://github.com/ExponentialML/ComfyUI_ELLA" + ], + "install_type": "git-clone", + "description": "ComfyUI Implementaion of ELLA: Equip Diffusion Models with LLM for Enhanced Semantic Alignment.[w/Officially implemented here: [a/https://github.com/TencentQQGYLab/ComfyUI-ELLA](https://github.com/TencentQQGYLab/ComfyUI-ELLA)]" + }, + { + "author": "shinich39", + "title": "comfyui-text-pipe-39 [DEPRECATED]", + "reference": "https://github.com/shinich39/comfyui-text-pipe-39", + "files": [ + "https://github.com/shinich39/comfyui-text-pipe-39" + ], + "install_type": "git-clone", + "description": "Modify text by condition." + }, + { + "author": "Big Idea Technology", + "title": "Image Text Overlay Node for ComfyUI [DEPRECATED]", + "reference": "https://github.com/Big-Idea-Technology/ComfyUI_Image_Text_Overlay", + "files": [ + "https://github.com/Big-Idea-Technology/ComfyUI_Image_Text_Overlay" + ], + "install_type": "git-clone", + "description": "Please note that the ImageTextOverlay project is no longer supported and has been moved to a new repository. For ongoing developments, contributions, and issues, please refer to the new repository at: [a/https://github.com/Big-Idea-Technology/ComfyUI-Book-Tools](https://github.com/Big-Idea-Technology/ComfyUI-Book-Tools)" + }, + { + "author": "mlinmg", + "title": "LaMa Preprocessor [DEPRECATED]", + "reference": "https://github.com/mlinmg/ComfyUI-LaMA-Preprocessor", + "files": [ + "https://github.com/mlinmg/ComfyUI-LaMA-Preprocessor" + ], + "install_type": "git-clone", + "description": "A LaMa prerocessor for ComfyUI. This preprocessor finally enable users to generate coherent inpaint and outpaint prompt-free. The best results are given on landscapes, not so much in drawings/animation." + }, + { + "author": "CapsAdmin", + "title": "ComfyUI-Euler-Smea-Dyn-Sampler [DEPRECATED]", + "reference": "https://github.com/CapsAdmin/ComfyUI-Euler-Smea-Dyn-Sampler", + "files": [ + "https://github.com/CapsAdmin/ComfyUI-Euler-Smea-Dyn-Sampler" + ], + "install_type": "git-clone", + "description": "Just a comfyui version of [a/Euler Smea Dyn Sampler](https://github.com/Koishi-Star/Euler-Smea-Dyn-Sampler). It adds the sampler directly to existing samplers." + }, + { + "author": "BlakeOne", + "title": "ComfyUI FastImageListToImageBatch [REMOVED]", + "reference": "https://github.com/BlakeOne/ComfyUI-FastImageListToImageBatch", + "files": [ + "https://github.com/BlakeOne/ComfyUI-FastImageListToImageBatch" + ], + "install_type": "git-clone", + "description": "Quickly convert a list of images to a batch of images. All images must be the same size. Great for long videos." + }, + { + "author": "ggpid", + "title": "idpark_custom_node [REMOVED]", + "reference": "https://github.com/ggpid/idpark_custom_node", + "files": [ + "https://github.com/ggpid/idpark_custom_node" + ], + "install_type": "git-clone", + "description": "Nodes:Load Image from S3, Save Image to S3, Generate SAM, Generate FastSAM, Cut by Mask fixed" + }, + { + "author": "Davemane42", + "title": "Visual Area Conditioning / Latent composition [DEPRECATED]", + "reference": "https://github.com/Davemane42/ComfyUI_Dave_CustomNode", + "files": [ + "https://github.com/Davemane42/ComfyUI_Dave_CustomNode" + ], + "install_type": "git-clone", + "description": "This tool provides custom nodes that allow visualization and configuration of area conditioning and latent composite." + }, + { + "author": "laksjdjf", + "title": "LoRA-Merger-ComfyUI [DEPRECATED]", + "reference": "https://github.com/laksjdjf/LoRA-Merger-ComfyUI", + "files": [ + "https://github.com/laksjdjf/LoRA-Merger-ComfyUI" + ], + "install_type": "git-clone", + "description": "Nodes:Load LoRA Weight Only, Load LoRA from Weight, Merge LoRA, Save LoRA. This extension provides nodes for merging LoRA." + }, + { + "author": "kinfolk0117", + "title": "TiledIPAdapter [DEPRECATED]", + "reference": "https://github.com/kinfolk0117/ComfyUI_TiledIPAdapter", + "files": [ + "https://github.com/kinfolk0117/ComfyUI_TiledIPAdapter" + ], + "install_type": "git-clone", + "description": "Proof of concent on how to use IPAdapter to control tiled upscaling. NOTE: You need to have 'ComfyUI_IPAdapter_plus' installed." + }, + { + "author": "XINZHANG-ops", + "title": "comfyui-xin-nodes [REMOVED]", + "reference": "https://github.com/XINZHANG-ops/comfyui-xin-nodes", + "files": [ + "https://github.com/XINZHANG-ops/comfyui-xin-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:ImageSizeClassifer, RandomInt, ShowValue" + }, + { + "author": "ssitu", + "title": "NestedNodeBuilder [DEPRECATED]", + "reference": "https://github.com/ssitu/ComfyUI_NestedNodeBuilder", + "files": [ + "https://github.com/ssitu/ComfyUI_NestedNodeBuilder" + ], + "install_type": "git-clone", + "description": "This extension provides the ability to combine multiple nodes into a single node.\nNOTE:An identical feature now exists in ComfyUI. Additionally, this extension is largely broken with the recent versions of the codebase, so please use the built-in feature for group nodes." + }, + { + "author": "ccvv804", + "title": "ComfyUI StableCascade using diffusers for Low VRAM [DEPRECATED]", + "reference": "https://github.com/ccvv804/ComfyUI-DiffusersStableCascade-LowVRAM", + "files": [ + "https://github.com/ccvv804/ComfyUI-DiffusersStableCascade-LowVRAM" + ], + "install_type": "git-clone", + "description": "Works with RTX 4070ti 12GB.\nSimple quick wrapper for [a/https://huggingface.co/stabilityai/stable-cascade](https://huggingface.co/stabilityai/stable-cascade)\nComfy is going to implement this properly soon, this repo is just for quick testing for the impatient!" + }, + { + "author": "kijai", + "title": "ComfyUI StableCascade using diffusers [DEPRECATED]", + "reference": "https://github.com/kijai/ComfyUI-DiffusersStableCascade", + "files": [ + "https://github.com/kijai/ComfyUI-DiffusersStableCascade" + ], + "install_type": "git-clone", + "description": "Simple quick wrapper for [a/https://huggingface.co/stabilityai/stable-cascade](https://huggingface.co/stabilityai/stable-cascade)\nComfy is going to implement this properly soon, this repo is just for quick testing for the impatient!" + }, + { + "author": "solarpush", + "title": "comfyui_sendimage_node [REMOVED]", + "reference": "https://github.com/solarpush/comfyui_sendimage_node", + "files": [ + "https://github.com/solarpush/comfyui_sendimage_node" + ], + "install_type": "git-clone", + "description": "Send images to the pod." + }, + { + "author": "azazeal04", + "title": "ComfyUI-Styles", + "reference": "https://github.com/azazeal04/ComfyUI-Styles", + "files": [ + "https://github.com/azazeal04/ComfyUI-Styles" + ], + "install_type": "git-clone", + "description": "Nodes:Anime_Styler, Fantasy_Styler, Gothic_Styler, Line_Art_Styler, Movie_Poster_Styler, Punk_Styler, Travel_Poster_Styler. This extension offers 8 art style nodes, each of which includes approximately 50 individual style variations.\n\nNOTE: Due to the dynamic nature of node name definitions, ComfyUI-Manager cannot recognize the node list from this extension. The Missing nodes and Badge features are not available for this extension.\nNOTE: This extension is removed. Users who were previously using this node should install ComfyUI-styles-all instead." + }, + { + "author": "hnmr293", + "title": "ComfyUI-nodes-hnmr", + "reference": "https://github.com/hnmr293/ComfyUI-nodes-hnmr", + "files": [ + "https://github.com/hnmr293/ComfyUI-nodes-hnmr" + ], + "install_type": "git-clone", + "description": "Provide various custom nodes for Latent, Sampling, Model, Loader, Image, Text" + }, + { + "author": "bvhari", + "title": "ComfyUI_PerpNeg [WIP]", + "reference": "https://github.com/bvhari/ComfyUI_PerpNeg", + "files": [ + "https://github.com/bvhari/ComfyUI_PerpNeg" + ], + "install_type": "git-clone", + "description": "Nodes: KSampler (Advanced + Perp-Neg). Implementation of [a/Perp-Neg](https://perp-neg.github.io/)\nIncludes Tonemap and CFG Rescale optionsComfyUI custom node to convert latent to RGB.[w/WARNING: Experimental code, might have incompatibilities and edge cases.]\nNOTE: In the latest version of ComfyUI, this extension is included as built-in." + }, + { + "author": "laksjdjf", + "title": "IPAdapter-ComfyUI", + "reference": "https://github.com/laksjdjf/IPAdapter-ComfyUI", + "files": [ + "https://github.com/laksjdjf/IPAdapter-ComfyUI" + ], + "install_type": "git-clone", + "description": "This custom nodes provides loader of the IP-Adapter model.[w/NOTE: To use this extension node, you need to download the [a/ip-adapter_sd15.bin](https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15.bin) file and place it in the %%**custom_nodes/IPAdapter-ComfyUI/models**%% directory. Additionally, you need to download the 'Clip vision model' from the 'Install models' menu as well.]
      NOTE: Use ComfyUI_IPAdapter_plus instead of this." + }, + { + "author": "RockOfFire", + "title": "CR Animation Nodes", + "reference": "https://github.com/RockOfFire/CR_Animation_Nodes", + "files": [ + "https://github.com/RockOfFire/CR_Animation_Nodes" + ], + "install_type": "git-clone", + "description": "A comprehensive suite of nodes to enhance your animations. These nodes include some features similar to Deforum, and also some new ideas.
      NOTE: This node is merged into Comfyroll Custom Nodes." + }, + { + "author": "tkoenig89", + "title": "Load Image with metadata", + "reference": "https://github.com/tkoenig89/ComfyUI_Load_Image_With_Metadata", + "files": [ + "https://github.com/tkoenig89/ComfyUI_Load_Image_With_Metadata" + ], + "install_type": "git-clone", + "description": "A custom node for comfy ui to read generation data from images (prompt, seed, size...). This could be used when upscaling generated images to use the original prompt and seed." + }, + { + "author": "LucianoCirino", + "title": "Efficiency Nodes for ComfyUI [LEGACY]", + "reference": "https://github.com/LucianoCirino/efficiency-nodes-comfyui", + "files": [ + "https://github.com/LucianoCirino/efficiency-nodes-comfyui" + ], + "install_type": "git-clone", + "description": "A collection of ComfyUI custom nodes to help streamline workflows and reduce total node count.
      NOTE: This repository is the original repository but is no longer maintained. Please use the forked version by jags." + }, + { + "author": "GeLi1989", + "title": "roop nodes for ComfyUI", + "reference": "https://github.com/GeLi1989/GK-beifen-ComfyUI_roop", + "files": [ + "https://github.com/GeLi1989/GK-beifen-ComfyUI_roop" + ], + "install_type": "git-clone", + "description": "ComfyUI nodes for the roop A1111 webui script. NOTE: Need to download
      model to use this node. NOTE: This is removed." + }, + { + "author": "ProDALOR", + "title": "comfyui_u2net", + "reference": "https://github.com/ProDALOR/comfyui_u2net", + "files": [ + "https://github.com/ProDALOR/comfyui_u2net" + ], + "install_type": "git-clone", + "description": "Nodes: Load U2Net model, U2Net segmentation, To mask, Segmentation to mask, U2NetBaseNormalization, U2NetMaxNormalization. NOTE: This is removed." + }, + { + "author": "FizzleDorf", + "title": "AIT", + "reference": "https://github.com/FizzleDorf/AIT", + "files": [ + "https://github.com/FizzleDorf/AIT" + ], + "install_type": "git-clone", + "description": "Nodes: Load AITemplate, Load AITemplate (ControlNet), VAE Decode (AITemplate), VAE Encode (AITemplate), VAE Encode (AITemplate, Inpaint). Experimental usage of AITemplate. NOTE: This is deprecated extension. Use ComfyUI-AIT instead of this." + }, + { + "author": "chenbaiyujason", + "title": "sc-node-comfyui", + "reference": "https://github.com/chenbaiyujason/sc-node-comfyui", + "files": [ + "https://github.com/chenbaiyujason/sc-node-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes for GPT interaction and text manipulation" + }, + { + "author": "asd417", + "title": "CheckpointTomeLoader", + "reference": "https://github.com/asd417/tomeSD_for_Comfy", + "files": [ + "https://github.com/ltdrdata/ComfyUI-tomeSD-installer" + ], + "install_type": "git-clone", + "description": "tomeSD(https://github.com/dbolya/tomesd) applied to ComfyUI stable diffusion UI using custom node. Note:In vanilla ComfyUI, the TomePatchModel node is provided as a built-in feature." + }, + { + "author": "gamert", + "title": "ComfyUI_tagger", + "reference": "https://github.com/gamert/ComfyUI_tagger", + "pip": ["gradio"], + "files": [ + "https://github.com/gamert/ComfyUI_tagger" + ], + "install_type": "git-clone", + "description": "Nodes: CLIPTextEncodeTaggerDD, ImageTaggerDD.

      WARNING: Installing the current version is causing an issue where ComfyUI fails to start.

      " + }, + { + "author": "Fannovel16", + "title": "ControlNet Preprocessors", + "reference": "https://github.com/Fannovel16/comfy_controlnet_preprocessors", + "files": [ + "https://github.com/Fannovel16/comfy_controlnet_preprocessors" + ], + "install_type": "git-clone", + "description": "ControlNet Preprocessors. (To use this extension, you need to download the required model file from Install Models)

      NOTE: Please uninstall this custom node and instead install 'ComfyUI's ControlNet Auxiliary Preprocessors' from the default channel.
      To use nodes belonging to controlnet v1 such as Canny_Edge_Preprocessor, MIDAS_Depth_Map_Preprocessor, Uniformer_SemSegPreprocessor, etc., you need to copy the config.yaml.example file to config.yaml and change skip_v1: True to skip_v1: False.

      " + }, + { + "author": "comfyanonymous", + "title": "ComfyUI_experiments/sampler_tonemap", + "reference": "https://github.com/comfyanonymous/ComfyUI_experiments", + "files": [ + "https://github.com/comfyanonymous/ComfyUI_experiments/raw/master/sampler_tonemap.py" + ], + "install_type": "copy", + "description": "ModelSamplerTonemapNoiseTest a node that makes the sampler use a simple tonemapping algorithm to tonemap the noise. It will let you use higher CFG without breaking the image. To using higher CFG lower the multiplier value. Similar to Dynamic Thresholding extension of A1111. " + }, + { + "author": "comfyanonymous", + "title": "ComfyUI_experiments/sampler_rescalecfg", + "reference": "https://github.com/comfyanonymous/ComfyUI_experiments", + "files": [ + "https://github.com/comfyanonymous/ComfyUI_experiments/raw/master/sampler_rescalecfg.py" + ], + "install_type": "copy", + "description": "RescaleClassifierFreeGuidance improves the problem of images being degraded by high CFG.To using higher CFG lower the multiplier value. Similar to Dynamic Thresholding extension of A1111. (reference paper)

      It is recommended to use the integrated custom nodes in the default channel for update support rather than installing individual nodes.

      " + }, + { + "author": "comfyanonymous", + "title": "ComfyUI_experiments/advanced_model_merging", + "reference": "https://github.com/comfyanonymous/ComfyUI_experiments", + "files": [ + "https://github.com/comfyanonymous/ComfyUI_experiments/raw/master/advanced_model_merging.py" + ], + "install_type": "copy", + "description": "This provides a detailed model merge feature based on block weight. ModelMergeBlock, in vanilla ComfyUI, allows for adjusting the ratios of input/middle/output layers, but this node provides ratio adjustments for all blocks within each layer.

      It is recommended to use the integrated custom nodes in the default channel for update support rather than installing individual nodes.

      " + }, + { + "author": "comfyanonymous", + "title": "ComfyUI_experiments/sdxl_model_merging", + "reference": "https://github.com/comfyanonymous/ComfyUI_experiments", + "files": [ + "https://github.com/comfyanonymous/ComfyUI_experiments/raw/master/sdxl_model_merging.py" + ], + "install_type": "copy", + "description": "These nodes provide the capability to merge SDXL base models.

      It is recommended to use the integrated custom nodes in the default channel for update support rather than installing individual nodes.

      " + }, + { + "author": "comfyanonymous", + "title": "ComfyUI_experiments/reference_only", + "reference": "https://github.com/comfyanonymous/ComfyUI_experiments", + "files": [ + "https://github.com/comfyanonymous/ComfyUI_experiments/raw/master/reference_only.py" + ], + "install_type": "copy", + "description": "This node provides functionality corresponding to Reference only in Controlnet.

      It is recommended to use the integrated custom nodes in the default channel for update support rather than installing individual nodes.

      " + } + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/legacy/extension-node-map.json b/custom_nodes/ComfyUI-Manager/node_db/legacy/extension-node-map.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/legacy/extension-node-map.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/legacy/model-list.json b/custom_nodes/ComfyUI-Manager/node_db/legacy/model-list.json new file mode 100644 index 000000000..8e3e1dc48 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/legacy/model-list.json @@ -0,0 +1,3 @@ +{ + "models": [] +} diff --git a/custom_nodes/ComfyUI-Manager/node_db/new/alter-list.json b/custom_nodes/ComfyUI-Manager/node_db/new/alter-list.json new file mode 100644 index 000000000..072c3bb5e --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/new/alter-list.json @@ -0,0 +1,4 @@ +{ + "items": [ + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/new/custom-node-list.json b/custom_nodes/ComfyUI-Manager/node_db/new/custom-node-list.json new file mode 100644 index 000000000..72f9e2906 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/new/custom-node-list.json @@ -0,0 +1,702 @@ +{ + "custom_nodes": [ + { + "author": "#NOTICE_1.13", + "title": "NOTICE: This channel is not the default channel.", + "reference": "https://github.com/ltdrdata/ComfyUI-Manager","files": [], + "install_type": "git-clone", + "description": "If you see this message, your ComfyUI-Manager is outdated.\nRecent channel provides only the list of the latest nodes. If you want to find the complete node list, please go to the Default channel.\nMaking LoRA has never been easier!" + }, + + + + + { + "author": "Extraltodeus", + "title": "pre_cfg_comfy_nodes_for_ComfyUI", + "id": "precfg", + "reference": "https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI", + "files": [ + "https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI" + ], + "install_type": "git-clone", + "description": "A set of nodes to prepare the noise predictions before the CFG function" + }, + { + "author": "ZZXYWQ", + "title": "ZZX Nodes", + "id": "ZZXYWQ", + "reference": "https://github.com/ZZXYWQ/ComfyUI-ZZXYWQ", + "files": [ + "https://github.com/ZZXYWQ/ComfyUI-ZZXYWQ" + ], + "install_type": "git-clone", + "description": "Node(s): VideoFormatConverter(VFC)" + }, + { + "author": "smthemex", + "title": "ComfyUI_AnyDoor", + "id": "ComfyUI_AnyDoor", + "reference": "https://github.com/smthemex/ComfyUI_AnyDoor", + "files": [ + "https://github.com/smthemex/ComfyUI_AnyDoor" + ], + "install_type": "git-clone", + "description": "You can use anydoor, change clothes or object..." + }, + { + "author": "Haoming02", + "title": "ComfyUI Node Beautify", + "reference": "https://github.com/Haoming02/comfyui-node-beautify", + "files": [ + "https://github.com/Haoming02/comfyui-node-beautify" + ], + "install_type": "git-clone", + "description": "This is an Extension for ComfyUI, which helps formatting the workflow." + }, + { + "author": "adigayung", + "title": "ComfyUI-Translator", + "reference": "https://github.com/adigayung/ComfyUI-Translator", + "files": [ + "https://github.com/adigayung/ComfyUI-Translator" + ], + "install_type": "git-clone", + "description": "Auto translate all languages ​​to english" + }, + { + "author": "christian-byrne", + "title": "comfyui-default-values-manager", + "reference": "https://github.com/christian-byrne/comfyui-default-values-manager", + "files": [ + "https://github.com/christian-byrne/comfyui-default-values-manager" + ], + "install_type": "git-clone", + "description": "comfyui-default-values-manager" + }, + { + "author": "vivax3794", + "title": "ComfyUI-Sub-Nodes", + "reference": "https://github.com/vivax3794/ComfyUI-Sub-Nodes", + "files": [ + "https://github.com/vivax3794/ComfyUI-Sub-Nodes" + ], + "install_type": "git-clone", + "description": "Creating subgraph and Calling subgraphs." + }, + { + "author": "HECer", + "title": "ComfyUI-FilePathCreator", + "reference": "https://github.com/HECer/ComfyUI-FilePathCreator", + "files": [ + "https://github.com/HECer/ComfyUI-FilePathCreator" + ], + "install_type": "git-clone", + "description": "The ComfyUI-FilePathCreator is a custom node extension for ComfyUI designed to generate dynamic filenames based on user-defined parameters. This node helps streamline the process of creating organized and timestamped filenames, ideal for saving output files in a structured manner." + }, + { + "author": "mullakhmetov", + "title": "comfyui_dynamic_util_nodes", + "reference": "https://github.com/mullakhmetov/comfyui_dynamic_util_nodes", + "files": [ + "https://github.com/mullakhmetov/comfyui_dynamic_util_nodes" + ], + "install_type": "git-clone", + "description": "ComfyS3 helpful util nodes for dynamic workflows" + }, + { + "author": "wTechArtist", + "title": "ComfyUI-CustomNodes", + "reference": "https://github.com/wTechArtist/ComfyUI-CustomNodes", + "files": [ + "https://github.com/wTechArtist/ComfyUI-CustomNodes" + ], + "install_type": "git-clone", + "description": "Nodes:Image Blending Mode Mask" + }, + { + "author": "bradsec", + "title": "ComfyUI_StringTools", + "id": "stringtools", + "reference": "https://github.com/bradsec/ComfyUI_StringTools", + "files": [ + "https://github.com/bradsec/ComfyUI_StringTools" + ], + "install_type": "git-clone", + "description": "Some simple string tools to modify text and strings in ComfyUI." + }, + { + "author": "bluevisor", + "title": "ComfyUI_PS_Blend_Node", + "reference": "https://github.com/bluevisor/ComfyUI_PS_Blend_Node", + "files": [ + "https://github.com/bluevisor/ComfyUI_PS_Blend_Node" + ], + "install_type": "git-clone", + "description": "This repository contains a simple custom node for ComfyUI that implements familiar PS-style blend modes using PyTorch. The PSBlendNode allows you to blend two images together using a variety of blend modes and an opacity parameter." + }, + { + "author": "longgui0318", + "title": "comfyui-common-util", + "id": "common-util", + "reference": "https://github.com/longgui0318/comfyui-common-util", + "files": [ + "https://github.com/longgui0318/comfyui-common-util" + ], + "install_type": "git-clone", + "description": "Nodes:Init Layer Info Array, Added Layer Info To Array, Layer Info Array Fuse, Layer Image Seleted, Layer Images IPAdapter Advanced, Enhanced Random Light Source" + }, + { + "author": "kijai", + "title": "ComfyUI-KwaiKolorsWrapper", + "id": "kwaikolors", + "reference": "https://github.com/kijai/ComfyUI-KwaiKolorsWrapper", + "files": [ + "https://github.com/kijai/ComfyUI-KwaiKolorsWrapper" + ], + "install_type": "git-clone", + "description": "Rudimentary wrapper that runs [a/Kwai-Kolors](https://huggingface.co/Kwai-Kolors/Kolors) text2image pipeline using diffusers." + }, + { + "author": "Smuzzies", + "title": "comfyui_meme_maker", + "reference": "https://github.com/Smuzzies/comfyui_meme_maker", + "files": [ + "https://github.com/Smuzzies/comfyui_meme_maker" + ], + "install_type": "git-clone", + "description": "Meme Maker Node for ComfyUI." + }, + { + "author": "kijai", + "title": "ComfyUI-LivePortraitKJ", + "id": "liveportrait-kijai", + "reference": "https://github.com/kijai/ComfyUI-LivePortraitKJ", + "files": [ + "https://github.com/kijai/ComfyUI-LivePortraitKJ" + ], + "install_type": "git-clone", + "description": "Nodes for [a/LivePortrait](https://github.com/KwaiVGI/LivePortrait), insightface is required" + }, + { + "author": "metncelik", + "title": "comfyui_met_suite", + "reference": "https://github.com/metncelik/comfyui_met_suite", + "files": [ + "https://github.com/metncelik/comfyui_met_suite" + ], + "install_type": "git-clone", + "description": "Nodes: Primitive BBOX, BBOX Padding, BBOX Resize, ImageResize KeepRatio." + }, + { + "author": "shadowcz007", + "title": "comfyui-liveportrait", + "id": "liveportrait", + "reference": "https://github.com/shadowcz007/comfyui-liveportrait", + "files": [ + "https://github.com/shadowcz007/comfyui-liveportrait" + ], + "install_type": "git-clone", + "description": "The ComfyUI version of [a/LivePortrait](https://github.com/KwaiVGI/LivePortrait)." + }, + { + "author": "Tritant", + "title": "ComfyUI-CreaPrompt", + "id": "creaprompt", + "reference": "https://github.com/tritant/ComfyUI_CreaPrompt", + "files": [ + "https://github.com/tritant/ComfyUI_CreaPrompt" + ], + "install_type": "git-clone", + "description": "Generate random prompts easily." + }, + { + "author": "kijai", + "title": "ComfyUI-MimicMotionWrapper", + "id": "mimicmotion-kijai", + "reference": "https://github.com/kijai/ComfyUI-MimicMotionWrapper", + "files": [ + "https://github.com/kijai/ComfyUI-MimicMotionWrapper" + ], + "install_type": "git-clone", + "description": "Optimized wrapper nodes for MimicMotion: [a/https://github.com/tencent/MimicMotion](https://github.com/tencent/MimicMotion)" + }, + { + "author": "kijai", + "title": "ComfyUI-OpenDiTWrapper", + "id": "opendit-kijai", + "reference": "https://github.com/kijai/ComfyUI-OpenDiTWrapper", + "files": [ + "https://github.com/kijai/ComfyUI-OpenDiTWrapper" + ], + "install_type": "git-clone", + "description": "Wrapper nodes for OpenDiT: [a/OpenDiT](https://github.com/NUS-HPC-AI-Lab/OpenDiT/), supports Open-Sora t2i and i2i" + }, + { + "author": "smthemex", + "title": "ComfyUI_MS_Diffusion", + "id": "MS_Diffusion", + "reference": "https://github.com/smthemex/ComfyUI_MS_Diffusion", + "files": [ + "https://github.com/smthemex/ComfyUI_MS_Diffusion" + ], + "install_type": "git-clone", + "description": "You can using MS-diffusion make story in comfyUI." + }, + { + "author": "christian-byrne", + "title": "audio-separation-nodes-comfyui", + "reference": "https://github.com/christian-byrne/audio-separation-nodes-comfyui", + "files": [ + "https://github.com/christian-byrne/audio-separation-nodes-comfyui" + ], + "install_type": "git-clone", + "description": "Nodes:AudioSeparation, AudioCrop, AudioCombine, AudioTempoMatch." + }, + { + "author": "yiwangsimple", + "title": "comfy-groqchat", + "reference": "https://github.com/yiwangsimple/ComfyUI_GroqChat", + "files": [ + "https://github.com/yiwangsimple/ComfyUI_GroqChat" + ], + "install_type": "git-clone", + "description": "Content generation with open source models in comfyui via graq api implementation." + }, + { + "author": "AIFSH", + "title": "ComfyUI-MimicMotion", + "id": "mimicmotion-aifsh", + "reference": "https://github.com/AIFSH/ComfyUI-MimicMotion", + "files": [ + "https://github.com/AIFSH/ComfyUI-MimicMotion" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/MimicMotion](https://github.com/Tencent/MimicMotion)" + }, + { + "author": "AIFSH", + "title": "ComfyUI-DiffSynth-Studio", + "id": "diffsynth-studio", + "reference": "https://github.com/AIFSH/ComfyUI-DiffSynth-Studio", + "files": [ + "https://github.com/AIFSH/ComfyUI-DiffSynth-Studio" + ], + "install_type": "git-clone", + "description": "make [a/DiffSynth-Studio](https://github.com/modelscope/DiffSynth-Studio) available in ComfyUI" + }, + { + "author": "1038lab", + "title": "ComfyUI-latentSizeSelector", + "id": "ComfyUI-latentSizeSelector", + "reference": "https://github.com/1038lab/ComfyUI_LatentSizeSelector", + "files": [ + "https://github.com/1038lab/ComfyUI_LatentSizeSelector" + ], + "install_type": "git-clone", + "description": "You'll get a new node Latent Size Selector, you can pick the x and y sizes from a list." + }, + { + "author": "AIFSH", + "title": "ComfyUI-I2V-Adapter", + "id": "i2v-adapter", + "reference": "https://github.com/AIFSH/ComfyUI-I2V-Adapter", + "files": [ + "https://github.com/AIFSH/ComfyUI-I2V-Adapter" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/I2V-Adapter](https://github.com/KwaiVGI/I2V-Adapter)" + }, + { + "author": "DeJoker", + "title": "Pipeline Parallel ComfyUI", + "reference": "https://github.com/DeJoker/pipeline-parallel-comfy", + "files": [ + "https://github.com/DeJoker/pipeline-parallel-comfy" + ], + "install_type": "git-clone", + "description": "provide extra api to run prompt request with parallel execution of independent node" + }, + { + "author": "AIFSH", + "title": "ComfyUI-MARS5-TTS", + "id": "mars5-tts", + "reference": "https://github.com/AIFSH/ComfyUI-MARS5-TTS", + "files": [ + "https://github.com/AIFSH/ComfyUI-MARS5-TTS" + ], + "install_type": "git-clone", + "description": "a comfyui custom node for [a/MARS5-TTS](https://github.com/Camb-ai/MARS5-TTS)" + }, + { + "author": "MrSamSeen", + "title": "ComfyUI_SSStereoscope", + "id": "ssstereoscope", + "reference": "https://github.com/MrSamSeen/ComfyUI_SSStereoscope", + "files": [ + "https://github.com/MrSamSeen/ComfyUI_SSStereoscope" + ], + "install_type": "git-clone", + "description": "The SideBySide Node is a powerful tool designed for ComfyUI to generate stereoscopic images. It takes a base image and a corresponding depth map as inputs and produces a combined image that simulates a 3D effect when viewed with appropriate equipment." + }, + { + "author": "jroc22", + "title": "ComfyUI-CSV-prompt-builder", + "id": "csv-prompt-builder", + "reference": "https://github.com/jroc22/ComfyUI-CSV-prompt-builder", + "files": [ + "https://github.com/jroc22/ComfyUI-CSV-prompt-builder" + ], + "install_type": "git-clone", + "description": "This is a simple node for creating prompts using a .csv file. I created this node as an easy way to output different prompts each time a workflow is run." + }, + { + "author": "ImmortalPie", + "title": "PonySwitch Node", + "reference": "https://github.com/ImmortalPie/ComfyUI-PonySwitch", + "files": [ + "https://github.com/ImmortalPie/ComfyUI-PonySwitch/raw/main/PonySwitch.py" + ], + "install_type": "copy", + "description": "The PonySwitch node is a custom node for ComfyUI that modifies prompts based on a toggle switch and adds configurable pony tags." + }, + { + "author": "SEkINVR", + "title": "ComfyUI SaveAS", + "id": "saveas", + "reference": "https://github.com/SEkINVR/ComfyUI-SaveAs", + "files": [ + "https://github.com/SEkINVR/ComfyUI-SaveAs" + ], + "install_type": "git-clone", + "description": "This custom node for ComfyUI allows you to save images in multiple formats, including PNG, JPG, WebP, and ICO.\n[w/ComfyUI-Save-Multi-Format is renamed to SaveAs. Remove previous one and reinstall to this.]" + }, + { + "author": "Fuou Marinas", + "title": "ComfyUI-FirstOrderMM", + "id": "fomm", + "reference": "https://github.com/FuouM/ComfyUI-FirstOrderMM", + "files": [ + "https://github.com/FuouM/ComfyUI-FirstOrderMM" + ], + "install_type": "git-clone", + "description": "Run [a/First Order Motion Model](https://github.com/AliaksandrSiarohin/first-order-model) for Image Animation in ComfyUI." + }, + { + "author": "my-opencode", + "title": "ComfyUI_IndustrialMagick", + "id": "industrialmagick", + "reference": "https://github.com/my-opencode/ComfyUI_IndustrialMagick", + "files": [ + "https://github.com/my-opencode/ComfyUI_IndustrialMagick" + ], + "install_type": "git-clone", + "description": "[a/ImageMagick](https://imagemagick.org/index.php) nodes for ComfyUI. Adds nodes to call ImageMagick subprocesses from ComfyUI.\nRequirements: [a/ImagMagick7](https://imagemagick.org/script/download.php), 'magick' command in your CLI environment." + }, + { + "author": "my-opencode", + "title": "ComfyUI_KSamplerTimer", + "id": "ksamplertimer", + "reference": "https://github.com/my-opencode/ComfyUI_KSamplerTimer", + "files": [ + "https://github.com/my-opencode/ComfyUI_KSamplerTimer" + ], + "install_type": "git-clone", + "description": "A custom node that returns the generation time of the KSampler. Intended for benchmarking or debugging." + }, + { + "author": "licyk", + "title": "ComfyUI-Restart-Sampler", + "id": "restart-sampler-licyk", + "reference": "https://github.com/licyk/ComfyUI-Restart-Sampler", + "files": [ + "https://github.com/licyk/ComfyUI-Restart-Sampler" + ], + "install_type": "git-clone", + "description": "This extension is a node that directly expands the functionality of KSampler, rather than being in the form of a custom node. [w/Workflows created using this feature are not compatible with other users.]" + }, + { + "author": "pamparamm", + "title": "ComfyUI Vectorscope CC", + "id": "vectorscope", + "reference": "https://github.com/pamparamm/ComfyUI-vectorscope-cc", + "files": [ + "https://github.com/pamparamm/ComfyUI-vectorscope-cc" + ], + "install_type": "git-clone", + "description": "ComfyUI port of a wonderful extension [a/SD Webui Vectorscope CC by Haoming02](https://github.com/Haoming02/sd-webui-vectorscope-cc).\nBased on (and probably incompatible with) [a/ComfyUI Diffusion Color Grading by Haoming02](https://github.com/Haoming02/comfyui-diffusion-cg)." + }, + { + "author": "yuvraj108c", + "title": "ComfyUI YoloNasPose Tensorrt", + "id": "yolonaspose-tensorrt", + "reference": "https://github.com/yuvraj108c/ComfyUI-YoloNasPose-Tensorrt", + "files": [ + "https://github.com/yuvraj108c/ComfyUI-YoloNasPose-Tensorrt" + ], + "install_type": "git-clone", + "description": "This repo provides a ComfyUI Custom Node implementation of [a/YOLO-NAS-POSE](https://github.com/Deci-AI/super-gradients), powered by TensorRT for ultra fast pose estimation. It has been adapted to work with openpose controlnet (experimental)" + }, + { + "author": "GreenLandisaLie", + "title": "AuraSR-ComfyUI", + "id": "aurasr-greenlandisalie", + "reference": "https://github.com/GreenLandisaLie/AuraSR-ComfyUI", + "files": [ + "https://github.com/GreenLandisaLie/AuraSR-ComfyUI" + ], + "install_type": "git-clone", + "description": "ComfyUI implementation of [a/Aura-SR](https://github.com/fal-ai/aura-sr)" + }, + { + "author": "mingqizhang", + "title": "ComfyUI_InSPyResNet_zmq", + "id": "inspy", + "reference": "https://github.com/mingqizhang/ComfyUI_InSPyResNet_zmq", + "files": [ + "https://github.com/mingqizhang/ComfyUI_InSPyResNet_zmq" + ], + "install_type": "git-clone", + "description": "Nodes:INSPY removebg ModelLoader, INSPY RMBG" + }, + { + "author": "hwhaocool", + "title": "ComfyUI-Select-Any", + "id": "select-any", + "reference": "https://github.com/hwhaocool/ComfyUI-Select-Any", + "files": [ + "https://github.com/hwhaocool/ComfyUI-Select-Any" + ], + "install_type": "git-clone", + "description": "a comfyui custom node, which can select value from inputs" + }, + { + "author": "leiweiqiang", + "title": "ComfyUI-TRA", + "id": "tra", + "reference": "https://github.com/leiweiqiang/ComfyUI-TRA", + "files": [ + "https://github.com/leiweiqiang/ComfyUI-TRA" + ], + "install_type": "git-clone", + "description": "Nodes:TCL EbSynth, TCL Extract Frames (From File), TCL Extract Frames (From Video), TCL Combine Frames, TCL Save Video (From Frames)" + }, + { + "author": "AIFSH", + "title": "ComfyUI-AuraSR", + "id": "aurasr", + "reference": "https://github.com/AIFSH/ComfyUI-AuraSR", + "files": [ + "https://github.com/AIFSH/ComfyUI-AuraSR" + ], + "install_type": "git-clone", + "description": "a node for [a/AuraSR](https://github.com/fal-ai/aura-sr)" + }, + { + "author": "veighnsche", + "title": "comfyui_gr85", + "id": "gr85", + "reference": "https://github.com/veighnsche/comfyui_gr85", + "files": [ + "https://github.com/veighnsche/comfyui_gr85" + ], + "install_type": "git-clone", + "description": "Nodes:Image Dimension Resizer, Image Sizer, Random Ratio, Show Text, Random Title Character, Random Wildcard Tag Picker, Random Show Atm Loc Outfit, Contains Word, Elements Concatenator, ..." + }, + { + "author": "hyunamy", + "title": "Comfy-UI on-complete-email-me", + "id": "hyunamy", + "reference": "https://github.com/hyunamy/comfy-ui-on-complete-email-me", + "files": [ + "https://github.com/hyunamy/comfy-ui-on-complete-email-me" + ], + "install_type": "git-clone", + "description": "A feature that sends an email via Gmail once image generation is completed in Comfy-ui." + }, + { + "author": "rhdunn", + "title": "comfyui-bus-plugin", + "id": "bus", + "reference": "https://github.com/rhdunn/comfyui-bus-plugin", + "files": [ + "https://github.com/rhdunn/comfyui-bus-plugin" + ], + "install_type": "git-clone", + "description": "A collection of nodes for rerouting multiple I/O lines together in a bus." + }, + { + "author": "hay86", + "title": "ComfyUI Hallo", + "id": "hallo-hay86", + "reference": "https://github.com/hay86/ComfyUI_Hallo", + "files": [ + "https://github.com/hay86/ComfyUI_Hallo" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of [a/hallo](https://github.com/fudan-generative-vision/hallo) for ComfyUI" + }, + { + "author": "AI2lab", + "title": "comfyUI-siliconflow-api-2lab", + "id": "siliconflow", + "reference": "https://github.com/AI2lab/comfyUI-siliconflow-api-2lab", + "files": [ + "https://github.com/AI2lab/comfyUI-siliconflow-api-2lab" + ], + "install_type": "git-clone", + "description": "Unofficial implementation of siliconflow API for ComfyUI\nHow to use:apply api key in :https://cloud.siliconflow.cn/\nadd api key in config.json" + }, + { + "author": "11dogzi", + "title": "ComfUI-EGAdapterMadAssistant", + "id": "ergouzi-samplers", + "reference": "https://github.com/11dogzi/ComfUI-EGAdapterMadAssistant", + "files": [ + "https://github.com/11dogzi/ComfUI-EGAdapterMadAssistant" + ], + "install_type": "git-clone", + "description": "This is a hierarchical auxiliary project of the IPAdapter project, which uses a slider to quickly control the hierarchical weights and add fully random and semi random modes" + }, + { + "author": "iwanders", + "title": "iwanders/ComfyUI_nodes", + "id": "iwanders-nodes", + "reference": "https://github.com/iwanders/ComfyUI_nodes", + "files": [ + "https://github.com/iwanders/ComfyUI_nodes" + ], + "install_type": "git-clone", + "description": "Nodes:IW SaveString, IW PrintString, IW ReplaceString, IW StringNode, IW StringConcat, IW TokenizerVocab, IW JsonPickItem." + }, + { + "author": "SaltAI", + "title": "SaltAI_AudioViz", + "id": "saltai-audioviz", + "reference": "https://github.com/get-salt-AI/SaltAI_AudioViz", + "files": [ + "https://github.com/get-salt-AI/SaltAI_AudioViz" + ], + "install_type": "git-clone", + "description": "SaltAI AudioViz contains ComfyUI nodes for generating complex audio reactive visualizations" + }, + { + "author": "AI2lab", + "title": "comfyUI-tool-2lab", + "id": "tool-2lab", + "reference": "https://github.com/AI2lab/comfyUI-tool-2lab", + "files": [ + "https://github.com/AI2lab/comfyUI-tool-2lab" + ], + "install_type": "git-clone", + "description": "tool set for developing workflow and publish to web api server" + }, + { + "author": "SherryXieYuchen", + "title": "ComfyUI-Image-Inpainting", + "id": "image-inpainting", + "reference": "https://github.com/SherryXieYuchen/ComfyUI-Image-Inpainting", + "files": [ + "https://github.com/SherryXieYuchen/ComfyUI-Image-Inpainting" + ], + "install_type": "git-clone", + "description": "Nodes:VAE Encode Inpaint, VAE Decode Inpaint, ColorCorrection Inpaint, ImagePreprocess Inpaint, ImagePostprocess Inpaint, Load Model Inpaint, Inpainting (using Model)" + }, + { + "author": "zeroxoxo", + "title": "ComfyUI-Fast-Style-Transfer", + "id": "fast-style-transfer", + "reference": "https://github.com/zeroxoxo/ComfyUI-Fast-Style-Transfer", + "files": [ + "https://github.com/zeroxoxo/ComfyUI-Fast-Style-Transfer" + ], + "install_type": "git-clone", + "description": "ComfyUI node for fast neural style transfer. This is a simple conversion based on this: [a/https://github.com/rrmina/fast-neural-style-pytorch](https://github.com/rrmina/fast-neural-style-pytorch) Only basic inference functionality is ported for now." + }, + { + "author": "Shibiko-AI", + "title": "Shibiko AI ComfyUI Tools", + "id": "shibiko-ai-tools", + "reference": "https://github.com/Shibiko-AI/ShibikoAI-ComfyUI-Tools", + "files": [ + "https://github.com/Shibiko-AI/ShibikoAI-ComfyUI-Tools" + ], + "install_type": "git-clone", + "description": "This is a collection of tools that I use to make my life easier when developing ComfyUI applications. It is a collection of tools that I have created to help me with my development process. I have decided to share these tools with the community in the hopes that they will be useful to others as well. I use this tools to further develop features for [a/https://shibiko.ai](https://shibiko.ai)" + }, + { + "author": "fofr", + "title": "comfyui-replicate", + "reference": "https://github.com/fofr/comfyui-replicate", + "files": [ + "https://github.com/fofr/comfyui-replicate" + ], + "install_type": "git-clone", + "description": "Nodes:Llama 3 Replicate" + }, + { + "author": "RedRayz", + "title": "ComfyUI-Danbooru-To-WD", + "id": "danbooru2wd", + "reference": "https://github.com/RedRayz/ComfyUI-Danbooru-To-WD", + "files": [ + "https://github.com/RedRayz/ComfyUI-Danbooru-To-WD" + ], + "install_type": "git-clone", + "description": "Converts booru tags to a format suitable for Waifu Diffusion(or Danbooru based models)." + }, + { + "author": "akkyoss", + "title": "ComfyUI_Zwng_Nodes", + "id": "zwng", + "reference": "https://github.com/za-wa-n-go/ComfyUI_Zwng_Nodes", + "files": [ + "https://github.com/za-wa-n-go/ComfyUI_Zwng_Nodes" + ], + "install_type": "git-clone", + "description": "Simple nodes for loading image files.Nodes that include a simple remote connection to Photoshop, a node that can overlay and preview an image with a mask, and a node that can load images directly from a file path." + }, + { + "author": "slyt", + "title": "comfyui-ollama-nodes", + "reference": "https://github.com/slyt/comfyui-ollama-nodes", + "files": [ + "https://github.com/slyt/comfyui-ollama-nodes" + ], + "install_type": "git-clone", + "description": "ComfyUI custom nodes for working with [a/Ollama](https://github.com/ollama/ollama).\nNOTE:Assumes that an Ollama server is running at http://127.0.0.1:11434 and accessible by the ComfyUI backend." + }, + { + "author": "MilitantHitchhiker", + "title": "Militant Hitchhiker's Switchblade Pack", + "id": "hitchhiker", + "reference": "https://github.com/MilitantHitchhiker/MilitantHitchhiker-SwitchbladePack", + "files": [ + "https://github.com/MilitantHitchhiker/MilitantHitchhiker-SwitchbladePack" + ], + "install_type": "git-clone", + "description": "Militant Hitchhiker's Switchblade Pack is a collection of custom nodes for ComfyUI that provide various multi-function capabilities." + }, + { + "author": "turkyden", + "title": "ComfyUI-Avatar", + "id": "avatar", + "reference": "https://github.com/turkyden/ComfyUI-Avatar", + "files": [ + "https://github.com/turkyden/ComfyUI-Avatar" + ], + "install_type": "git-clone", + "description": "a comfyui plugin for image to avatar" + }, + { + "author": "fablestudio", + "title": "ComfyUI-Showrunner-Utils", + "reference": "https://github.com/fablestudio/ComfyUI-Showrunner-Utils", + "files": [ + "https://github.com/fablestudio/ComfyUI-Showrunner-Utils" + ], + "install_type": "git-clone", + "description": "Comfyui Custom Nodes for Showrunner" + } + ] +} diff --git a/custom_nodes/ComfyUI-Manager/node_db/new/extension-node-map.json b/custom_nodes/ComfyUI-Manager/node_db/new/extension-node-map.json new file mode 100644 index 000000000..8843576b5 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/new/extension-node-map.json @@ -0,0 +1,15962 @@ +{ + "https://gist.github.com/alkemann/7361b8eb966f29c8238fd323409efb68/raw/f9605be0b38d38d3e3a2988f89248ff557010076/alkemann.py": [ + [ + "Int to Text", + "Save A1 Image", + "Seed With Text" + ], + { + "title_aux": "alkemann nodes" + } + ], + "https://git.mmaker.moe/mmaker/sd-webui-color-enhance": [ + [ + "MMakerColorBlend", + "MMakerColorEnhance" + ], + { + "title_aux": "Color Enhance" + } + ], + "https://github.com/0xbitches/ComfyUI-LCM": [ + [ + "LCM_Sampler", + "LCM_Sampler_Advanced", + "LCM_img2img_Sampler", + "LCM_img2img_Sampler_Advanced" + ], + { + "title_aux": "Latent Consistency Model for ComfyUI" + } + ], + "https://github.com/1038lab/ComfyUI-GPT2P": [ + [ + "GPT2PNode" + ], + { + "title_aux": "ComfyUI-GPT2P" + } + ], + "https://github.com/1038lab/ComfyUI_LatentSizeSelector": [ + [ + "LatentSizeSelector" + ], + { + "title_aux": "ComfyUI-latentSizeSelector" + } + ], + "https://github.com/11dogzi/ComfUI-EGAdapterMadAssistant": [ + [ + "EGIPAdapter_Mad_Assistant", + "EGIPAdapter_Mad_AssistantV1", + "EGIPAdapter_Mad_AssistantV2", + "EGIPAdapter_Mad_AssistantV3", + "EGIPAdapter_Mad_AssistantV4", + "EGIPAdapter_Mad_AssistantV5" + ], + { + "title_aux": "ComfUI-EGAdapterMadAssistant" + } + ], + "https://github.com/11dogzi/Comfyui-ergouzi-Nodes": [ + [ + "EG-YSZT-ZT", + "EG_CPSYTJ", + "EG_FX_BDAPI", + "EG_HT_YSTZ", + "EG_JF_ZZSC", + "EG_JXFZ_node", + "EG_K_LATENT", + "EG_RY_HT", + "EG_SCQY_BHDQY", + "EG_SCQY_QBQY", + "EG_SCQY_SXQY", + "EG_SJ", + "EG_SJPJ_Node", + "EG_SS_RYZH", + "EG_SZ_JDYS", + "EG_TC_Node", + "EG_TSCDS_CJ", + "EG_TSCDS_DG", + "EG_TSCDS_FG", + "EG_TSCDS_JT", + "EG_TSCDS_QT", + "EG_TSCDS_RW", + "EG_TSCDS_WP", + "EG_TSCDS_ZL", + "EG_TSCMB_GL", + "EG_TXZZ_ZH", + "EG_TX_CCHQ", + "EG_TX_CJPJ", + "EG_TX_JZRY", + "EG_TX_LJ", + "EG_TX_LJBC", + "EG_TX_SFBLS", + "EG_TX_WHLJ", + "EG_WB_KSH", + "EG_WXZ_QH", + "EG_XZ_QH", + "EG_YSQY_BBLLD", + "EG_YSQY_BLLD", + "EG_ZY_WBK", + "EG_ZZHBCJ", + "EG_ZZKZ_HT_node", + "EG_ZZ_BSYH", + "EG_ZZ_BYYH", + "EG_ZZ_HSYH", + "EG_ZZ_SSKZ", + "ER_JBCH", + "ER_TX_ZZCJ" + ], + { + "title_aux": "Comfyui-ergouzi-Nodes" + } + ], + "https://github.com/11dogzi/Comfyui-ergouzi-samplers": [ + [ + "EGBYZZCYQ", + "EGCYQJB", + "EGCYQJBCJ" + ], + { + "title_aux": "Comfyui-ergouzi-samplers" + } + ], + "https://github.com/1mckw/Comfyui-Gelbooru": [ + [ + "Gelbooru (ID)", + "Gelbooru (Random)" + ], + { + "title_aux": "Comfyui-Gelbooru" + } + ], + "https://github.com/1shadow1/hayo_comfyui_nodes/raw/main/LZCNodes.py": [ + [ + "LoadPILImages", + "MergeImages", + "make_transparentmask", + "tensor_trans_pil", + "words_generatee" + ], + { + "title_aux": "Hayo comfyui nodes" + } + ], + "https://github.com/42lux/ComfyUI-safety-checker": [ + [ + "Safety Checker" + ], + { + "title_aux": "ComfyUI-safety-checker" + } + ], + "https://github.com/438443467/ComfyUI-GPT4V-Image-Captioner": [ + [ + "GPT4VCaptioner", + "Image Load with Metadata", + "SAMIN String Attribute Selector", + "SANMIN Adapt Coordinates", + "SANMIN AdjustTransparency", + "SANMIN BlurMaskArea", + "SANMIN ChineseToCharacter", + "SANMIN ClothingWildcards", + "SANMIN ConvertToEnglish", + "SANMIN EditWildcards", + "SANMIN Float", + "SANMIN LoadPathImagesPreview", + "SANMIN SCALE AND FILL BLACK", + "SANMIN SanmiSaveImageToLocal", + "SANMIN SimpleWildcards", + "SANMIN Upscale And Original Size", + "Samin Counter", + "Samin Load Image Batch" + ], + { + "title_aux": "ComfyUI-GPT4V-Image-Captioner" + } + ], + "https://github.com/54rt1n/ComfyUI-DareMerge": [ + [ + "DM_AdvancedDareModelMerger", + "DM_AdvancedModelMerger", + "DM_AttentionGradient", + "DM_BlockGradient", + "DM_BlockModelMerger", + "DM_DareClipMerger", + "DM_DareModelMergerBlock", + "DM_DareModelMergerElement", + "DM_DareModelMergerMBW", + "DM_GradientEdit", + "DM_GradientOperations", + "DM_GradientReporting", + "DM_InjectNoise", + "DM_LoRALoaderTags", + "DM_LoRAReporting", + "DM_MBWGradient", + "DM_MagnitudeMasker", + "DM_MaskEdit", + "DM_MaskOperations", + "DM_MaskReporting", + "DM_ModelReporting", + "DM_NormalizeModel", + "DM_QuadMasker", + "DM_ShellGradient", + "DM_SimpleMasker" + ], + { + "title_aux": "ComfyUI-DareMerge" + } + ], + "https://github.com/80sVectorz/ComfyUI-Static-Primitives": [ + [ + "FloatStaticPrimitive", + "IntStaticPrimitive", + "StringMlStaticPrimitive", + "StringStaticPrimitive" + ], + { + "title_aux": "ComfyUI-Static-Primitives" + } + ], + "https://github.com/A4P7J1N7M05OT/ComfyUI-AutoColorGimp": [ + [ + "AutoColorGimp" + ], + { + "title_aux": "ComfyUI-AutoColorGimp" + } + ], + "https://github.com/A4P7J1N7M05OT/ComfyUI-PixelOE": [ + [ + "PixelOE" + ], + { + "title_aux": "ComfyUI-PixelOE" + } + ], + "https://github.com/AARG-FAN/Image-Raster-for-ComfyUI": [ + [ + "AIraster" + ], + { + "title_aux": "Image-vector-for-ComfyUI" + } + ], + "https://github.com/AIFSH/ComfyUI-3d-photo-inpainting": [ + [ + "LoadImagePath", + "PreViewVideo", + "TreeDNode" + ], + { + "title_aux": "ComfyUI-3d-photo-inpainting" + } + ], + "https://github.com/AIFSH/ComfyUI-AuraSR": [ + [ + "AuraSRNode" + ], + { + "title_aux": "AIFSH/ComfyUI-AuraSR" + } + ], + "https://github.com/AIFSH/ComfyUI-DiffSynth-Studio": [ + [ + "ControlNetPathLoader", + "DiffTextNode", + "DiffutoonNode", + "ExVideoNode", + "LoadVideo", + "PreViewVideo", + "SDPathLoader" + ], + { + "title_aux": "ComfyUI-DiffSynth-Studio" + } + ], + "https://github.com/AIFSH/ComfyUI-FishSpeech": [ + [ + "FishSpeech_INFER", + "FishSpeech_INFER_SRT", + "LoadAudio", + "LoadSRT", + "PreViewAudio" + ], + { + "title_aux": "ComfyUI-FishSpeech" + } + ], + "https://github.com/AIFSH/ComfyUI-GPT_SoVITS": [ + [ + "GPT_SOVITS_FT", + "GPT_SOVITS_INFER", + "GPT_SOVITS_TTS", + "LoadAudio", + "LoadSRT", + "PreViewAudio" + ], + { + "title_aux": "ComfyUI-GPT_SoVITS" + } + ], + "https://github.com/AIFSH/ComfyUI-Hallo": [ + [ + "HalloNode", + "LoadAudioPath", + "LoadImagePath", + "PreViewVideo" + ], + { + "title_aux": "ComfyUI-Hallo" + } + ], + "https://github.com/AIFSH/ComfyUI-I2V-Adapter": [ + [ + "I2V_AdapterNode", + "LoraPathLoader", + "MotionLoraLoader", + "PreViewVideo", + "PromptNode" + ], + { + "title_aux": "ComfyUI-I2V-Adapter" + } + ], + "https://github.com/AIFSH/ComfyUI-IP_LAP": [ + [ + "CombineAudioVideo", + "IP_LAP", + "LoadVideo", + "PreViewVideo" + ], + { + "title_aux": "ComfyUI-IP_LAP" + } + ], + "https://github.com/AIFSH/ComfyUI-Live2DViewer": [ + [ + "Live2DViewer", + "LoadAudio" + ], + { + "title_aux": "ComfyUI-Live2DViewer" + } + ], + "https://github.com/AIFSH/ComfyUI-MARS5-TTS": [ + [ + "LoadAudioPath", + "MARS5TTS_Node", + "PreViewAudio", + "TTSTextEncode" + ], + { + "title_aux": "ComfyUI-MARS5-TTS" + } + ], + "https://github.com/AIFSH/ComfyUI-MimicBrush": [ + [ + "MimicBrushNode" + ], + { + "title_aux": "ComfyUI-MimicBrush" + } + ], + "https://github.com/AIFSH/ComfyUI-MimicMotion": [ + [ + "LoadVideo", + "MimicMotionNode", + "PreViewVideo" + ], + { + "title_aux": "ComfyUI-MimicMotion" + } + ], + "https://github.com/AIFSH/ComfyUI-MuseTalk_FSH": [ + [ + "CombineAudioVideo", + "LoadVideo", + "MuseTalk", + "MuseTalkRealTime", + "PreViewVideo" + ], + { + "title_aux": "ComfyUI-MuseTalk_FSH" + } + ], + "https://github.com/AIFSH/ComfyUI-RVC": [ + [ + "CombineAudio", + "LoadAudio", + "PreViewAudio", + "RVC_Infer", + "RVC_Train" + ], + { + "title_aux": "ComfyUI-RVC" + } + ], + "https://github.com/AIFSH/ComfyUI-UVR5": [ + [ + "LoadAudioPath", + "PreViewAudio", + "UVR5_Node" + ], + { + "title_aux": "ComfyUI-UVR5" + } + ], + "https://github.com/AIFSH/ComfyUI-UniAnimate": [ + [ + "LoadImagePath", + "LoadVideo", + "PoseAlignNode", + "PreViewVideo", + "UniAnimateNode" + ], + { + "title_aux": "ComfyUI-UniAnimate" + } + ], + "https://github.com/AIFSH/ComfyUI-WhisperX": [ + [ + "LoadAudio", + "PreViewSRT", + "WhisperX" + ], + { + "title_aux": "ComfyUI-WhisperX" + } + ], + "https://github.com/AIFSH/ComfyUI-XTTS": [ + [ + "LoadAudioPath", + "LoadSRT", + "PreViewAudio", + "XTTS_INFER", + "XTTS_INFER_SRT" + ], + { + "title_aux": "ComfyUI-XTTS" + } + ], + "https://github.com/AIFSH/ComfyUI_V-Express": [ + [ + "LoadAudioPath", + "LoadImagePath", + "LoadVideo", + "PreViewVideo", + "VExpress" + ], + { + "title_aux": "ComfyUI_V-Express" + } + ], + "https://github.com/AIGCTeam/ComfyUI_kkTranslator_nodes": [ + [ + "LoadMarianMTCheckPoint", + "PromptBaiduFanyiToText", + "PromptTranslateToText" + ], + { + "title_aux": "ComfyUI_kkTranslator_nodes" + } + ], + "https://github.com/AIGODLIKE/ComfyUI-CUP": [ + [ + "Mask", + "OpenPose", + "OpenPoseCanny", + "OpenPoseDepth", + "OpenPoseFace", + "OpenPoseFull", + "OpenPoseFullExtraLimb", + "OpenPoseHand", + "OpenPoseKeyPose", + "OpenPoseLineart", + "OpenPoseMediaPipeFace", + "PreviewAudio", + "SaveAudioBL", + "\u5b58\u50a8", + "\u5bfc\u5165", + "\u622a\u56fe", + "\u6750\u8d28\u56fe", + "\u8f93\u5165\u56fe\u50cf", + "\u9884\u89c8" + ], + { + "title_aux": "ComfyUI-CUP" + } + ], + "https://github.com/AIGODLIKE/ComfyUI-ToonCrafter": [ + [ + "ToonCrafterNode" + ], + { + "title_aux": "ComfyUI-ToonCrafter" + } + ], + "https://github.com/AInseven/ComfyUI-fastblend": [ + [ + "FillDarkMask", + "InterpolateKeyFrame", + "MaskListcaptoBatch", + "Merge_Image_List", + "MyOpenPoseNode", + "SmoothVideo", + "alert_when_finished", + "reBatchImage" + ], + { + "title_aux": "ComfyUI-fastblend" + } + ], + "https://github.com/AIrjen/OneButtonPrompt": [ + [ + "AutoNegativePrompt", + "CreatePromptVariant", + "OneButtonArtify", + "OneButtonFlufferize", + "OneButtonPreset", + "OneButtonPrompt", + "OneButtonSuperPrompt", + "SavePromptToFile" + ], + { + "title_aux": "One Button Prompt" + } + ], + "https://github.com/ALatentPlace/ComfyUI_yanc": [ + [ + "> Clear Text", + "> Float to Int", + "> Get Mean Color", + "> Int", + "> Int to Text", + "> Layer Weights (for IPAMS)", + "> Light Source Mask", + "> Load Image", + "> Load Image From Folder", + "> Mask Curves", + "> NIKSampler", + "> Noise From Image", + "> Normal Map Lighting", + "> RGB Color", + "> Resolution by Aspect Ratio", + "> Rotate Image", + "> Save Image", + "> Scale Image to Side", + "> Text", + "> Text Combine", + "> Text Pick Random Line", + "> Text Random Weights", + "> Text Replace" + ], + { + "title_aux": "ComfyUI_yanc" + } + ], + "https://github.com/AbdullahAlfaraj/Comfy-Photoshop-SD": [ + [ + "APS_LatentBatch", + "APS_Seed", + "ContentMaskLatent", + "ControlNetScript", + "ControlnetUnit", + "GaussianLatentImage", + "GetConfig", + "LoadImageBase64", + "LoadImageWithMetaData", + "LoadLorasFromPrompt", + "MaskExpansion" + ], + { + "title_aux": "Comfy-Photoshop-SD" + } + ], + "https://github.com/AbyssYuan0/ComfyUI_BadgerTools": [ + [ + "ApplyMaskToImage-badger", + "CropImageByMask-badger", + "ExpandImageWithColor-badger", + "FindThickLinesFromCanny-badger", + "FloatToInt-badger", + "FloatToString-badger", + "FrameToVideo-badger", + "GETRequset-badger", + "GarbageCollect-badger", + "GetColorFromBorder-badger", + "GetDirName-badger", + "GetUUID-badger", + "IdentifyBorderColorToMask-badger", + "IdentifyColorToMask-badger", + "ImageNormalization-badger", + "ImageOverlap-badger", + "ImageScaleToSide-badger", + "IntToString-badger", + "IntToStringAdvanced-badger", + "LoadImageAdvanced-badger", + "LoadImagesFromDirListAdvanced-badger", + "SegmentToMaskByPoint-badger", + "SimpleBoolean-badger", + "StringToFizz-badger", + "TextListToString-badger", + "ToPixel-badger", + "TrimTransparentEdges-badger", + "VideoCutFromDir-badger", + "VideoToFrame-badger", + "deleteDir-badger", + "findCenterOfMask-badger", + "getImageSide-badger", + "getParentDir-badger", + "mkdir-badger" + ], + { + "title_aux": "ComfyUI_BadgerTools" + } + ], + "https://github.com/Acly/comfyui-inpaint-nodes": [ + [ + "INPAINT_ApplyFooocusInpaint", + "INPAINT_DenoiseToCompositingMask", + "INPAINT_ExpandMask", + "INPAINT_InpaintWithModel", + "INPAINT_LoadFooocusInpaint", + "INPAINT_LoadInpaintModel", + "INPAINT_MaskedBlur", + "INPAINT_MaskedFill", + "INPAINT_VAEEncodeInpaintConditioning" + ], + { + "title_aux": "ComfyUI Inpaint Nodes" + } + ], + "https://github.com/Acly/comfyui-tooling-nodes": [ + [ + "ETN_ApplyMaskToImage", + "ETN_AttentionMask", + "ETN_BackgroundRegion", + "ETN_CropImage", + "ETN_DefineRegion", + "ETN_ExtractImageTile", + "ETN_ExtractMaskTile", + "ETN_GenerateTileMask", + "ETN_ListRegionMasks", + "ETN_LoadImageBase64", + "ETN_LoadMaskBase64", + "ETN_MergeImageTile", + "ETN_SendImageWebSocket", + "ETN_TileLayout" + ], + { + "title_aux": "ComfyUI Nodes for External Tooling" + } + ], + "https://github.com/AiMiDi/ComfyUI-Aimidi-nodes": [ + [ + "Add Tag", + "Clear Tag", + "Load Images Pair Batch", + "Merge Tag", + "Move Tag To Top", + "Reserve Tag", + "Save Images Pair" + ], + { + "title_aux": "ComfyUI-Aimidi-nodes" + } + ], + "https://github.com/AlekPet/ComfyUI_Custom_Nodes_AlekPet": [ + [ + "ArgosTranslateCLIPTextEncodeNode", + "ArgosTranslateTextNode", + "ColorsCorrectNode", + "DeepTranslatorCLIPTextEncodeNode", + "DeepTranslatorTextNode", + "GoogleTranslateCLIPTextEncodeNode", + "GoogleTranslateTextNode", + "HexToHueNode", + "PainterNode", + "PoseNode", + "PreviewTextNode" + ], + { + "title_aux": "AlekPet/ComfyUI_Custom_Nodes_AlekPet" + } + ], + "https://github.com/Amorano/Jovimetrix": [ + [ + "ADJUST (JOV) \ud83d\udd78\ufe0f", + "AKASHIC (JOV) \ud83d\udcd3", + "ARRAY (JOV) \ud83d\udcda", + "BLEND (JOV) \u2697\ufe0f", + "COLOR BLIND (JOV) \ud83d\udc41\u200d\ud83d\udde8", + "COLOR MATCH (JOV) \ud83d\udc9e", + "COLOR THEORY (JOV) \ud83d\udede", + "COMPARISON (JOV) \ud83d\udd75\ud83c\udffd", + "CONSTANT (JOV) \ud83d\udfea", + "CROP (JOV) \u2702\ufe0f", + "DELAY (JOV) \u270b\ud83c\udffd", + "EXPORT (JOV) \ud83d\udcfd", + "FILTER MASK (JOV) \ud83e\udd3f", + "FLATTEN (JOV) \u2b07\ufe0f", + "GLSL (JOV) \ud83c\udf69", + "GRADIENT MAP (JOV) \ud83c\uddf2\ud83c\uddfa", + "GRAPH (JOV) \ud83d\udcc8", + "LERP (JOV) \ud83d\udd30", + "MIDI FILTER (JOV) \u2733\ufe0f", + "MIDI FILTER EZ (JOV) \u2747\ufe0f", + "MIDI MESSAGE (JOV) \ud83c\udf9b\ufe0f", + "MIDI READER (JOV) \ud83c\udfb9", + "OP BINARY (JOV) \ud83c\udf1f", + "OP UNARY (JOV) \ud83c\udfb2", + "PIXEL MERGE (JOV) \ud83e\udec2", + "PIXEL SPLIT (JOV) \ud83d\udc94", + "PIXEL SWAP (JOV) \ud83d\udd03", + "QUEUE (JOV) \ud83d\uddc3", + "ROUTE (JOV) \ud83d\ude8c", + "SAVE OUTPUT (JOV) \ud83d\udcbe", + "SHAPE GEN (JOV) \u2728", + "SPOUT WRITER (JOV) \ud83c\udfa5", + "STACK (JOV) \u2795", + "STEREOGRAM (JOV) \ud83d\udcfb", + "STEREOSCOPIC (JOV) \ud83d\udd76\ufe0f", + "STREAM READER (JOV) \ud83d\udcfa", + "STREAM WRITER (JOV) \ud83c\udf9e\ufe0f", + "SWIZZLE (JOV) \ud83d\ude35", + "TEXT GEN (JOV) \ud83d\udcdd", + "THRESHOLD (JOV) \ud83d\udcc9", + "TICK (JOV) \u23f1", + "TRANSFORM (JOV) \ud83c\udfdd\ufe0f", + "VALUE (JOV) \ud83e\uddec", + "WAVE GEN (JOV) \ud83c\udf0a", + "WAVE GRAPH (JOV) \u25b6 \u0131l\u0131\u0131l\u0131" + ], + { + "author": "amorano", + "description": "Jovimetrix integrates Webcam, MIDI, Spout and GLSL shader support.", + "nodename_pattern": " \\(JOV\\)$", + "title": "Jovimetrix", + "title_aux": "Jovimetrix Composition Nodes" + } + ], + "https://github.com/AonekoSS/ComfyUI-LoRA-Tuner": [ + [ + "LoraTuner" + ], + { + "title_aux": "ComfyUI-LoRA-Tuner" + } + ], + "https://github.com/AonekoSS/ComfyUI-SimpleCounter": [ + [ + "Simple Counter" + ], + { + "title_aux": "ComfyUI-SimpleCounter" + } + ], + "https://github.com/ArcherFMY/Diffusion360_ComfyUI": [ + [ + "Diffusion360LoaderImage2Pano", + "Diffusion360LoaderText2Pano", + "Diffusion360Sampler", + "Diffusion360SamplerImage2Pano", + "Diffusion360SamplerText2Pano", + "InputImage", + "InputText", + "VAEDecodeTiledBlended" + ], + { + "title_aux": "Diffusion360_ComfyUI" + } + ], + "https://github.com/ArdeniusAI/CPlus_Ardenius": [ + [ + "Control_Box" + ], + { + "author": "initials AMA", + "description": "CPlus control box is designed to gather workflow variables into 1 node for easier control of your workflow.", + "nickname": "Ardenius", + "title": "Ardenius", + "title_aux": "CPlus_Ardenius ComfyUI Control Box" + } + ], + "https://github.com/ArtBot2023/CharacterFaceSwap": [ + [ + "Color Blend", + "Crop Face", + "Exclude Facial Feature", + "Generation Parameter Input", + "Generation Parameter Output", + "Image Full BBox", + "Load BiseNet", + "Load RetinaFace", + "Mask Contour", + "Segment Face", + "Uncrop Face" + ], + { + "title_aux": "Character Face Swap" + } + ], + "https://github.com/ArtVentureX/comfyui-animatediff": [ + [ + "AnimateDiffCombine", + "AnimateDiffLoraLoader", + "AnimateDiffModuleLoader", + "AnimateDiffSampler", + "AnimateDiffSlidingWindowOptions", + "ImageSizeAndBatchSize", + "LoadVideo" + ], + { + "title_aux": "AnimateDiff" + } + ], + "https://github.com/AshMartian/ComfyUI-DirGir": [ + [ + "Dir_Gir_Looper", + "Dir_Gir_Picker", + "Gir_Image_Nabber" + ], + { + "title_aux": "Dir Gir" + } + ], + "https://github.com/AuroBit/ComfyUI-AnimateAnyone-reproduction": [ + [ + "AnimateAnyone" + ], + { + "title_aux": "ComfyUI-AnimateAnyone-reproduction" + } + ], + "https://github.com/AustinMroz/ComfyUI-DynamicOversampling": [ + [ + "DynamicSampler", + "MeasuredSampler", + "ResolveMaskPromise" + ], + { + "title_aux": "DynamicOversampling" + } + ], + "https://github.com/AustinMroz/ComfyUI-SpliceTools": [ + [ + "LogSigmas", + "RerangeSigmas", + "SpliceDenoised", + "SpliceLatents", + "TemporalSplice" + ], + { + "title_aux": "SpliceTools" + } + ], + "https://github.com/Auttasak-L/ComfyUI-ImageCropper": [ + [ + "ImageCropper" + ], + { + "title_aux": "ComfyUI-ImageCropper" + } + ], + "https://github.com/BAIS1C/ComfyUI_RSS_Feed_Reader": [ + [ + "RSSFeedNode" + ], + { + "title_aux": "ComfyUI_RSS_Feed_Reader" + } + ], + "https://github.com/BXYMartin/ComfyUI-InstantIDUtils": [ + [ + "ListOfImages", + "MultiControlNetConverter", + "NHWC2NCHWTensor", + "NHWCTensor2PIL", + "PIL2NHWCTensor" + ], + { + "title_aux": "ComfyUI-InstantIDUtils" + } + ], + "https://github.com/BadCafeCode/masquerade-nodes-comfyui": [ + [ + "Blur", + "Change Channel Count", + "Combine Masks", + "Constant Mask", + "Convert Color Space", + "Create QR Code", + "Create Rect Mask", + "Cut By Mask", + "Get Image Size", + "Image To Mask", + "Make Image Batch", + "Mask By Text", + "Mask Morphology", + "Mask To Region", + "MasqueradeIncrementer", + "Mix Color By Mask", + "Mix Images By Mask", + "Paste By Mask", + "Prune By Mask", + "Separate Mask Components", + "Unary Image Op", + "Unary Mask Op" + ], + { + "title_aux": "Masquerade Nodes" + } + ], + "https://github.com/Beinsezii/bsz-cui-extras": [ + [ + "BSZAbsoluteHires", + "BSZAspectHires", + "BSZColoredLatentImageXL", + "BSZCombinedHires", + "BSZHueChromaXL", + "BSZInjectionKSampler", + "BSZLatentDebug", + "BSZLatentFill", + "BSZLatentGradient", + "BSZLatentHSVAImage", + "BSZLatentOffsetXL", + "BSZLatentRGBAImage", + "BSZLatentbuster", + "BSZPixelbuster", + "BSZPixelbusterHelp", + "BSZPrincipledConditioning", + "BSZPrincipledSampler", + "BSZPrincipledScale", + "BSZStrangeResample" + ], + { + "title_aux": "bsz-cui-extras" + } + ], + "https://github.com/BenNarum/SigmaWaveFormNode": [ + [ + "AttenuatorNode", + "FourierFilterNode", + "PhaseLockedLoopNode", + "SigmaWaveFormNode", + "SigmaWaveFormNodeAdvanced", + "SigmaWaveFormNodeSimple" + ], + { + "title_aux": "SigmaWaveFormNodes" + } + ], + "https://github.com/BennyKok/comfyui-deploy": [ + [ + "ComfyDeployWebscoketImageInput", + "ComfyDeployWebscoketImageOutput", + "ComfyUIDeployExternalBoolean", + "ComfyUIDeployExternalCheckpoint", + "ComfyUIDeployExternalImage", + "ComfyUIDeployExternalImageAlpha", + "ComfyUIDeployExternalImageBatch", + "ComfyUIDeployExternalLora", + "ComfyUIDeployExternalNumber", + "ComfyUIDeployExternalNumberInt", + "ComfyUIDeployExternalNumberSlider", + "ComfyUIDeployExternalText", + "ComfyUIDeployExternalVid", + "ComfyUIDeployExternalVideo" + ], + { + "author": "BennyKok", + "description": "", + "nickname": "Comfy Deploy", + "title": "comfyui-deploy", + "title_aux": "ComfyUI Deploy" + } + ], + "https://github.com/Big-Idea-Technology/ComfyUI-Book-Tools": [ + [ + "BTPromptSchedule", + "BTPromptSelector", + "EndQueue", + "ImageTextOverlay", + "Loop", + "LoopEnd", + "LoopStart" + ], + { + "title_aux": "ComfyUI-Book-Tools Nodes for ComfyUI" + } + ], + "https://github.com/Big-Idea-Technology/ComfyUI_LLM_Node": [ + [ + "AdvOptions_Node", + "CodingOptionsNode", + "LLM_Node", + "Output_Node", + "QuantizationConfig_Node" + ], + { + "title_aux": "LLM Node for ComfyUI" + } + ], + "https://github.com/Bikecicle/ComfyUI-Waveform-Extensions/raw/main/EXT_AudioManipulation.py": [ + [ + "BatchJoinAudio", + "CutAudio", + "DuplicateAudio", + "JoinAudio", + "ResampleAudio", + "ReverseAudio", + "StretchAudio" + ], + { + "title_aux": "Waveform Extensions" + } + ], + "https://github.com/Billius-AI/ComfyUI-Path-Helper": [ + [ + "Add File Name Prefix", + "Add File Name Prefix Advanced", + "Add Folder", + "Add Folder Advanced", + "Create Project Root", + "Join Variables", + "Show Path", + "Show String" + ], + { + "title_aux": "ComfyUI-Path-Helper" + } + ], + "https://github.com/BlakeOne/ComfyUI-CustomScheduler": [ + [ + "CustomScheduler" + ], + { + "title_aux": "ComfyUI CustomScheduler" + } + ], + "https://github.com/BlakeOne/ComfyUI-SchedulerMixer": [ + [ + "SchedulerMixer" + ], + { + "title_aux": "ComfyUI SchedulerMixer" + } + ], + "https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb": [ + [ + "BNK_AddCLIPSDXLParams", + "BNK_AddCLIPSDXLRParams", + "BNK_CLIPTextEncodeAdvanced", + "BNK_CLIPTextEncodeSDXLAdvanced" + ], + { + "title_aux": "Advanced CLIP Text Encode" + } + ], + "https://github.com/BlenderNeko/ComfyUI_Cutoff": [ + [ + "BNK_CutoffBasePrompt", + "BNK_CutoffRegionsToConditioning", + "BNK_CutoffRegionsToConditioning_ADV", + "BNK_CutoffSetRegions" + ], + { + "title_aux": "ComfyUI Cutoff" + } + ], + "https://github.com/BlenderNeko/ComfyUI_Noise": [ + [ + "BNK_DuplicateBatchIndex", + "BNK_GetSigma", + "BNK_InjectNoise", + "BNK_NoisyLatentImage", + "BNK_SlerpLatent", + "BNK_Unsampler" + ], + { + "title_aux": "ComfyUI Noise" + } + ], + "https://github.com/BlenderNeko/ComfyUI_SeeCoder": [ + [ + "ConcatConditioning", + "SEECoderImageEncode" + ], + { + "title_aux": "SeeCoder [WIP]" + } + ], + "https://github.com/BlenderNeko/ComfyUI_TiledKSampler": [ + [ + "BNK_TiledKSampler", + "BNK_TiledKSamplerAdvanced" + ], + { + "title_aux": "Tiled sampling for ComfyUI" + } + ], + "https://github.com/CC-BryanOttho/ComfyUI_API_Manager": [ + [ + "APIRequestNode", + "PostImageToAPI", + "TextPromptCombinerNode" + ], + { + "title_aux": "ComfyUI_API_Manager" + } + ], + "https://github.com/CYBERLOOM-INC/ComfyUI-nodes-hnmr": [ + [ + "CLIPIter", + "Dict2Model", + "GridImage", + "ImageBlend2", + "KSamplerOverrided", + "KSamplerSetting", + "KSamplerXYZ", + "LatentToHist", + "LatentToImage", + "ModelIter", + "RandomLatentImage", + "SaveStateDict", + "SaveText", + "StateDictLoader", + "StateDictMerger", + "StateDictMergerBlockWeighted", + "StateDictMergerBlockWeightedMulti", + "VAEDecodeBatched", + "VAEEncodeBatched", + "VAEIter" + ], + { + "title_aux": "ComfyUI-nodes-hnmr" + } + ], + "https://github.com/CaptainGrock/ComfyUIInvisibleWatermark/raw/main/Invisible%20Watermark.py": [ + [ + "Apply Invisible Watermark", + "Extract Watermark" + ], + { + "title_aux": "ComfyUIInvisibleWatermark" + } + ], + "https://github.com/Chan-0312/ComfyUI-EasyDeforum": [ + [ + "Easy2DDeforum" + ], + { + "title_aux": "ComfyUI-EasyDeforum" + } + ], + "https://github.com/Chan-0312/ComfyUI-IPAnimate": [ + [ + "IPAdapterAnimate" + ], + { + "title_aux": "ComfyUI-IPAnimate" + } + ], + "https://github.com/Chan-0312/ComfyUI-Prompt-Preview": [ + [ + "SDXLPromptStylerAdvancedPreview", + "SDXLPromptStylerPreview" + ], + { + "title_aux": "ComfyUI-Prompt-Preview" + } + ], + "https://github.com/Chaoses-Ib/ComfyUI_Ib_CustomNodes": [ + [ + "ImageToPIL", + "LoadImageFromPath", + "PILToImage", + "PILToMask" + ], + { + "title_aux": "ComfyUI_Ib_CustomNodes" + } + ], + "https://github.com/Clybius/ComfyUI-Extra-Samplers": [ + [ + "GeometricCFGGuider", + "ImageAssistedCFGGuider", + "MegaCFGGuider", + "SamplerCLYB_4M_SDE_Momentumized", + "SamplerCustomModelMixtureDuo", + "SamplerCustomNoise", + "SamplerCustomNoiseDuo", + "SamplerDPMPP_3M_SDE_DynETA", + "SamplerDPMPP_DualSDE_Momentumized", + "SamplerEulerAncestralDancing_Experimental", + "SamplerLCMCustom", + "SamplerRES_Momentumized", + "SamplerSupreme", + "SamplerTTM", + "ScaledCFGGuider", + "SimpleExponentialScheduler", + "WarmupDecayCFGGuider" + ], + { + "title_aux": "ComfyUI Extra Samplers" + } + ], + "https://github.com/Clybius/ComfyUI-Latent-Modifiers": [ + [ + "Latent Diffusion Mega Modifier" + ], + { + "title_aux": "ComfyUI-Latent-Modifiers" + } + ], + "https://github.com/CosmicLaca/ComfyUI_Primere_Nodes": [ + [ + "PrimereAestheticCKPTScorer", + "PrimereAnyDetailer", + "PrimereAnyOutput", + "PrimereCKPT", + "PrimereCKPTLoader", + "PrimereCLIPEncoder", + "PrimereClearPrompt", + "PrimereConceptDataTuple", + "PrimereDynamicParser", + "PrimereEmbedding", + "PrimereEmbeddingHandler", + "PrimereEmbeddingKeywordMerger", + "PrimereEmotionsStyles", + "PrimereHypernetwork", + "PrimereImageSegments", + "PrimereKSampler", + "PrimereLCMSelector", + "PrimereLORA", + "PrimereLYCORIS", + "PrimereLatentNoise", + "PrimereLoraKeywordMerger", + "PrimereLoraStackMerger", + "PrimereLycorisKeywordMerger", + "PrimereLycorisStackMerger", + "PrimereMetaCollector", + "PrimereMetaDistributor", + "PrimereMetaDistributorStage2", + "PrimereMetaHandler", + "PrimereMetaRead", + "PrimereMetaSave", + "PrimereMidjourneyStyles", + "PrimereModelConceptSelector", + "PrimereModelKeyword", + "PrimereNetworkTagLoader", + "PrimerePreviewImage", + "PrimerePrompt", + "PrimerePromptOrganizer", + "PrimerePromptSwitch", + "PrimereRefinerPrompt", + "PrimereResolution", + "PrimereResolutionCoordinatorMPX", + "PrimereResolutionMultiplier", + "PrimereResolutionMultiplierMPX", + "PrimereSamplers", + "PrimereSamplersSteps", + "PrimereSeed", + "PrimereStepsCfg", + "PrimereStyleLoader", + "PrimereStylePile", + "PrimereTextOutput", + "PrimereUpscaleModel", + "PrimereVAE", + "PrimereVAELoader", + "PrimereVAESelector", + "PrimereVisualCKPT", + "PrimereVisualEmbedding", + "PrimereVisualHypernetwork", + "PrimereVisualLORA", + "PrimereVisualLYCORIS", + "PrimereVisualStyle" + ], + { + "title_aux": "Primere nodes for ComfyUI" + } + ], + "https://github.com/Danand/ComfyUI-ComfyCouple": [ + [ + "Attention couple", + "Comfy Couple" + ], + { + "author": "Rei D.", + "description": "If you want to draw two different characters together without blending their features, so you could try to check out this custom node.", + "nickname": "Danand", + "title": "Comfy Couple", + "title_aux": "Comfy Couple" + } + ], + "https://github.com/DannyStone1999/ComfyUI-Depth2Mask/raw/main/Depth2Mask.py": [ + [ + "Depth2Mask" + ], + { + "title_aux": "ComfyUI-Depth2Mask" + } + ], + "https://github.com/DarKDinDoN/comfyui-checkpoint-automatic-config": [ + [ + "CheckpointAutomaticConfig", + "ConfigPipe" + ], + { + "title_aux": "ComfyUI Checkpoint Automatic Config" + } + ], + "https://github.com/DataCTE/prompt_injection": [ + [ + "AdvancedPromptInjection", + "PromptInjection", + "SVDPromptInjection", + "SimplePromptInjection" + ], + { + "title_aux": "Prompt Injection Node for ComfyUI" + } + ], + "https://github.com/DeJoker/pipeline-parallel-comfy": [ + [ + "PipelineParallel" + ], + { + "title_aux": "Pipeline Parallel ComfyUI" + } + ], + "https://github.com/Derfuu/Derfuu_ComfyUI_ModdedNodes": [ + [], + { + "author": "Derfuu", + "description": "Pack of simple (or not) and modded nodes for scaling images/latents, editing numbers or text. Automate calculations depending on image sizes or any other thing you want. Or randomize any number in your workflow. Debug node included.", + "nickname": "Derfuu simple/modded Nodes", + "nodename_pattern": "^DF_", + "title": "Derfuu simple/modded Nodes", + "title_aux": "Derfuu_ComfyUI_ModdedNodes" + } + ], + "https://github.com/DonBaronFactory/ComfyUI-Cre8it-Nodes": [ + [ + "ApplySerialPrompter", + "ImageSizer", + "SerialPrompter" + ], + { + "author": "CRE8IT GmbH", + "description": "This extension offers various nodes.", + "nickname": "cre8Nodes", + "title": "cr8SerialPrompter", + "title_aux": "ComfyUI-Cre8it-Nodes" + } + ], + "https://github.com/DrMWeigand/ComfyUI_ColorImageDetection": [ + [ + "LABColorDetection", + "RGBColorDetection" + ], + { + "title_aux": "ComfyUI Color Detection Nodes" + } + ], + "https://github.com/Electrofried/ComfyUI-OpenAINode": [ + [ + "OpenAINode" + ], + { + "title_aux": "OpenAINode" + } + ], + "https://github.com/EllangoK/ComfyUI-post-processing-nodes": [ + [ + "ArithmeticBlend", + "AsciiArt", + "Blend", + "Blur", + "CannyEdgeMask", + "ChromaticAberration", + "ColorCorrect", + "ColorTint", + "Dissolve", + "Dither", + "DodgeAndBurn", + "FilmGrain", + "Glow", + "HSVThresholdMask", + "KMeansQuantize", + "KuwaharaBlur", + "Parabolize", + "PencilSketch", + "PixelSort", + "Pixelize", + "Quantize", + "Sharpen", + "SineWave", + "Solarize", + "Vignette" + ], + { + "title_aux": "ComfyUI-post-processing-nodes" + } + ], + "https://github.com/ExponentialML/ComfyUI_ModelScopeT2V": [ + [ + "ModelScopeT2VLoader" + ], + { + "title_aux": "ComfyUI_ModelScopeT2V" + } + ], + "https://github.com/ExponentialML/ComfyUI_Native_DynamiCrafter": [ + [ + "DynamiCrafterLoader", + "DynamiCrafterProcessor" + ], + { + "title_aux": "ComfyUI - Native DynamiCrafter" + } + ], + "https://github.com/ExponentialML/ComfyUI_VisualStylePrompting": [ + [ + "ApplyVisualStyle" + ], + { + "title_aux": "ComfyUI_VisualStylePrompting" + } + ], + "https://github.com/Extraltodeus/ComfyUI-AutomaticCFG": [ + [ + "Automatic CFG", + "Automatic CFG - Advanced", + "Automatic CFG - Attention modifiers", + "Automatic CFG - Attention modifiers tester", + "Automatic CFG - Custom attentions", + "Automatic CFG - Excellent attention", + "Automatic CFG - Negative", + "Automatic CFG - Post rescale only", + "Automatic CFG - Preset Loader", + "Automatic CFG - Unpatch function", + "Automatic CFG - Warp Drive", + "SAG delayed activation", + "Temperature separate settings CLIP SDXL", + "Temperature settings CLIP", + "Temperature settings SD 1.5", + "Temperature settings SDXL", + "Zero Uncond CFG - standalone patch (incompatible with the others)" + ], + { + "title_aux": "ComfyUI-AutomaticCFG" + } + ], + "https://github.com/Extraltodeus/LoadLoraWithTags": [ + [ + "LoraLoaderTagsQuery" + ], + { + "title_aux": "LoadLoraWithTags" + } + ], + "https://github.com/Extraltodeus/Stable-Diffusion-temperature-settings": [ + [ + "CLIP Temperature", + "Unet Temperature" + ], + { + "title_aux": "Stable-Diffusion-temperature-settings" + } + ], + "https://github.com/Extraltodeus/Uncond-Zero-for-ComfyUI": [ + [ + "Conditioning combine positive and negative", + "Conditioning crop or fill", + "Uncond Zero", + "interrupt on NaN" + ], + { + "title_aux": "Uncond-Zero-for-ComfyUI" + } + ], + "https://github.com/Extraltodeus/Vector_Sculptor_ComfyUI": [ + [ + "CLIP Vector Sculptor text encode", + "Conditioning (Average keep magnitude)", + "Conditioning (Slerp)", + "Conditioning SDXL merge clip_g / clip_l", + "Conditioning normalize magnitude to empty" + ], + { + "title_aux": "Vector_Sculptor_ComfyUI" + } + ], + "https://github.com/Extraltodeus/noise_latent_perlinpinpin": [ + [ + "NoisyLatentPerlin" + ], + { + "title_aux": "noise latent perlinpinpin" + } + ], + "https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI": [ + [ + "Pre CFG automatic scale", + "Pre CFG consensus sharpening", + "Pre CFG exponentiation", + "Pre CFG perp-neg", + "Pre CFG sharpening" + ], + { + "title_aux": "pre_cfg_comfy_nodes_for_ComfyUI" + } + ], + "https://github.com/Extraltodeus/sigmas_tools_and_the_golden_scheduler": [ + [ + "Aligned Scheduler", + "Gaussian Tail Scheduler", + "Get sigmas as float", + "Graph sigmas", + "Manual scheduler", + "Merge many sigmas by average", + "Merge sigmas by average", + "Merge sigmas gradually", + "Multiply sigmas", + "Output min/max sigmas", + "Split and concatenate sigmas", + "The Golden Scheduler" + ], + { + "title_aux": "sigmas_tools_and_the_golden_scheduler" + } + ], + "https://github.com/Fannovel16/ComfyUI-Frame-Interpolation": [ + [ + "AMT VFI", + "CAIN VFI", + "FILM VFI", + "FLAVR VFI", + "GMFSS Fortuna VFI", + "IFRNet VFI", + "IFUnet VFI", + "KSampler Gradually Adding More Denoise (efficient)", + "M2M VFI", + "Make Interpolation State List", + "RIFE VFI", + "STMFNet VFI", + "Sepconv VFI", + "VFI FloatToInt" + ], + { + "title_aux": "ComfyUI Frame Interpolation" + } + ], + "https://github.com/Fannovel16/ComfyUI-Loopchain": [ + [ + "EmptyLatentImageLoop", + "FolderToImageStorage", + "ImageStorageExportLoop", + "ImageStorageImport", + "ImageStorageReset", + "LatentStorageExportLoop", + "LatentStorageImport", + "LatentStorageReset" + ], + { + "title_aux": "ComfyUI Loopchain" + } + ], + "https://github.com/Fannovel16/ComfyUI-MagickWand": [ + [ + "ImageMagick Adaptive Blur", + "ImageMagick Adaptive Resize", + "ImageMagick Adaptive Sharpen", + "ImageMagick Adaptive Threshold", + "ImageMagick Auto Gamma", + "ImageMagick Auto Level", + "ImageMagick Auto Orient", + "ImageMagick Auto Threshold", + "ImageMagick Blue Shift", + "ImageMagick Blur", + "ImageMagick Brightness Contrast", + "ImageMagick Canny", + "ImageMagick Charcoal", + "ImageMagick Chop", + "ImageMagick Clahe", + "ImageMagick Clamp", + "ImageMagick Coalesce", + "ImageMagick Color Decision List", + "ImageMagick Color Matrix", + "ImageMagick Combine", + "ImageMagick Concat", + "ImageMagick Contrast", + "ImageMagick Contrast Stretch", + "ImageMagick Crop", + "ImageMagick Cycle Color Map", + "ImageMagick Decipher", + "ImageMagick Despeckle", + "ImageMagick Distort", + "ImageMagick Edge", + "ImageMagick Emboss", + "ImageMagick Encipher", + "ImageMagick Enhance", + "ImageMagick Equalize", + "ImageMagick Evaluate", + "ImageMagick Extent", + "ImageMagick Flip", + "ImageMagick Flop", + "ImageMagick Forward Fourier Transform", + "ImageMagick Function", + "ImageMagick Gamma", + "ImageMagick Gaussian Blur", + "ImageMagick Hough Lines", + "ImageMagick Implode", + "ImageMagick Kmeans", + "ImageMagick Kuwahara", + "ImageMagick Level", + "ImageMagick Levelize", + "ImageMagick Linear Stretch", + "ImageMagick Liquid Rescale", + "ImageMagick Local Contrast", + "ImageMagick Magnify", + "ImageMagick Mean Shift", + "ImageMagick Merge Layers", + "ImageMagick Mode", + "ImageMagick Modulate", + "ImageMagick Morphology", + "ImageMagick Motion Blur", + "ImageMagick Negate", + "ImageMagick Noise", + "ImageMagick Normalize", + "ImageMagick Oil Paint", + "ImageMagick Ordered Dither", + "ImageMagick Polynomial", + "ImageMagick Posterize", + "ImageMagick Quantize", + "ImageMagick Random Threshold", + "ImageMagick Range Threshold", + "ImageMagick Resample", + "ImageMagick Resize", + "ImageMagick Roll", + "ImageMagick Rotational Blur", + "ImageMagick Sample", + "ImageMagick Scale", + "ImageMagick Selective Blur", + "ImageMagick Sepia Tone", + "ImageMagick Shade", + "ImageMagick Shadow", + "ImageMagick Sharpen", + "ImageMagick Shave", + "ImageMagick Sigmoidal Contrast", + "ImageMagick Sketch", + "ImageMagick Smush", + "ImageMagick Solarize", + "ImageMagick Splice", + "ImageMagick Spread", + "ImageMagick Statistic", + "ImageMagick Swirl", + "ImageMagick Threshold", + "ImageMagick Thumbnail", + "ImageMagick Transform", + "ImageMagick Transform Colorspace", + "ImageMagick Transparentize", + "ImageMagick Transpose", + "ImageMagick Transverse", + "ImageMagick Unsharp Mask", + "ImageMagick Vignette", + "ImageMagick Wave", + "ImageMagick Wavelet Denoise", + "ImageMagick White Balance" + ], + { + "title_aux": "ComfyUI-MagickWand" + } + ], + "https://github.com/Fannovel16/ComfyUI-MotionDiff": [ + [ + "EmptyMotionData", + "ExportSMPLTo3DSoftware", + "Export_SMPLMultipleSubjects_To_3DSoftware", + "Human4D_Img2SMPL", + "Humans4DLoader", + "MotionCLIPTextEncode", + "MotionDataVisualizer", + "MotionDiffLoader", + "MotionDiffSimpleSampler", + "RenderMultipleSubjectsSMPLMesh", + "RenderSMPLMesh", + "Render_OpenPose_From_SMPL_Mesh_Multiple_Subjects", + "SMPLLoader", + "SMPLShapeParameters", + "SaveSMPL", + "SmplifyMotionData", + "SpectreFaceReconLoader", + "SpectreImg2SMPL", + "mgpt_model_loader", + "mgpt_t2m" + ], + { + "title_aux": "ComfyUI MotionDiff" + } + ], + "https://github.com/Fannovel16/ComfyUI-Video-Matting": [ + [ + "BRIAAI Matting", + "Robust Video Matting" + ], + { + "title_aux": "ComfyUI-Video-Matting" + } + ], + "https://github.com/Fannovel16/comfyui_controlnet_aux": [ + [ + "AIO_Preprocessor", + "AnimalPosePreprocessor", + "AnimeFace_SemSegPreprocessor", + "AnimeLineArtPreprocessor", + "AnyLineArtPreprocessor_aux", + "BAE-NormalMapPreprocessor", + "BinaryPreprocessor", + "CannyEdgePreprocessor", + "ColorPreprocessor", + "ControlNetPreprocessorSelector", + "DSINE-NormalMapPreprocessor", + "DWPreprocessor", + "DensePosePreprocessor", + "DepthAnythingPreprocessor", + "DepthAnythingV2Preprocessor", + "DiffusionEdge_Preprocessor", + "FacialPartColoringFromPoseKps", + "FakeScribblePreprocessor", + "HEDPreprocessor", + "HintImageEnchance", + "ImageGenResolutionFromImage", + "ImageGenResolutionFromLatent", + "ImageIntensityDetector", + "ImageLuminanceDetector", + "InpaintPreprocessor", + "LeReS-DepthMapPreprocessor", + "LineArtPreprocessor", + "LineartStandardPreprocessor", + "M-LSDPreprocessor", + "Manga2Anime_LineArt_Preprocessor", + "MaskOptFlow", + "MediaPipe-FaceMeshPreprocessor", + "MeshGraphormer+ImpactDetector-DepthMapPreprocessor", + "MeshGraphormer-DepthMapPreprocessor", + "Metric3D-DepthMapPreprocessor", + "Metric3D-NormalMapPreprocessor", + "Metric_DepthAnythingV2Preprocessor", + "MiDaS-DepthMapPreprocessor", + "MiDaS-NormalMapPreprocessor", + "OneFormer-ADE20K-SemSegPreprocessor", + "OneFormer-COCO-SemSegPreprocessor", + "OpenposePreprocessor", + "PiDiNetPreprocessor", + "PixelPerfectResolution", + "RenderAnimalKps", + "RenderPeopleKps", + "SAMPreprocessor", + "SavePoseKpsAsJsonFile", + "ScribblePreprocessor", + "Scribble_PiDiNet_Preprocessor", + "Scribble_XDoG_Preprocessor", + "SemSegPreprocessor", + "ShufflePreprocessor", + "TEEDPreprocessor", + "TTPlanet_TileGF_Preprocessor", + "TTPlanet_TileSimple_Preprocessor", + "TilePreprocessor", + "UniFormer-SemSegPreprocessor", + "Unimatch_OptFlowPreprocessor", + "UpperBodyTrackingFromPoseKps", + "Zoe-DepthMapPreprocessor", + "Zoe_DepthAnythingPreprocessor" + ], + { + "author": "tstandley", + "preemptions": [ + "AIO_Preprocessor", + "AnimalPosePreprocessor", + "AnimeFace_SemSegPreprocessor", + "AnimeLineArtPreprocessor", + "BAE-NormalMapPreprocessor", + "BinaryPreprocessor", + "CannyEdgePreprocessor", + "ColorPreprocessor", + "DSINE-NormalMapPreprocessor", + "DWPreprocessor", + "DensePosePreprocessor", + "DepthAnythingPreprocessor", + "DiffusionEdge_Preprocessor", + "FacialPartColoringFromPoseKps", + "FakeScribblePreprocessor", + "HEDPreprocessor", + "HintImageEnchance", + "ImageGenResolutionFromImage", + "ImageGenResolutionFromLatent", + "ImageIntensityDetector", + "ImageLuminanceDetector", + "InpaintPreprocessor", + "LeReS-DepthMapPreprocessor", + "LineArtPreprocessor", + "LineartStandardPreprocessor", + "M-LSDPreprocessor", + "Manga2Anime_LineArt_Preprocessor", + "MaskOptFlow", + "MediaPipe-FaceMeshPreprocessor", + "MeshGraphormer-DepthMapPreprocessor", + "MiDaS-DepthMapPreprocessor", + "MiDaS-NormalMapPreprocessor", + "OneFormer-ADE20K-SemSegPreprocessor", + "OneFormer-COCO-SemSegPreprocessor", + "OpenposePreprocessor", + "PiDiNetPreprocessor", + "PixelPerfectResolution", + "SAMPreprocessor", + "SavePoseKpsAsJsonFile", + "ScribblePreprocessor", + "Scribble_XDoG_Preprocessor", + "SemSegPreprocessor", + "ShufflePreprocessor", + "TEEDPreprocessor", + "TilePreprocessor", + "UniFormer-SemSegPreprocessor", + "Unimatch_OptFlowPreprocessor", + "Zoe-DepthMapPreprocessor", + "Zoe_DepthAnythingPreprocessor" + ], + "title_aux": "ComfyUI's ControlNet Auxiliary Preprocessors" + } + ], + "https://github.com/Fantaxico/ComfyUI-GCP-Storage": [ + [ + "GCPStorageNode" + ], + { + "title_aux": "ComfyUI-GCP-Storage" + } + ], + "https://github.com/Feidorian/feidorian-ComfyNodes": [ + [], + { + "nodename_pattern": "^Feidorian_", + "title_aux": "feidorian-ComfyNodes" + } + ], + "https://github.com/Fictiverse/ComfyUI_Fictiverse": [ + [ + "Add Noise to Image with Mask", + "Color correction", + "Displace Image with Depth", + "Displace Images with Mask", + "Zoom Image with Depth" + ], + { + "title_aux": "ComfyUI Fictiverse Nodes" + } + ], + "https://github.com/Fihade/IC-Light-ComfyUI-Node": [ + [ + "LoadICLightUnetDiffusers", + "diffusers_model_loader", + "iclight_diffusers_sampler" + ], + { + "title_aux": "IC-Light-ComfyUI-Node" + } + ], + "https://github.com/FizzleDorf/ComfyUI-AIT": [ + [ + "AIT_Unet_Loader", + "AIT_VAE_Encode_Loader" + ], + { + "title_aux": "ComfyUI-AIT" + } + ], + "https://github.com/FizzleDorf/ComfyUI_FizzNodes": [ + [ + "AbsCosWave", + "AbsSinWave", + "BatchGLIGENSchedule", + "BatchPromptSchedule", + "BatchPromptScheduleEncodeSDXL", + "BatchPromptScheduleLatentInput", + "BatchPromptScheduleNodeFlowEnd", + "BatchPromptScheduleSDXLLatentInput", + "BatchStringSchedule", + "BatchValueSchedule", + "BatchValueScheduleLatentInput", + "CalculateFrameOffset", + "ConcatStringSingle", + "CosWave", + "FizzFrame", + "FizzFrameConcatenate", + "ImagesFromBatchSchedule", + "Init FizzFrame", + "InvCosWave", + "InvSinWave", + "Lerp", + "PromptSchedule", + "PromptScheduleEncodeSDXL", + "PromptScheduleNodeFlow", + "PromptScheduleNodeFlowEnd", + "SawtoothWave", + "SinWave", + "SquareWave", + "StringConcatenate", + "StringSchedule", + "TriangleWave", + "ValueSchedule", + "convertKeyframeKeysToBatchKeys" + ], + { + "title_aux": "FizzNodes" + } + ], + "https://github.com/FlyingFireCo/tiled_ksampler": [ + [ + "Asymmetric Tiled KSampler", + "Circular VAEDecode", + "Tiled KSampler" + ], + { + "title_aux": "tiled_ksampler" + } + ], + "https://github.com/ForeignGods/ComfyUI-Mana-Nodes": [ + [ + "Canvas Properties", + "Combine Video", + "Font Properties", + "Generate Audio", + "Preset Color Animations", + "Save/Preview Text", + "Scheduled Values", + "Speech Recognition", + "Split Video", + "Text to Image Generator" + ], + { + "title_aux": "ComfyUI-Mana-Nodes" + } + ], + "https://github.com/Franck-Demongin/NX_PromptStyler": [ + [ + "NX_PromptStyler" + ], + { + "title_aux": "NX_PromptStyler" + } + ], + "https://github.com/FuouM/ComfyUI-FirstOrderMM": [ + [ + "FOMM_Partswap", + "FOMM_Runner", + "FOMM_Seg10Chooser", + "FOMM_Seg15Chooser", + "FOMM_Seg5Chooser" + ], + { + "author": "Fuou Marinas", + "description": "Run First Order Motion Model for Image Animation in ComfyUI.", + "nickname": "FOMM", + "title": "ComfyUI-FirstOrderMM", + "title_aux": "ComfyUI-FirstOrderMM" + } + ], + "https://github.com/G-370/ComfyUI-SD3-Powerlab": [ + [ + "G370SD3PowerLab_AttentionToImage", + "G370SD3PowerLab_ImageIntoAttention", + "G370SD3PowerLab_ImageIntoLayer", + "G370SD3PowerLab_LayerToImage", + "G370SD3PowerLab_RenderAttention" + ], + { + "title_aux": "ComfyUI-SD3-Powerlab" + } + ], + "https://github.com/GMapeSplat/ComfyUI_ezXY": [ + [ + "ConcatenateString", + "ItemFromDropdown", + "IterationDriver", + "JoinImages", + "LineToConsole", + "NumberFromList", + "NumbersToList", + "PlotImages", + "StringFromList", + "StringToLabel", + "StringsToList", + "ezMath", + "ezXY_AssemblePlot", + "ezXY_Driver" + ], + { + "title_aux": "ezXY scripts and nodes" + } + ], + "https://github.com/GTSuya-Studio/ComfyUI-Gtsuya-Nodes": [ + [ + "Danbooru (ID)", + "Danbooru (Random)", + "Random File From Path", + "Replace Strings", + "Simple Wildcards", + "Simple Wildcards (Dir.)", + "Wildcards Nodes" + ], + { + "title_aux": "ComfyUI-GTSuya-Nodes" + } + ], + "https://github.com/GavChap/ComfyUI-SD3LatentSelectRes": [ + [ + "SD3LatentSelectRes" + ], + { + "title_aux": "ComfyUI-SD3LatentSelectRes" + } + ], + "https://github.com/GentlemanHu/ComfyUI-SunoAI": [ + [ + "GentlemanHu_SunoAI", + "GentlemanHu_SunoAI_NotSafe" + ], + { + "title_aux": "ComfyUI Suno API" + } + ], + "https://github.com/Goktug/comfyui-saveimage-plus": [ + [ + "SaveImagePlus" + ], + { + "title_aux": "Save Image Plus for ComfyUI" + } + ], + "https://github.com/Gourieff/comfyui-reactor-node": [ + [ + "ImageRGBA2RGB", + "ReActorBuildFaceModel", + "ReActorFaceBoost", + "ReActorFaceSwap", + "ReActorFaceSwapOpt", + "ReActorImageDublicator", + "ReActorLoadFaceModel", + "ReActorMakeFaceModelBatch", + "ReActorMaskHelper", + "ReActorOptions", + "ReActorRestoreFace", + "ReActorSaveFaceModel" + ], + { + "title_aux": "ReActor Node for ComfyUI" + } + ], + "https://github.com/GraftingRayman/ComfyUI_GraftingRayman": [ + [ + "GR Background Remover REMBG", + "GR Checkered Board", + "GR Counter", + "GR Flip Tile Random Inverted", + "GR Flip Tile Random Red Ring", + "GR Image Details Displayer", + "GR Image Details Saver", + "GR Image Paste", + "GR Image Paste With Mask", + "GR Image Resize", + "GR Image Resize Methods", + "GR Image Size", + "GR Image/Depth Mask", + "GR Mask Create", + "GR Mask Create Random", + "GR Mask Resize", + "GR Multi Mask Create", + "GR Onomatopoeia", + "GR Prompt HUB", + "GR Prompt Selector", + "GR Prompt Selector Multi", + "GR Scroller", + "GR Stack Image", + "GR Text Overlay", + "GR Tile and Border Image", + "GR Tile and Border Image Random Flip" + ], + { + "title_aux": "GraftingRayman" + } + ], + "https://github.com/Grant-CP/ComfyUI-LivePortraitKJ-MPS": [ + [ + "DownloadAndLoadLivePortraitModels", + "LivePortraitProcess" + ], + { + "title_aux": "ComfyUI-LivePortraitKJ-MPS" + } + ], + "https://github.com/GreenLandisaLie/AuraSR-ComfyUI": [ + [ + "AuraSR.AuraSRUpscaler" + ], + { + "title_aux": "AuraSR-ComfyUI" + } + ], + "https://github.com/Guillaume-Fgt/ComfyUI_StableCascadeLatentRatio": [ + [ + "StableCascadeLatentRatio" + ], + { + "title_aux": "ComfyUI_StableCascadeLatentRatio" + } + ], + "https://github.com/HAL41/ComfyUI-aichemy-nodes": [ + [ + "aichemyYOLOv8Segmentation" + ], + { + "title_aux": "ComfyUI aichemy nodes" + } + ], + "https://github.com/HECer/ComfyUI-FilePathCreator": [ + [ + "FilePathCreator" + ], + { + "title_aux": "ComfyUI-FilePathCreator" + } + ], + "https://github.com/Hangover3832/ComfyUI-Hangover-Moondream": [ + [ + "Moondream Interrogator" + ], + { + "author": "AlexL", + "description": "An implementation of the moondream visual LLM", + "nickname": "Hangover-Moondream", + "title": "ComfyUI-Hangover-Moondream", + "title_aux": "ComfyUI-Hangover-Moondream" + } + ], + "https://github.com/Hangover3832/ComfyUI-Hangover-Nodes": [ + [ + "Image Scale Bounding Box", + "MS kosmos-2 Interrogator", + "Make Inpaint Model", + "Save Image w/o Metadata" + ], + { + "author": "AlexL", + "description": "Scales an input image into a given box size, whereby the aspect ratio keeps retained.", + "nickname": "Hangover-Image_Scale_Bouning_Box", + "title": "ComfyUI-Hangover-Image_Scale_Bouning_Box", + "title_aux": "ComfyUI-Hangover-Nodes" + } + ], + "https://github.com/Hangover3832/ComfyUI-Hangover-Recognize_Anything": [ + [ + "Recognize Anything Model (RAM)" + ], + { + "author": "AlexL", + "description": "An implementation of the Recognize Anything Model (RAM++) for ComfyUI. The counterpart of Segment Anything Model (SAM).", + "nickname": "Hangover-Recognize_Anything", + "title": "ComfyUI-Hangover-Recognize_Anything", + "title_aux": "Recognize Anything Model (RAM) for ComfyUI" + } + ], + "https://github.com/Haoming02/comfyui-diffusion-cg": [ + [ + "Normalization", + "NormalizationXL", + "Recenter", + "Recenter XL" + ], + { + "title_aux": "ComfyUI Diffusion Color Grading" + } + ], + "https://github.com/Haoming02/comfyui-floodgate": [ + [ + "FloodGate" + ], + { + "title_aux": "ComfyUI Floodgate" + } + ], + "https://github.com/HaydenReeve/ComfyUI-Better-Strings": [ + [ + "BetterString" + ], + { + "title_aux": "ComfyUI Better Strings" + } + ], + "https://github.com/HebelHuber/comfyui-enhanced-save-node": [ + [ + "EnhancedSaveNode" + ], + { + "title_aux": "comfyui-enhanced-save-node" + } + ], + "https://github.com/Hiero207/ComfyUI-Hiero-Nodes": [ + [ + "Load Prompt Travel file", + "Post to Discord w/ Webhook", + "Save Prompt Travel file" + ], + { + "author": "Hiero", + "description": "Just some nodes that I wanted/needed, so I made them.", + "nickname": "HNodes", + "title": "Hiero-Nodes", + "title_aux": "Hiero-Nodes" + } + ], + "https://github.com/IDGallagher/ComfyUI-IG-Nodes": [ + [ + "IG Analyze SSIM", + "IG Cross Fade Images", + "IG Explorer", + "IG Float", + "IG Float List", + "IG Folder", + "IG Int", + "IG Interpolate", + "IG Load Image", + "IG Load Images", + "IG Multiply", + "IG Path Join", + "IG String", + "IG String List", + "IG ZFill" + ], + { + "author": "IDGallagher", + "description": "Custom nodes to aid in the exploration of Latent Space", + "nickname": "IG Interpolation Nodes", + "title": "IG Interpolation Nodes", + "title_aux": "IG Interpolation Nodes" + } + ], + "https://github.com/ITurchenko/ComfyUI-SizeFromArray": [ + [ + "SizeFromArray" + ], + { + "title_aux": "ComfyUI-SizeFromArray" + } + ], + "https://github.com/ImmortalPie/ComfyUI-PonySwitch/raw/main/PonySwitch.py": [ + [ + "PonySwitch" + ], + { + "title_aux": "PonySwitch Node" + } + ], + "https://github.com/Intersection98/ComfyUI_MX_post_processing-nodes": [ + [ + "MX_AlphaBlend", + "MX_Blend", + "MX_Blur", + "MX_Canny", + "MX_ChromaticAberration", + "MX_ColorCorrect", + "MX_ColorMatch", + "MX_ColorTint", + "MX_Glow", + "MX_HSVThresholdMask", + "MX_KuwaharaBlur(Cartoon)", + "MX_LUT", + "MX_LensBokeh", + "MX_LensOpticAxis", + "MX_LensZoomBurst", + "MX_Mosaic", + "MX_Noise", + "MX_Posterize", + "MX_SineWave", + "MX_Solarize", + "MX_Vignette" + ], + { + "title_aux": "ComfyUI-MX-post-processing-nodes" + } + ], + "https://github.com/Inzaniak/comfyui-ranbooru": [ + [ + "LockSeed", + "PromptBackground", + "PromptLimit", + "PromptMix", + "PromptRandomWeight", + "PromptRemove", + "Ranbooru", + "RanbooruURL", + "RandomPicturePath", + "TimestampFileName" + ], + { + "title_aux": "Ranbooru for ComfyUI" + } + ], + "https://github.com/IsItDanOrAi/ComfyUI-Stereopsis": [ + [ + "Dan_FrameDelay", + "Dan_Stereopsis" + ], + { + "title_aux": "ComfyUI-Stereopsis" + } + ], + "https://github.com/JPS-GER/ComfyUI_JPS-Nodes": [ + [ + "CLIPTextEncode SDXL Plus (JPS)", + "Conditioning Switch (JPS)", + "ControlNet Switch (JPS)", + "Crop Image Pipe (JPS)", + "Crop Image Settings (JPS)", + "Crop Image Square (JPS)", + "Crop Image TargetSize (JPS)", + "CtrlNet CannyEdge Pipe (JPS)", + "CtrlNet CannyEdge Settings (JPS)", + "CtrlNet MiDaS Pipe (JPS)", + "CtrlNet MiDaS Settings (JPS)", + "CtrlNet OpenPose Pipe (JPS)", + "CtrlNet OpenPose Settings (JPS)", + "CtrlNet ZoeDepth Pipe (JPS)", + "CtrlNet ZoeDepth Settings (JPS)", + "Disable Enable Switch (JPS)", + "Enable Disable Switch (JPS)", + "Generation TXT IMG Settings (JPS)", + "Get Date Time String (JPS)", + "Get Image Size (JPS)", + "IP Adapter Settings (JPS)", + "IP Adapter Settings Pipe (JPS)", + "IP Adapter Tiled Settings (JPS)", + "IP Adapter Tiled Settings Pipe (JPS)", + "IPA Switch (JPS)", + "Image Prepare Pipe (JPS)", + "Image Prepare Settings (JPS)", + "Image Switch (JPS)", + "ImageToImage Pipe (JPS)", + "ImageToImage Settings (JPS)", + "Images Masks MultiPipe (JPS)", + "InstantID Mask Prepare Pipe (JPS)", + "InstantID Mask Prepare Settings (JPS)", + "InstantID Pipe (JPS)", + "InstantID Pose Prepare Pipe (JPS)", + "InstantID Pose Prepare Settings (JPS)", + "InstantID Settings (JPS)", + "InstantID Source Prepare Pipe (JPS)", + "InstantID Source Prepare Settings (JPS)", + "Integer Switch (JPS)", + "Largest Int (JPS)", + "Latent Switch (JPS)", + "Lora Loader (JPS)", + "Mask Switch (JPS)", + "Model Switch (JPS)", + "Multiply Float Float (JPS)", + "Multiply Int Float (JPS)", + "Multiply Int Int (JPS)", + "Prepare Image (JPS)", + "Prepare Image Plus (JPS)", + "Prepare Image Tiled IPA (JPS)", + "Resolution Multiply (JPS)", + "Revision Settings (JPS)", + "Revision Settings Pipe (JPS)", + "SDXL Basic Settings (JPS)", + "SDXL Basic Settings Pipe (JPS)", + "SDXL Fundamentals MultiPipe (JPS)", + "SDXL Prompt Handling (JPS)", + "SDXL Prompt Handling Plus (JPS)", + "SDXL Prompt Styler (JPS)", + "SDXL Recommended Resolution Calc (JPS)", + "SDXL Resolutions (JPS)", + "SDXL Settings (JPS)", + "SDXL Settings Pipe (JPS)", + "Sampler Scheduler Settings (JPS)", + "Save Images Plus (JPS)", + "Substract Int Int (JPS)", + "Text Concatenate (JPS)", + "Text Prompt (JPS)", + "Text Prompt Combo (JPS)", + "Time Seed (JPS)", + "VAE Switch (JPS)" + ], + { + "author": "JPS", + "description": "Various nodes to handle SDXL Resolutions, SDXL Basic Settings, IP Adapter Settings, Revision Settings, SDXL Prompt Styler, Crop Image to Square, Crop Image to Target Size, Get Date-Time String, Resolution Multiply, Largest Integer, 5-to-1 Switches for Integer, Images, Latents, Conditioning, Model, VAE, ControlNet", + "nickname": "JPS Custom Nodes", + "title": "JPS Custom Nodes for ComfyUI", + "title_aux": "JPS Custom Nodes for ComfyUI" + } + ], + "https://github.com/Jannchie/ComfyUI-J": [ + [ + "DiffusersCompelPromptEmbedding", + "DiffusersControlnetLoader", + "DiffusersControlnetUnit", + "DiffusersControlnetUnitStack", + "DiffusersDecoder", + "DiffusersGenerator", + "DiffusersPipeline", + "DiffusersPrepareLatents", + "DiffusersTextureInversionLoader", + "DiffusersXLPipeline", + "GetAverageColorFromImage", + "GetFilledColorImage" + ], + { + "title_aux": "ComfyUI-J" + } + ], + "https://github.com/JaredTherriault/ComfyUI-JNodes": [ + [ + "JNodes_AddOrSetMetaDataKey", + "JNodes_AnyToString", + "JNodes_AppendReversedFrames", + "JNodes_BooleanSelectorWithString", + "JNodes_BreakMediaInfo", + "JNodes_CheckpointSelectorWithString", + "JNodes_CreateStereoscopicImageFromDepth", + "JNodes_GetOutputDirectory", + "JNodes_GetParameterFromList", + "JNodes_GetParameterGlobal", + "JNodes_GetTempDirectory", + "JNodes_ImageFormatSelector", + "JNodes_ImageSizeSelector", + "JNodes_LoadVideo", + "JNodes_LoadVisualMediaFromPath", + "JNodes_LoraExtractor", + "JNodes_MediaInfoToString", + "JNodes_OutVideoInfo", + "JNodes_ParseDynamicPrompts", + "JNodes_ParseParametersToGlobalList", + "JNodes_ParseWildcards", + "JNodes_PromptBuilderSingleSubject", + "JNodes_RemoveCommentedText", + "JNodes_RemoveMetaDataKey", + "JNodes_RemoveParseableDataForInference", + "JNodes_SamplerSelectorWithString", + "JNodes_SaveImageWithOutput", + "JNodes_SaveVideo", + "JNodes_SchedulerSelectorWithString", + "JNodes_SearchAndReplace", + "JNodes_SearchAndReplaceFromFile", + "JNodes_SearchAndReplaceFromList", + "JNodes_SelectRandomFileFromDirectory", + "JNodes_SetNegativePromptInMetaData", + "JNodes_SetPositivePromptInMetaData", + "JNodes_SplitAndJoin", + "JNodes_StringLiteral", + "JNodes_SyncedStringLiteral", + "JNodes_TokenCounter", + "JNodes_TrimAndStrip", + "JNodes_UploadVideo", + "JNodes_UploadVisualMedia", + "JNodes_VaeSelectorWithString" + ], + { + "title_aux": "ComfyUI-JNodes" + } + ], + "https://github.com/JayLyu/ComfyUI_BaiKong_Node": [ + [ + "BK_ColorLimit", + "BK_ColorSelector", + "BK_GradientImage", + "BK_Img2Color" + ], + { + "title_aux": "ComfyUI_BaiKong_Node" + } + ], + "https://github.com/JcandZero/ComfyUI_GLM4Node": [ + [ + "GLM3_turbo_CHAT", + "GLM4_CHAT", + "GLM4_Vsion_IMGURL" + ], + { + "title_aux": "ComfyUI_GLM4Node" + } + ], + "https://github.com/Jcd1230/rembg-comfyui-node": [ + [ + "Image Remove Background (rembg)" + ], + { + "title_aux": "Rembg Background Removal Node for ComfyUI" + } + ], + "https://github.com/JerryOrbachJr/ComfyUI-RandomSize": [ + [ + "JOJR_RandomSize" + ], + { + "author": "JerryOrbachJr", + "description": "A ComfyUI custom node that randomly selects a height and width pair from a list in a config file", + "nickname": "Random Size", + "title": "Random Size", + "title_aux": "Random Size" + } + ], + "https://github.com/JettHu/ComfyUI-TCD": [ + [ + "TCDModelSamplingDiscrete" + ], + { + "title_aux": "ComfyUI-TCD" + } + ], + "https://github.com/JettHu/ComfyUI_TGate": [ + [ + "TGateApply", + "TGateApplyAdvanced", + "TGateApplySimple" + ], + { + "title_aux": "ComfyUI_TGate" + } + ], + "https://github.com/Jordach/comfy-plasma": [ + [ + "JDC_AutoContrast", + "JDC_BlendImages", + "JDC_BrownNoise", + "JDC_Contrast", + "JDC_EqualizeGrey", + "JDC_GaussianBlur", + "JDC_GreyNoise", + "JDC_Greyscale", + "JDC_ImageLoader", + "JDC_ImageLoaderMeta", + "JDC_PinkNoise", + "JDC_Plasma", + "JDC_PlasmaSampler", + "JDC_PowerImage", + "JDC_RandNoise", + "JDC_ResizeFactor" + ], + { + "title_aux": "comfy-plasma" + } + ], + "https://github.com/Kangkang625/ComfyUI-paint-by-example": [ + [ + "PaintbyExamplePipeLoader", + "PaintbyExampleSampler" + ], + { + "title_aux": "ComfyUI-Paint-by-Example" + } + ], + "https://github.com/KewkLW/ComfyUI-kewky_tools": [ + [ + "CLIPInterrogator", + "FormattedPromptNode", + "ImageBatcher", + "LoadImagePlus", + "LoadVideoPlus", + "TensorDebugPlus", + "TextAppendNode", + "TextSearchNode", + "VRAM_Debug_Plus" + ], + { + "title_aux": "ComfyUI-kewky_tools" + } + ], + "https://github.com/KoreTeknology/ComfyUI-Universal-Styler": [ + [ + "Load Nai Styles Complex CSV", + "ShowText|pysssss", + "Universal_Styler_Node", + "concat" + ], + { + "title_aux": "ComfyUI Universal Styler" + } + ], + "https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet": [ + [ + "ACN_AdvancedControlNetApply", + "ACN_ControlNetLoaderWithLoraAdvanced", + "ACN_DefaultUniversalWeights", + "ACN_ReferenceControlNet", + "ACN_ReferenceControlNetFinetune", + "ACN_ReferencePreprocessor", + "ACN_SparseCtrlIndexMethodNode", + "ACN_SparseCtrlLoaderAdvanced", + "ACN_SparseCtrlMergedLoaderAdvanced", + "ACN_SparseCtrlRGBPreprocessor", + "ACN_SparseCtrlSpreadMethodNode", + "ACN_SparseCtrlWeightExtras", + "ACN_TimestepKeyframeFromStrengthList", + "ACN_TimestepKeyframeInterpolation", + "ControlNetLoaderAdvanced", + "CustomControlNetWeights", + "CustomT2IAdapterWeights", + "DiffControlNetLoaderAdvanced", + "LatentKeyframe", + "LatentKeyframeBatchedGroup", + "LatentKeyframeGroup", + "LatentKeyframeTiming", + "LoadImagesFromDirectory", + "ScaledSoftControlNetWeights", + "ScaledSoftMaskedUniversalWeights", + "SoftControlNetWeights", + "SoftT2IAdapterWeights", + "TimestepKeyframe" + ], + { + "title_aux": "ComfyUI-Advanced-ControlNet" + } + ], + "https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved": [ + [ + "ADE_AdjustPEFullStretch", + "ADE_AdjustPEManual", + "ADE_AdjustPESweetspotStretch", + "ADE_AdjustWeightAllAdd", + "ADE_AdjustWeightAllMult", + "ADE_AdjustWeightIndivAdd", + "ADE_AdjustWeightIndivAttnAdd", + "ADE_AdjustWeightIndivAttnMult", + "ADE_AdjustWeightIndivMult", + "ADE_AnimateDiffCombine", + "ADE_AnimateDiffKeyframe", + "ADE_AnimateDiffLoRALoader", + "ADE_AnimateDiffLoaderGen1", + "ADE_AnimateDiffLoaderV1Advanced", + "ADE_AnimateDiffLoaderWithContext", + "ADE_AnimateDiffModelSettings", + "ADE_AnimateDiffModelSettingsAdvancedAttnStrengths", + "ADE_AnimateDiffModelSettingsSimple", + "ADE_AnimateDiffModelSettings_Release", + "ADE_AnimateDiffSamplingSettings", + "ADE_AnimateDiffSettings", + "ADE_AnimateDiffUniformContextOptions", + "ADE_AnimateDiffUnload", + "ADE_ApplyAnimateDiffModel", + "ADE_ApplyAnimateDiffModelSimple", + "ADE_ApplyAnimateDiffModelWithCameraCtrl", + "ADE_ApplyAnimateDiffModelWithPIA", + "ADE_ApplyAnimateLCMI2VModel", + "ADE_AttachLoraHookToCLIP", + "ADE_AttachLoraHookToConditioning", + "ADE_BatchedContextOptions", + "ADE_CameraCtrlAnimateDiffKeyframe", + "ADE_CameraManualPoseAppend", + "ADE_CameraPoseAdvanced", + "ADE_CameraPoseBasic", + "ADE_CameraPoseCombo", + "ADE_CombineLoraHooks", + "ADE_CombineLoraHooksEight", + "ADE_CombineLoraHooksFour", + "ADE_ConditioningSetMask", + "ADE_ConditioningSetMaskAndCombine", + "ADE_ConditioningSetUnmaskedAndCombine", + "ADE_CustomCFG", + "ADE_CustomCFGKeyframe", + "ADE_EmptyLatentImageLarge", + "ADE_InjectI2VIntoAnimateDiffModel", + "ADE_InjectPIAIntoAnimateDiffModel", + "ADE_InputPIA_Multival", + "ADE_InputPIA_PaperPresets", + "ADE_IterationOptsDefault", + "ADE_IterationOptsFreeInit", + "ADE_LoadAnimateDiffModel", + "ADE_LoadAnimateDiffModelWithCameraCtrl", + "ADE_LoadAnimateLCMI2VModel", + "ADE_LoadCameraPoses", + "ADE_LoopedUniformContextOptions", + "ADE_LoopedUniformViewOptions", + "ADE_LoraHookKeyframe", + "ADE_LoraHookKeyframeFromStrengthList", + "ADE_LoraHookKeyframeInterpolation", + "ADE_MultivalConvertToMask", + "ADE_MultivalDynamic", + "ADE_MultivalDynamicFloatInput", + "ADE_MultivalScaledMask", + "ADE_NoiseLayerAdd", + "ADE_NoiseLayerAddWeighted", + "ADE_NoiseLayerReplace", + "ADE_NoisedImageInjectOptions", + "ADE_NoisedImageInjection", + "ADE_PIA_AnimateDiffKeyframe", + "ADE_PairedConditioningSetMask", + "ADE_PairedConditioningSetMaskAndCombine", + "ADE_PairedConditioningSetUnmaskedAndCombine", + "ADE_RawSigmaSchedule", + "ADE_RegisterLoraHook", + "ADE_RegisterLoraHookModelOnly", + "ADE_RegisterModelAsLoraHook", + "ADE_RegisterModelAsLoraHookModelOnly", + "ADE_ReplaceCameraParameters", + "ADE_ReplaceOriginalPoseAspectRatio", + "ADE_SetLoraHookKeyframe", + "ADE_SigmaSchedule", + "ADE_SigmaScheduleSplitAndCombine", + "ADE_SigmaScheduleWeightedAverage", + "ADE_SigmaScheduleWeightedAverageInterp", + "ADE_StandardStaticContextOptions", + "ADE_StandardStaticViewOptions", + "ADE_StandardUniformContextOptions", + "ADE_StandardUniformViewOptions", + "ADE_TimestepsConditioning", + "ADE_UpscaleAndVAEEncode", + "ADE_UseEvolvedSampling", + "ADE_ViewsOnlyContextOptions", + "AnimateDiffLoaderV1", + "CheckpointLoaderSimpleWithNoiseSelect" + ], + { + "title_aux": "AnimateDiff Evolved" + } + ], + "https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite": [ + [ + "VHS_AudioToVHSAudio", + "VHS_BatchManager", + "VHS_DuplicateImages", + "VHS_DuplicateLatents", + "VHS_DuplicateMasks", + "VHS_GetImageCount", + "VHS_GetLatentCount", + "VHS_GetMaskCount", + "VHS_LoadAudio", + "VHS_LoadAudioUpload", + "VHS_LoadImages", + "VHS_LoadImagesPath", + "VHS_LoadVideo", + "VHS_LoadVideoPath", + "VHS_MergeImages", + "VHS_MergeLatents", + "VHS_MergeMasks", + "VHS_PruneOutputs", + "VHS_SelectEveryNthImage", + "VHS_SelectEveryNthLatent", + "VHS_SelectEveryNthMask", + "VHS_SplitImages", + "VHS_SplitLatents", + "VHS_SplitMasks", + "VHS_VAEDecodeBatched", + "VHS_VAEEncodeBatched", + "VHS_VHSAudioToAudio", + "VHS_VideoCombine", + "VHS_VideoInfo", + "VHS_VideoInfoLoaded", + "VHS_VideoInfoSource" + ], + { + "title_aux": "ComfyUI-VideoHelperSuite" + } + ], + "https://github.com/KytraScript/ComfyUI_KytraWebhookHTTP": [ + [ + "SendToDiscordWebhook" + ], + { + "title_aux": "ComfyUI_KytraWebhookHTTP" + } + ], + "https://github.com/LEv145/images-grid-comfy-plugin": [ + [ + "GridAnnotation", + "ImageCombine", + "ImagesGridByColumns", + "ImagesGridByRows", + "LatentCombine" + ], + { + "title_aux": "ImagesGrid" + } + ], + "https://github.com/LarryJane491/Image-Captioning-in-ComfyUI": [ + [ + "LoRA Caption Load", + "LoRA Caption Save" + ], + { + "title_aux": "Image-Captioning-in-ComfyUI" + } + ], + "https://github.com/LarryJane491/Lora-Training-in-Comfy": [ + [ + "Lora Training in Comfy (Advanced)", + "Lora Training in ComfyUI", + "Tensorboard Access" + ], + { + "title_aux": "Lora-Training-in-Comfy" + } + ], + "https://github.com/Layer-norm/comfyui-lama-remover": [ + [ + "LamaRemover", + "LamaRemoverIMG" + ], + { + "title_aux": "Comfyui lama remover" + } + ], + "https://github.com/Lerc/canvas_tab": [ + [ + "Canvas_Tab", + "Send_To_Editor" + ], + { + "author": "Lerc", + "description": "This extension provides a full page image editor with mask support. There are two nodes, one to receive images from the editor and one to send images to the editor.", + "nickname": "Canvas Tab", + "title": "Canvas Tab", + "title_aux": "Canvas Tab" + } + ], + "https://github.com/Limitex/ComfyUI-Calculation": [ + [ + "CenterCalculation", + "CreateQRCode" + ], + { + "title_aux": "ComfyUI-Calculation" + } + ], + "https://github.com/Limitex/ComfyUI-Diffusers": [ + [ + "CreateIntListNode", + "DiffusersClipTextEncode", + "DiffusersModelMakeup", + "DiffusersPipelineLoader", + "DiffusersSampler", + "DiffusersSchedulerLoader", + "DiffusersVaeLoader", + "LcmLoraLoader", + "StreamDiffusionCreateStream", + "StreamDiffusionFastSampler", + "StreamDiffusionSampler", + "StreamDiffusionWarmup" + ], + { + "title_aux": "ComfyUI-Diffusers" + } + ], + "https://github.com/Loewen-Hob/rembg-comfyui-node-better": [ + [ + "Image Remove Background (rembg)" + ], + { + "title_aux": "Rembg Background Removal Node for ComfyUI (Better)" + } + ], + "https://github.com/LonicaMewinsky/ComfyUI-MakeFrame": [ + [ + "BreakFrames", + "BreakGrid", + "GetKeyFrames", + "MakeGrid", + "RandomImageFromDir" + ], + { + "title_aux": "ComfyBreakAnim" + } + ], + "https://github.com/LonicaMewinsky/ComfyUI-RawSaver": [ + [ + "SaveTifImage" + ], + { + "title_aux": "ComfyUI-RawSaver" + } + ], + "https://github.com/Ludobico/ComfyUI-ScenarioPrompt": [ + [ + "ScenarioPrompt" + ], + { + "title_aux": "ComfyUI-ScenarioPrompt" + } + ], + "https://github.com/LyazS/comfyui-anime-seg": [ + [ + "Anime Character Seg" + ], + { + "title_aux": "Anime Character Segmentation node for comfyui" + } + ], + "https://github.com/M1kep/ComfyLiterals": [ + [ + "Checkpoint", + "Float", + "Int", + "KepStringLiteral", + "Lora", + "Operation", + "String" + ], + { + "title_aux": "ComfyLiterals" + } + ], + "https://github.com/M1kep/ComfyUI-KepOpenAI": [ + [ + "KepOpenAI_ImageWithPrompt" + ], + { + "title_aux": "ComfyUI-KepOpenAI" + } + ], + "https://github.com/M1kep/ComfyUI-OtherVAEs": [ + [ + "OtherVAE_Taesd" + ], + { + "title_aux": "ComfyUI-OtherVAEs" + } + ], + "https://github.com/M1kep/Comfy_KepKitchenSink": [ + [ + "KepRotateImage" + ], + { + "title_aux": "Comfy_KepKitchenSink" + } + ], + "https://github.com/M1kep/Comfy_KepListStuff": [ + [ + "Empty Images", + "Image Overlay", + "ImageListLoader", + "Join Float Lists", + "Join Image Lists", + "KepStringList", + "KepStringListFromNewline", + "Kep_JoinListAny", + "Kep_RepeatList", + "Kep_ReverseList", + "Kep_VariableImageBuilder", + "List Length", + "Range(Num Steps) - Float", + "Range(Num Steps) - Int", + "Range(Step) - Float", + "Range(Step) - Int", + "Stack Images", + "XYAny", + "XYImage" + ], + { + "title_aux": "Comfy_KepListStuff" + } + ], + "https://github.com/M1kep/Comfy_KepMatteAnything": [ + [ + "MatteAnything_DinoBoxes", + "MatteAnything_GenerateVITMatte", + "MatteAnything_InitSamPredictor", + "MatteAnything_LoadDINO", + "MatteAnything_LoadVITMatteModel", + "MatteAnything_SAMLoader", + "MatteAnything_SAMMaskFromBoxes", + "MatteAnything_ToTrimap" + ], + { + "title_aux": "Comfy_KepMatteAnything" + } + ], + "https://github.com/M1kep/KepPromptLang": [ + [ + "Build Gif", + "Special CLIP Loader" + ], + { + "title_aux": "KepPromptLang" + } + ], + "https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes": [ + [ + "\u26d4 Generate Negative Prompt", + "\u2728 Groq LLM API", + "\ud83d\udcbe Save Text File With Path", + "\ud83d\uddbc\ufe0f Download Image from URL" + ], + { + "title_aux": "ComfyUI-mnemic-nodes" + } + ], + "https://github.com/Makeezi/ComfyUI-promptLAB": [ + [ + "PromptLAB" + ], + { + "title_aux": "ComfyUI-promptLAB" + } + ], + "https://github.com/Mamaaaamooooo/batchImg-rembg-ComfyUI-nodes": [ + [ + "Image Remove Background (rembg)" + ], + { + "title_aux": "Batch Rembg for ComfyUI" + } + ], + "https://github.com/ManglerFTW/ComfyI2I": [ + [ + "Color Transfer", + "Combine and Paste", + "Inpaint Segments", + "Mask Ops" + ], + { + "author": "ManglerFTW", + "title": "ComfyI2I", + "title_aux": "ComfyI2I" + } + ], + "https://github.com/MaraScott/ComfyUI_MaraScott_Nodes": [ + [ + "MaraScottAnyBusNode", + "MaraScottAnyBus_v2", + "MaraScottDisplayInfoNode", + "MaraScottDisplayInfo_v1", + "MaraScottPasteInpaintingByMask_v1", + "MaraScottPromptFromImage_v1", + "MaraScottSetInpaintingByMask_v1", + "MaraScottUpscalerRefinerNode_v2", + "MaraScottUpscalerRefinerNode_v3", + "MaraScott_Kijai_TokenCounter_v1", + "McBoaty_Refiner_v4", + "McBoaty_TilePrompter_v4", + "McBoaty_Upscaler_v4" + ], + { + "title_aux": "\ud83d\udc30 MaraScott Nodes" + } + ], + "https://github.com/MarcusNyne/m9-prompts-comfyui": [ + [ + "ScramblePrompts_m9", + "TweakWeights_m9" + ], + { + "title_aux": "m9-prompts-comfyui" + } + ], + "https://github.com/MariusKM/ComfyUI-BadmanNodes": [ + [ + "BadmanCLIPTextEncodeSDXLRegion", + "BadmanIO", + "BadmanIntUtil", + "BadmanStringSelect", + "Badman_Blend", + "Badman_Concat_String", + "Badman_HexGenerator", + "Badman_Print", + "Badman_String" + ], + { + "title_aux": "ComfyUI-BadmanNodes" + } + ], + "https://github.com/MarkoCa1/ComfyUI-Text": [ + [ + "CombinationText", + "PlaceholderText", + "ReplaceText", + "ShowText" + ], + { + "title_aux": "ComfyUI-Text" + } + ], + "https://github.com/MarkoCa1/ComfyUI_Segment_Mask": [ + [ + "AutomaticMask(segment anything)" + ], + { + "title_aux": "ComfyUI_Segment_Mask" + } + ], + "https://github.com/Mason-McGough/ComfyUI-Mosaica": [ + [ + "ApplyLUTToLabelImage", + "KMeans", + "LoadLUTFromMatplotlib", + "MeanShift", + "RandomLUT", + "Watershed" + ], + { + "title_aux": "Mosaica" + } + ], + "https://github.com/MilitantHitchhiker/MilitantHitchhiker-SwitchbladePack": [ + [ + "IntegratedRandomPromptGenerator", + "TextAppender" + ], + { + "author": "Militant Hitchhiker", + "description": "Militant Hitchhiker's multi-function nodes.", + "nickname": "Switchblade", + "title": "Switchblade Pack", + "title_aux": "Militant Hitchhiker's Switchblade Pack" + } + ], + "https://github.com/Miosp/ComfyUI-FBCNN": [ + [ + "JPEG artifacts removal FBCNN" + ], + { + "title_aux": "ComfyUI-FBCNN" + } + ], + "https://github.com/MitoshiroPJ/comfyui_slothful_attention": [ + [ + "NearSightedAttention", + "NearSightedAttentionSimple", + "NearSightedTile", + "SlothfulAttention" + ], + { + "title_aux": "ComfyUI Slothful Attention" + } + ], + "https://github.com/MokkaBoss1/ComfyUI_Mokkaboss1": [ + [ + "AnimeCosplayDir", + "AspectRatioCondition", + "ChooseImage", + "Colors", + "CombinedCrop", + "ConnectFloat", + "ConnectImage", + "ConnectInteger", + "ConnectLatent", + "ConnectString", + "DirSelector", + "DoubleClipTextEncode", + "EmbeddingLoader", + "FilmCharDir", + "FuseImages", + "FuseImages2", + "HashText", + "HueSatLum", + "HueShift", + "ImageDimensions", + "ImageDimensionsBatch", + "ImageOverlayResized", + "ImageResizeLong", + "ImageZigzag", + "IndoorBackgrounds", + "IndoorDir", + "IntEvaluate", + "IntFloatDict", + "IntStringDict", + "JsonSearch", + "KillWorkflow", + "LandscapeBackgrounds", + "LandscapeDir", + "MakeupStylesDir", + "Mbsampler", + "OptimalCrop", + "Overlay", + "PhotomontageA", + "PhotomontageB", + "PhotomontageC", + "PostSamplerCrop", + "PresetLoad", + "PresetRemove", + "PresetSave", + "PromptSwitcher", + "RandomString", + "SDXLEmptyLatent", + "SavePrompt", + "SaveWithMetaData", + "SaveWithMetaData2", + "SearchReplace", + "SimplePrompts", + "SpecificStylesDir", + "SplitImages", + "StringJoin", + "TimeStamp", + "TintnShift", + "TricolorComposition", + "WorkflowSettings", + "WrapText", + "X_In_a_Dress", + "X_In_a_Suit", + "X_In_a_Suit)", + "ZoomCrop", + "imageborder" + ], + { + "title_aux": "Node Pack mostly for manipulating strings and integers" + } + ], + "https://github.com/MrForExample/ComfyUI-3D-Pack": [ + [], + { + "nodename_pattern": "^\\[Comfy3D\\]", + "title_aux": "ComfyUI-3D-Pack" + } + ], + "https://github.com/MrForExample/ComfyUI-AnimateAnyone-Evolved": [ + [], + { + "nodename_pattern": "^\\[AnimateAnyone\\]", + "title_aux": "ComfyUI-AnimateAnyone-Evolved" + } + ], + "https://github.com/MrSamSeen/ComfyUI_SSStereoscope": [ + [ + "SBS_by_SamSeen" + ], + { + "title_aux": "ComfyUI_SSStereoscope" + } + ], + "https://github.com/Munkyfoot/ComfyUI-TextOverlay": [ + [ + "Text Overlay" + ], + { + "title_aux": "ComfyUI-TextOverlay" + } + ], + "https://github.com/NeuralSamurAI/Comfyui-Superprompt-Unofficial": [ + [ + "SuperPrompterNode" + ], + { + "title_aux": "SuperPrompter Node for ComfyUI" + } + ], + "https://github.com/NicholasMcCarthy/ComfyUI_TravelSuite": [ + [ + "LatentTravel" + ], + { + "title_aux": "ComfyUI_TravelSuite" + } + ], + "https://github.com/NimaNzrii/comfyui-photoshop": [ + [ + "\ud83d\udd39 Photoshop RemoteConnection", + "\ud83d\udd39Photoshop ComfyUI Plugin", + "\ud83d\udd39SendTo Photoshop Plugin" + ], + { + "title_aux": "comfyui-photoshop" + } + ], + "https://github.com/NimaNzrii/comfyui-popup_preview": [ + [ + "PreviewPopup" + ], + { + "title_aux": "comfyui-popup_preview" + } + ], + "https://github.com/Niutonian/ComfyUi-NoodleWebcam": [ + [ + "WebcamNode" + ], + { + "title_aux": "ComfyUi-NoodleWebcam" + } + ], + "https://github.com/Nlar/ComfyUI_CartoonSegmentation": [ + [ + "AnimeSegmentation", + "KenBurnsConfigLoader", + "KenBurns_Processor", + "LoadImageFilename" + ], + { + "author": "Nels Larsen", + "description": "This extension offers a front end to the Cartoon Segmentation Project (https://github.com/CartoonSegmentation/CartoonSegmentation)", + "nickname": "CfyCS", + "title": "ComfyUI_CartoonSegmentation", + "title_aux": "ComfyUI_CartoonSegmentation" + } + ], + "https://github.com/NotHarroweD/Harronode": [ + [ + "Harronode" + ], + { + "author": "HarroweD and quadmoon (https://github.com/traugdor)", + "description": "This extension to ComfyUI will build a prompt for the Harrlogos LoRA for SDXL.", + "nickname": "Harronode", + "nodename_pattern": "Harronode", + "title": "Harrlogos Prompt Builder Node", + "title_aux": "Harrlogos Prompt Builder Node" + } + ], + "https://github.com/Nourepide/ComfyUI-Allor": [ + [ + "AlphaChanelAdd", + "AlphaChanelAddByMask", + "AlphaChanelAsMask", + "AlphaChanelRemove", + "AlphaChanelRestore", + "ClipClamp", + "ClipVisionClamp", + "ClipVisionOutputClamp", + "ConditioningClamp", + "ControlNetClamp", + "GligenClamp", + "ImageBatchCopy", + "ImageBatchFork", + "ImageBatchGet", + "ImageBatchJoin", + "ImageBatchPermute", + "ImageBatchRemove", + "ImageClamp", + "ImageCompositeAbsolute", + "ImageCompositeAbsoluteByContainer", + "ImageCompositeRelative", + "ImageCompositeRelativeByContainer", + "ImageContainer", + "ImageContainerInheritanceAdd", + "ImageContainerInheritanceMax", + "ImageContainerInheritanceScale", + "ImageContainerInheritanceSum", + "ImageDrawArc", + "ImageDrawArcByContainer", + "ImageDrawChord", + "ImageDrawChordByContainer", + "ImageDrawEllipse", + "ImageDrawEllipseByContainer", + "ImageDrawLine", + "ImageDrawLineByContainer", + "ImageDrawPieslice", + "ImageDrawPiesliceByContainer", + "ImageDrawPolygon", + "ImageDrawRectangle", + "ImageDrawRectangleByContainer", + "ImageDrawRectangleRounded", + "ImageDrawRectangleRoundedByContainer", + "ImageEffectsAdjustment", + "ImageEffectsGrayscale", + "ImageEffectsLensBokeh", + "ImageEffectsLensChromaticAberration", + "ImageEffectsLensOpticAxis", + "ImageEffectsLensVignette", + "ImageEffectsLensZoomBurst", + "ImageEffectsNegative", + "ImageEffectsSepia", + "ImageFilterBilateralBlur", + "ImageFilterBlur", + "ImageFilterBoxBlur", + "ImageFilterContour", + "ImageFilterDetail", + "ImageFilterEdgeEnhance", + "ImageFilterEdgeEnhanceMore", + "ImageFilterEmboss", + "ImageFilterFindEdges", + "ImageFilterGaussianBlur", + "ImageFilterGaussianBlurAdvanced", + "ImageFilterMax", + "ImageFilterMedianBlur", + "ImageFilterMin", + "ImageFilterMode", + "ImageFilterRank", + "ImageFilterSharpen", + "ImageFilterSmooth", + "ImageFilterSmoothMore", + "ImageFilterStackBlur", + "ImageNoiseBeta", + "ImageNoiseBinomial", + "ImageNoiseBytes", + "ImageNoiseGaussian", + "ImageSegmentation", + "ImageSegmentationCustom", + "ImageSegmentationCustomAdvanced", + "ImageText", + "ImageTextMultiline", + "ImageTextMultilineOutlined", + "ImageTextOutlined", + "ImageTransformCropAbsolute", + "ImageTransformCropCorners", + "ImageTransformCropRelative", + "ImageTransformPaddingAbsolute", + "ImageTransformPaddingRelative", + "ImageTransformResizeAbsolute", + "ImageTransformResizeClip", + "ImageTransformResizeRelative", + "ImageTransformRotate", + "ImageTransformTranspose", + "LatentClamp", + "MaskClamp", + "ModelClamp", + "StyleModelClamp", + "UpscaleModelClamp", + "VaeClamp" + ], + { + "title_aux": "Allor Plugin" + } + ], + "https://github.com/Nuked88/ComfyUI-N-Nodes": [ + [ + "CLIPTextEncodeAdvancedNSuite [n-suite]", + "DynamicPrompt [n-suite]", + "Float Variable [n-suite]", + "FrameInterpolator [n-suite]", + "GPT Loader Simple [n-suite]", + "GPT Sampler [n-suite]", + "ImagePadForOutpaintAdvanced [n-suite]", + "Integer Variable [n-suite]", + "Llava Clip Loader [n-suite]", + "LoadFramesFromFolder [n-suite]", + "LoadImageFromFolder [n-suite]", + "LoadVideo [n-suite]", + "SaveVideo [n-suite]", + "SetMetadataForSaveVideo [n-suite]", + "String Variable [n-suite]" + ], + { + "title_aux": "ComfyUI-N-Nodes" + } + ], + "https://github.com/Off-Live/ComfyUI-off-suite": [ + [ + "Apply CLAHE", + "Cached Image Load From URL", + "CalcMaskBound", + "Crop Center wigh SEGS", + "Crop Center with SEGS", + "Dilate Mask for Each Face", + "GW Number Formatting", + "Grid Image from batch (OFF)", + "Image Crop Fit", + "Image Resize Fit", + "OFF SEGS to Image", + "Paste Face Segment to Image", + "Query Gender and Age", + "RandomSeedfromList", + "SEGS to Face Crop Data", + "Safe Mask to Image", + "VAE Encode For Inpaint V2", + "Watermarking" + ], + { + "title_aux": "ComfyUI-off-suite" + } + ], + "https://github.com/Onierous/QRNG_Node_ComfyUI/raw/main/qrng_node.py": [ + [ + "QRNG_Node_CSV" + ], + { + "title_aux": "QRNG_Node_ComfyUI" + } + ], + "https://github.com/PCMonsterx/ComfyUI-CSV-Loader": [ + [ + "Load Artists CSV", + "Load Artmovements CSV", + "Load Characters CSV", + "Load Colors CSV", + "Load Composition CSV", + "Load Lighting CSV", + "Load Negative CSV", + "Load Positive CSV", + "Load Settings CSV", + "Load Styles CSV" + ], + { + "title_aux": "ComfyUI-CSV-Loader" + } + ], + "https://github.com/ParisNeo/lollms_nodes_suite": [ + [ + "Artbot", + "Lollms_Text_Gen", + "Lollms_Text_Saver", + "RandomizeVideo" + ], + { + "title_aux": "lollms_nodes_suite" + } + ], + "https://github.com/ParmanBabra/ComfyUI-Malefish-Custom-Scripts": [ + [ + "CSVPromptsLoader", + "CombinePrompt", + "MultiLoraLoader", + "RandomPrompt" + ], + { + "title_aux": "ComfyUI-Malefish-Custom-Scripts" + } + ], + "https://github.com/Pfaeff/pfaeff-comfyui": [ + [ + "AstropulsePixelDetector", + "BackgroundRemover", + "ImagePadForBetterOutpaint", + "Inpainting", + "InpaintingPipelineLoader" + ], + { + "title_aux": "pfaeff-comfyui" + } + ], + "https://github.com/PnthrLeo/comfyUI-image-search": [ + [ + "CloseImagesSearcher" + ], + { + "title_aux": "comfyUI-image-search" + } + ], + "https://github.com/Pos13/comfyui-cyclist": [ + [ + "CyclistCompare", + "CyclistMathFloat", + "CyclistMathInt", + "CyclistTimer", + "CyclistTimerStop", + "CyclistTypeCast", + "Interrupt", + "LoopManager", + "MemorizeConditioning", + "MemorizeFloat", + "MemorizeInt", + "MemorizeString", + "OverrideImage", + "OverrideLatent", + "OverrideModel", + "RecallConditioning", + "RecallFloat", + "RecallInt", + "RecallString", + "ReloadImage", + "ReloadLatent", + "ReloadModel" + ], + { + "author": "Pos13", + "description": "This extension provides tools to iterate generation results between runs. In general, it's for cycles.", + "nickname": "comfyui-cyclist", + "title": "Cyclist", + "title_aux": "Cyclist" + } + ], + "https://github.com/QaisMalkawi/ComfyUI-QaisHelper": [ + [ + "Bool Binary Operation", + "Bool Unary Operation", + "Item Debugger", + "Item Switch", + "Nearest SDXL Resolution", + "SDXL Resolution", + "Size Swapper" + ], + { + "title_aux": "ComfyUI-Qais-Helper" + } + ], + "https://github.com/RedRayz/ComfyUI-Danbooru-To-WD": [ + [ + "DanbooruToWD" + ], + { + "title_aux": "ComfyUI-Danbooru-To-WD" + } + ], + "https://github.com/RenderRift/ComfyUI-RenderRiftNodes": [ + [ + "AnalyseMetadata", + "DateIntegerNode", + "DisplayMetaOptions", + "LoadImageWithMeta", + "MetadataOverlayNode", + "VideoPathMetaExtraction" + ], + { + "title_aux": "ComfyUI-RenderRiftNodes" + } + ], + "https://github.com/RomanKuschanow/ComfyUI-Advanced-Latent-Control": [ + [ + "LatentAddTransform", + "LatentInterpolateTransform", + "LatentMirror", + "LatentNormalize", + "LatentShift", + "MirrorTransform", + "MultiplyTransform", + "OffsetCombine", + "OneTimeLatentAddTransform", + "OneTimeLatentInterpolateTransform", + "OneTimeMirrorTransform", + "OneTimeMultiplyTransform", + "OneTimeShiftTransform", + "ShiftTransform", + "TransformHijack", + "TransformOffset", + "TransformSampler", + "TransformSamplerAdvanced", + "TransformsCombine" + ], + { + "title_aux": "Advanced Latent Control" + } + ], + "https://github.com/Ron-Digital/ComfyUI-SceneGenerator": [ + [ + "Scene Generator" + ], + { + "title_aux": "ComfyUI-SceneGenerator" + } + ], + "https://github.com/Ryuukeisyou/comfyui_face_parsing": [ + [ + "BBoxListItemSelect(FaceParsing)", + "BBoxResize(FaceParsing)", + "ColorAdjust(FaceParsing)", + "FaceBBoxDetect(FaceParsing)", + "FaceBBoxDetectorLoader(FaceParsing)", + "FaceParse(FaceParsing)", + "FaceParsingModelLoader(FaceParsing)", + "FaceParsingProcessorLoader(FaceParsing)", + "FaceParsingResultsParser(FaceParsing)", + "GuidedFilter(FaceParsing)", + "ImageCropWithBBox(FaceParsing)", + "ImageInsertWithBBox(FaceParsing)", + "ImageListSelect(FaceParsing)", + "ImagePadWithBBox(FaceParsing)", + "ImageResizeCalculator(FaceParsing)", + "ImageResizeWithBBox(FaceParsing)", + "ImageSize(FaceParsing)", + "LatentCropWithBBox(FaceParsing)", + "LatentInsertWithBBox(FaceParsing)", + "LatentSize(FaceParsing)", + "MaskComposite(FaceParsing)", + "MaskInsertWithBBox(FaceParsing)", + "MaskListComposite(FaceParsing)", + "MaskListSelect(FaceParsing)", + "MaskToBBox(FaceParsing)", + "SkinDetectTraditional(FaceParsing)" + ], + { + "title_aux": "comfyui_face_parsing" + } + ], + "https://github.com/Ryuukeisyou/comfyui_io_helpers": [ + [ + "ImageLoadAsMaskByPath(IOHelpers)", + "ImageLoadByPath(IOHelpers)", + "ImageLoadFromBase64(IOHelpers)", + "ImageSaveAsBase64(IOHelpers)", + "ImageSaveToPath(IOHelpers)", + "TypeConversion(IOHelpers)" + ], + { + "title_aux": "comfyui_io_helpers" + } + ], + "https://github.com/SEkINVR/ComfyUI-SaveAs": [ + [ + "ComfyUISaveAs" + ], + { + "title_aux": "ComfyUI SaveAS" + } + ], + "https://github.com/SLAPaper/ComfyUI-Image-Selector": [ + [ + "ImageDuplicator", + "ImageSelector", + "LatentDuplicator", + "LatentSelector" + ], + { + "title_aux": "ComfyUI-Image-Selector" + } + ], + "https://github.com/SOELexicon/ComfyUI-LexMSDBNodes": [ + [ + "MSSqlSelectNode", + "MSSqlTableNode" + ], + { + "title_aux": "LexMSDBNodes" + } + ], + "https://github.com/SOELexicon/ComfyUI-LexTools": [ + [ + "AesthetlcScoreSorter", + "AgeClassifierNode", + "ArtOrHumanClassifierNode", + "CalculateAestheticScore", + "DocumentClassificationNode", + "FoodCategoryClassifierNode", + "ImageAspectPadNode", + "ImageCaptioning", + "ImageFilterByFloatScoreNode", + "ImageFilterByIntScoreNode", + "ImageQualityScoreNode", + "ImageRankingNode", + "ImageScaleToMin", + "LoadAesteticModel", + "MD5ImageHashNode", + "SamplerPropertiesNode", + "ScoreConverterNode", + "SeedIncrementerNode", + "SegformerNode", + "SegformerNodeMasks", + "SegformerNodeMergeSegments", + "StepCfgIncrementNode" + ], + { + "title_aux": "ComfyUI-LexTools" + } + ], + "https://github.com/SadaleNet/CLIPTextEncodeA1111-ComfyUI/raw/master/custom_nodes/clip_text_encoder_a1111.py": [ + [ + "CLIPTextEncodeA1111", + "RerouteTextForCLIPTextEncodeA1111" + ], + { + "preemptions": [ + "SAMLoader" + ], + "title_aux": "ComfyUI A1111-like Prompt Custom Node Solution" + } + ], + "https://github.com/SamKhoze/ComfyUI-DeepFuze": [ + [ + "DeepFuze Save", + "DeepFuzeAdavance", + "DeepFuzeFaceSwap", + "DeepfuzePreview", + "LLM_node", + "PlayBackAudio", + "TTS_generation" + ], + { + "title_aux": "DeepFuze" + } + ], + "https://github.com/SayanoAI/Comfy-RVC": [ + [ + "AudioBatchValueNode", + "AudioTranscriptionNode", + "DownloadAudio", + "ImageRepeatInterleavedNode", + "LatentRepeatInterleavedNode", + "LoadAudio", + "LoadHubertModel", + "LoadPitchExtractionParams", + "LoadRVCModelNode", + "LoadWhisperModelNode", + "MergeAudioNode", + "MergeImageBatches", + "MergeLatentBatches", + "PreviewAudio", + "RVCNode", + "UVR5Node" + ], + { + "title_aux": "Comfy-RVC" + } + ], + "https://github.com/Scholar01/ComfyUI-Keyframe": [ + [ + "KeyframeApply", + "KeyframeInterpolationPart", + "KeyframePart" + ], + { + "title_aux": "SComfyUI-Keyframe" + } + ], + "https://github.com/Scorpinaus/ComfyUI-DiffusersLoader": [ + [ + "CombinedDiffusersLoader", + "DiffusersClipLoader", + "DiffusersUNETLoader", + "DiffusersVAELoader" + ], + { + "title_aux": "Loaders for Diffusers-format checkpoints" + } + ], + "https://github.com/ScreamingHawk/comfyui-ollama-prompt-encode": [ + [ + "OllamaCLIPTextEncode", + "OllamaPromptGenerator" + ], + { + "author": "Michael Standen", + "description": "Use AI to generate prompts and perform CLIP text encoding", + "nickname": "Ollama Prompt Encode", + "title": "Ollama Prompt Encode", + "title_aux": "Ollama Prompt Encode" + } + ], + "https://github.com/SeaArtLab/ComfyUI-Long-CLIP": [ + [ + "SeaArtLongClip", + "SeaArtLongXLClipMerge" + ], + { + "title_aux": "ComfyUI-Long-CLIP" + } + ], + "https://github.com/SeargeDP/SeargeSDXL": [ + [ + "SeargeAdvancedParameters", + "SeargeCheckpointLoader", + "SeargeConditionMixing", + "SeargeConditioningMuxer2", + "SeargeConditioningMuxer5", + "SeargeConditioningParameters", + "SeargeControlnetAdapterV2", + "SeargeControlnetModels", + "SeargeCustomAfterUpscaling", + "SeargeCustomAfterVaeDecode", + "SeargeCustomPromptMode", + "SeargeDebugPrinter", + "SeargeEnablerInputs", + "SeargeFloatConstant", + "SeargeFloatMath", + "SeargeFloatPair", + "SeargeFreeU", + "SeargeGenerated1", + "SeargeGenerationParameters", + "SeargeHighResolution", + "SeargeImage2ImageAndInpainting", + "SeargeImageAdapterV2", + "SeargeImageSave", + "SeargeImageSaving", + "SeargeInput1", + "SeargeInput2", + "SeargeInput3", + "SeargeInput4", + "SeargeInput5", + "SeargeInput6", + "SeargeInput7", + "SeargeIntegerConstant", + "SeargeIntegerMath", + "SeargeIntegerPair", + "SeargeIntegerScaler", + "SeargeLatentMuxer3", + "SeargeLoraLoader", + "SeargeLoras", + "SeargeMagicBox", + "SeargeModelSelector", + "SeargeOperatingMode", + "SeargeOutput1", + "SeargeOutput2", + "SeargeOutput3", + "SeargeOutput4", + "SeargeOutput5", + "SeargeOutput6", + "SeargeOutput7", + "SeargeParameterProcessor", + "SeargePipelineStart", + "SeargePipelineTerminator", + "SeargePreviewImage", + "SeargePromptAdapterV2", + "SeargePromptCombiner", + "SeargePromptStyles", + "SeargePromptText", + "SeargeSDXLBasePromptEncoder", + "SeargeSDXLImage2ImageSampler", + "SeargeSDXLImage2ImageSampler2", + "SeargeSDXLPromptEncoder", + "SeargeSDXLRefinerPromptEncoder", + "SeargeSDXLSampler", + "SeargeSDXLSampler2", + "SeargeSDXLSamplerV3", + "SeargeSamplerAdvanced", + "SeargeSamplerInputs", + "SeargeSaveFolderInputs", + "SeargeSeparator", + "SeargeStylePreprocessor", + "SeargeTextInputV2", + "SeargeUpscaleModelLoader", + "SeargeUpscaleModels", + "SeargeVAELoader" + ], + { + "title_aux": "SeargeSDXL" + } + ], + "https://github.com/Seedsa/Fooocus_Nodes": [ + [ + "BasicScheduler", + "CLIPLoader", + "CLIPMergeSimple", + "CLIPSave", + "CLIPSetLastLayer", + "CLIPTextEncode", + "CLIPTextEncodeSDXL", + "CLIPTextEncodeSDXLRefiner", + "CLIPVisionEncode", + "CLIPVisionLoader", + "Canny", + "CheckpointLoader", + "CheckpointLoaderSimple", + "CheckpointSave", + "ConditioningAverage", + "ConditioningCombine", + "ConditioningConcat", + "ConditioningSetArea", + "ConditioningSetAreaPercentage", + "ConditioningSetMask", + "ConditioningSetTimestepRange", + "ConditioningZeroOut", + "ControlNetApply", + "ControlNetApplyAdvanced", + "ControlNetLoader", + "CropMask", + "DiffControlNetLoader", + "DiffusersLoader", + "DualCLIPLoader", + "EmptyImage", + "EmptyLatentImage", + "ExponentialScheduler", + "FeatherMask", + "FlipSigmas", + "Fooocus ApplyImagePrompt", + "Fooocus Controlnet", + "Fooocus ImagePrompt", + "Fooocus Inpaint", + "Fooocus KSampler", + "Fooocus Loader", + "Fooocus LoraStack", + "Fooocus PipeOut", + "Fooocus PreKSampler", + "Fooocus Styles", + "Fooocus Upscale", + "Fooocus detailerFix", + "Fooocus negative", + "Fooocus positive", + "Fooocus preDetailerFix", + "Fooocus samLoaderPipe", + "Fooocus ultralyticsDetectorPipe", + "FreeU", + "FreeU_V2", + "GLIGENLoader", + "GLIGENTextBoxApply", + "GrowMask", + "HyperTile", + "HypernetworkLoader", + "ImageBatch", + "ImageBlend", + "ImageBlur", + "ImageColorToMask", + "ImageCompositeMasked", + "ImageCrop", + "ImageInvert", + "ImageOnlyCheckpointLoader", + "ImageOnlyCheckpointSave", + "ImagePadForOutpaint", + "ImageQuantize", + "ImageScale", + "ImageScaleBy", + "ImageScaleToTotalPixels", + "ImageSharpen", + "ImageToMask", + "ImageUpscaleWithModel", + "InpaintModelConditioning", + "InvertMask", + "JoinImageWithAlpha", + "KSampler", + "KSamplerAdvanced", + "KSamplerSelect", + "KarrasScheduler", + "LatentAdd", + "LatentBatch", + "LatentBatchSeedBehavior", + "LatentBlend", + "LatentComposite", + "LatentCompositeMasked", + "LatentCrop", + "LatentFlip", + "LatentFromBatch", + "LatentInterpolate", + "LatentMultiply", + "LatentRotate", + "LatentSubtract", + "LatentUpscale", + "LatentUpscaleBy", + "LoadImage", + "LoadImageMask", + "LoadLatent", + "LoraLoader", + "LoraLoaderModelOnly", + "MaskComposite", + "MaskToImage", + "ModelMergeAdd", + "ModelMergeBlocks", + "ModelMergeSimple", + "ModelMergeSubtract", + "ModelSamplingContinuousEDM", + "ModelSamplingDiscrete", + "PatchModelAddDownscale", + "PerpNeg", + "PhotoMakerEncode", + "PhotoMakerLoader", + "PolyexponentialScheduler", + "PorterDuffImageComposite", + "PreviewImage", + "RebatchImages", + "RebatchLatents", + "RepeatImageBatch", + "RepeatLatentBatch", + "RescaleCFG", + "SDTurboScheduler", + "SD_4XUpscale_Conditioning", + "SVD_img2vid_Conditioning", + "SamplerCustom", + "SamplerDPMPP_2M_SDE", + "SamplerDPMPP_SDE", + "SaveAnimatedPNG", + "SaveAnimatedWEBP", + "SaveImage", + "SaveLatent", + "SelfAttentionGuidance", + "SetLatentNoiseMask", + "SolidMask", + "SplitImageWithAlpha", + "SplitSigmas", + "StableZero123_Conditioning", + "StableZero123_Conditioning_Batched", + "StyleModelApply", + "StyleModelLoader", + "TomePatchModel", + "UNETLoader", + "UpscaleModelLoader", + "VAEDecode", + "VAEDecodeTiled", + "VAEEncode", + "VAEEncodeForInpaint", + "VAEEncodeTiled", + "VAELoader", + "VAESave", + "VPScheduler", + "VideoLinearCFGGuidance", + "unCLIPCheckpointLoader", + "unCLIPConditioning" + ], + { + "title_aux": "ComfyUI Fooocus Nodes" + } + ], + "https://github.com/Ser-Hilary/SDXL_sizing/raw/main/conditioning_sizing_for_SDXL.py": [ + [ + "get_aspect_from_image", + "get_aspect_from_ints", + "sizing_node", + "sizing_node_basic", + "sizing_node_unparsed" + ], + { + "title_aux": "SDXL_sizing" + } + ], + "https://github.com/Shadetail/ComfyUI_Eagleshadow": [ + [ + "Batch 12 Images", + "Detect Transparency", + "Fix Checkpoint Name", + "ImageLinearGammaCompositeMasked", + "KSampler Same Noise", + "MaskGlow", + "OffsetImage", + "Round Float to String", + "SaveImageToFolder", + "Select ControlNet", + "Select Model 20", + "Simple Load Image Batch" + ], + { + "title_aux": "Eagleshadow Custom Nodes" + } + ], + "https://github.com/SherryXieYuchen/ComfyUI-Image-Inpainting": [ + [ + "CropImageByRect", + "INPAINT_ColorCorrection", + "INPAINT_CropImage", + "INPAINT_InpaintingWithModel", + "INPAINT_LoadModel", + "INPAINT_PasteBackCropImage", + "INPAINT_VAEDecode", + "INPAINT_VAEEncode", + "ImagePostprocess", + "ImagePreprocess" + ], + { + "title_aux": "ComfyUI-Image-Inpainting" + } + ], + "https://github.com/Shibiko-AI/ShibikoAI-ComfyUI-Tools": [ + [ + "Cascade", + "Luts", + "Waifu2x" + ], + { + "title_aux": "Shibiko AI ComfyUI Tools" + } + ], + "https://github.com/ShmuelRonen/ComfyUI-SVDResizer": [ + [ + "SVDRsizer" + ], + { + "title_aux": "ComfyUI-SVDResizer" + } + ], + "https://github.com/ShmuelRonen/ComfyUI_Gemini_Flash": [ + [ + "Gemini_Flash" + ], + { + "title_aux": "ComfyUI_Gemini_Flash" + } + ], + "https://github.com/ShmuelRonen/ComfyUI_wav2lip": [ + [ + "Wav2Lip" + ], + { + "title_aux": "Wav2Lip Node for ComfyUI" + } + ], + "https://github.com/Shraknard/ComfyUI-Remover": [ + [ + "Remover" + ], + { + "title_aux": "ComfyUI-Remover" + } + ], + "https://github.com/Siberpone/lazy-pony-prompter": [ + [ + "LPP_Deleter", + "LPP_Derpibooru", + "LPP_E621", + "LPP_Loader_Derpibooru", + "LPP_Loader_E621", + "LPP_Saver" + ], + { + "title_aux": "Lazy Pony Prompter" + } + ], + "https://github.com/Smirnov75/ComfyUI-mxToolkit": [ + [ + "mxSeed", + "mxSlider", + "mxSlider2D", + "mxStop" + ], + { + "title_aux": "ComfyUI-mxToolkit" + } + ], + "https://github.com/Smuzzies/comfyui_chatbox_overlay/raw/main/chatbox_overlay.py": [ + [ + "Chatbox Overlay" + ], + { + "title_aux": "Chatbox Overlay node for ComfyUI" + } + ], + "https://github.com/Smuzzies/comfyui_meme_maker": [ + [ + "MemeMaker" + ], + { + "title_aux": "comfyui_meme_maker" + } + ], + "https://github.com/SoftMeng/ComfyUI_ImageToText": [ + [ + "ComfyUI_ImageToText" + ], + { + "title_aux": "ComfyUI_ImageToText" + } + ], + "https://github.com/SoftMeng/ComfyUI_Mexx_Poster": [ + [ + "ComfyUI_Mexx_Poster" + ], + { + "title_aux": "ComfyUI_Mexx_Poster" + } + ], + "https://github.com/SoftMeng/ComfyUI_Mexx_Styler": [ + [ + "MexxSDXLPromptStyler", + "MexxSDXLPromptStylerAdvanced" + ], + { + "title_aux": "ComfyUI_Mexx_Styler" + } + ], + "https://github.com/Sorcerio/MBM-Music-Visualizer": [ + [ + "id", + "mbmAudioFeatureCalculator", + "mbmAudioLoader", + "mbmImageConcat", + "mbmPromptSequenceBuilder", + "mbmPromptSequenceBuilderAdv", + "mbmPromptSequenceInterpolator", + "mbmPromptSequenceLoader", + "mbmPromptSequenceRenderer" + ], + { + "title_aux": "MBM's Music Visualizer" + } + ], + "https://github.com/SozeInc/ComfyUI-Mobile": [ + [ + "Mobile_Settings_Launcher_Data", + "Send Notification (Mobile)", + "Settings Launcher (Mobile)", + "Ultimate Concat (Mobile)" + ], + { + "title_aux": "ComfyUI-Mobile" + } + ], + "https://github.com/SpaceKendo/ComfyUI-svd_txt2vid": [ + [ + "SVD_txt2vid_ConditioningwithLatent" + ], + { + "title_aux": "Text to video for Stable Video Diffusion in ComfyUI" + } + ], + "https://github.com/Stability-AI/ComfyUI-SAI_API": [ + [ + "Stability Conservative Upscale", + "Stability Control Skech", + "Stability Control Structure", + "Stability Creative Upscale", + "Stability Erase", + "Stability Image Core", + "Stability Image Ultra", + "Stability Inpainting", + "Stability Outpainting", + "Stability Remove Background", + "Stability SD3", + "Stability Search and Replace" + ], + { + "title_aux": "Stability API nodes for ComfyUI" + } + ], + "https://github.com/Stability-AI/stability-ComfyUI-nodes": [ + [ + "ColorBlend", + "ControlLoraSave", + "GetImageSize" + ], + { + "title_aux": "stability-ComfyUI-nodes" + } + ], + "https://github.com/StartHua/ComfyUI_OOTDiffusion_CXH": [ + [ + "Ood_CXH" + ], + { + "title_aux": "ComfyUI_OOTDiffusion_CXH" + } + ], + "https://github.com/StartHua/ComfyUI_PCDMs": [ + [ + "PCDMS_CXH" + ], + { + "title_aux": "ComfyUI_PCDMs" + } + ], + "https://github.com/StartHua/ComfyUI_Seg_VITON": [ + [ + "segformer_agnostic", + "segformer_clothes", + "segformer_remove_bg", + "stabel_vition" + ], + { + "title_aux": "ComfyUI_Seg_VITON" + } + ], + "https://github.com/StartHua/Comfyui_joytag": [ + [ + "CXH_JoyTag" + ], + { + "title_aux": "Comfyui_joytag" + } + ], + "https://github.com/StartHua/Comfyui_segformer_b2_clothes": [ + [ + "segformer_b2_clothes" + ], + { + "title_aux": "comfyui_segformer_b2_clothes" + } + ], + "https://github.com/SuperBeastsAI/ComfyUI-SuperBeasts": [ + [ + "Deflicker (SuperBeasts.AI)", + "HDR Effects (SuperBeasts.AI)", + "Image Batch Manager (SuperBeasts.AI)", + "Make Resized Mask Batch (SuperBeasts.AI)", + "Mask Batch Manager (SuperBeasts.AI)", + "Pixel Deflicker (SuperBeasts.AI)", + "String List Manager (SuperBeasts.AI)" + ], + { + "title_aux": "ComfyUI-SuperBeasts" + } + ], + "https://github.com/SuperMasterBlasterLaser/ComfyUI_YOLO_Classifiers": [ + [ + "YOLO Classifier Model Loader", + "YOLO Classify" + ], + { + "title_aux": "ComfyUI_YOLO_Classifiers" + } + ], + "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes": [ + [ + "CR 8 Channel In", + "CR 8 Channel Out", + "CR Apply ControlNet", + "CR Apply LoRA Stack", + "CR Apply Model Merge", + "CR Apply Multi Upscale", + "CR Apply Multi-ControlNet", + "CR Arabic Text RTL", + "CR Aspect Ratio", + "CR Aspect Ratio Banners", + "CR Aspect Ratio SDXL", + "CR Aspect Ratio Social Media", + "CR Batch Images From List", + "CR Batch Process Switch", + "CR Binary Pattern", + "CR Binary To Bit List", + "CR Bit Schedule", + "CR Central Schedule", + "CR Checker Pattern", + "CR Clamp Value", + "CR Clip Input Switch", + "CR Color Bars", + "CR Color Gradient", + "CR Color Panel", + "CR Color Tint", + "CR Combine Prompt", + "CR Combine Schedules", + "CR Comic Panel Templates", + "CR Composite Text", + "CR Conditioning Input Switch", + "CR Conditioning Mixer", + "CR ControlNet Input Switch", + "CR Current Frame", + "CR Cycle Images", + "CR Cycle Images Simple", + "CR Cycle LoRAs", + "CR Cycle Models", + "CR Cycle Text", + "CR Cycle Text Simple", + "CR Data Bus In", + "CR Data Bus Out", + "CR Debatch Frames", + "CR Diamond Panel", + "CR Draw Perspective Text", + "CR Draw Pie", + "CR Draw Shape", + "CR Draw Text", + "CR Encode Scheduled Prompts", + "CR Feathered Border", + "CR Float Range List", + "CR Float To Integer", + "CR Float To String", + "CR Font File List", + "CR Get Parameter From Prompt", + "CR Gradient Float", + "CR Gradient Integer", + "CR Half Drop Panel", + "CR Halftone Filter", + "CR Halftone Grid", + "CR Hires Fix Process Switch", + "CR Image Border", + "CR Image Grid Panel", + "CR Image Input Switch", + "CR Image Input Switch (4 way)", + "CR Image List", + "CR Image List Simple", + "CR Image Output", + "CR Image Panel", + "CR Image Pipe Edit", + "CR Image Pipe In", + "CR Image Pipe Out", + "CR Image Size", + "CR Img2Img Process Switch", + "CR Increment Float", + "CR Increment Integer", + "CR Index", + "CR Index Increment", + "CR Index Multiply", + "CR Index Reset", + "CR Input Text List", + "CR Integer Multiple", + "CR Integer Range List", + "CR Integer To String", + "CR Interpolate Latents", + "CR Intertwine Lists", + "CR Keyframe List", + "CR Latent Batch Size", + "CR Latent Input Switch", + "CR LoRA List", + "CR LoRA Stack", + "CR Load Animation Frames", + "CR Load Flow Frames", + "CR Load GIF As List", + "CR Load Image List", + "CR Load Image List Plus", + "CR Load LoRA", + "CR Load Prompt Style", + "CR Load Schedule From File", + "CR Load Scheduled ControlNets", + "CR Load Scheduled LoRAs", + "CR Load Scheduled Models", + "CR Load Text List", + "CR Mask Text", + "CR Math Operation", + "CR Model Input Switch", + "CR Model List", + "CR Model Merge Stack", + "CR Module Input", + "CR Module Output", + "CR Module Pipe Loader", + "CR Multi Upscale Stack", + "CR Multi-ControlNet Stack", + "CR Multiline Text", + "CR Output Flow Frames", + "CR Output Schedule To File", + "CR Overlay Text", + "CR Overlay Transparent Image", + "CR Page Layout", + "CR Pipe Switch", + "CR Polygons", + "CR Prompt List", + "CR Prompt List Keyframes", + "CR Prompt Scheduler", + "CR Prompt Text", + "CR Radial Gradient", + "CR Random Hex Color", + "CR Random LoRA Stack", + "CR Random Multiline Colors", + "CR Random Multiline Values", + "CR Random Panel Codes", + "CR Random RGB", + "CR Random RGB Gradient", + "CR Random Shape Pattern", + "CR Random Weight LoRA", + "CR Repeater", + "CR SD1.5 Aspect Ratio", + "CR SDXL Aspect Ratio", + "CR SDXL Base Prompt Encoder", + "CR SDXL Prompt Mix Presets", + "CR SDXL Prompt Mixer", + "CR SDXL Style Text", + "CR Save Text To File", + "CR Schedule Input Switch", + "CR Schedule To ScheduleList", + "CR Seamless Checker", + "CR Seed", + "CR Seed to Int", + "CR Select Font", + "CR Select ISO Size", + "CR Select Model", + "CR Select Resize Method", + "CR Set Switch From String", + "CR Set Value On Binary", + "CR Set Value On Boolean", + "CR Set Value on String", + "CR Simple Banner", + "CR Simple Binary Pattern", + "CR Simple Binary Pattern Simple", + "CR Simple Image Compare", + "CR Simple List", + "CR Simple Meme Template", + "CR Simple Prompt List", + "CR Simple Prompt List Keyframes", + "CR Simple Prompt Scheduler", + "CR Simple Schedule", + "CR Simple Text Panel", + "CR Simple Text Scheduler", + "CR Simple Text Watermark", + "CR Simple Titles", + "CR Simple Value Scheduler", + "CR Split String", + "CR Starburst Colors", + "CR Starburst Lines", + "CR String To Boolean", + "CR String To Combo", + "CR String To Number", + "CR Style Bars", + "CR Switch Model and CLIP", + "CR Text", + "CR Text Blacklist", + "CR Text Concatenate", + "CR Text Cycler", + "CR Text Input Switch", + "CR Text Input Switch (4 way)", + "CR Text Length", + "CR Text List", + "CR Text List Simple", + "CR Text List To String", + "CR Text Operation", + "CR Text Replace", + "CR Text Scheduler", + "CR Thumbnail Preview", + "CR Trigger", + "CR Upscale Image", + "CR VAE Decode", + "CR VAE Input Switch", + "CR Value", + "CR Value Cycler", + "CR Value Scheduler", + "CR Vignette Filter", + "CR XY From Folder", + "CR XY Index", + "CR XY Interpolate", + "CR XY List", + "CR XY Product", + "CR XY Save Grid Image", + "CR XYZ Index", + "CR_Aspect Ratio For Print" + ], + { + "author": "Suzie1", + "description": "175 custom nodes for artists, designers and animators.", + "nickname": "Comfyroll Studio", + "title": "Comfyroll Studio", + "title_aux": "Comfyroll Studio" + } + ], + "https://github.com/Sxela/ComfyWarp": [ + [ + "ExtractOpticalFlow", + "LoadFrame", + "LoadFrameFromDataset", + "LoadFrameFromFolder", + "LoadFramePairFromDataset", + "LoadFrameSequence", + "MakeFrameDataset", + "MixConsistencyMaps", + "OffsetNumber", + "ResizeToFit", + "SaveFrame", + "WarpFrame" + ], + { + "title_aux": "ComfyWarp" + } + ], + "https://github.com/TGu-97/ComfyUI-TGu-utils": [ + [ + "MPNReroute", + "MPNSwitch", + "PNSwitch" + ], + { + "title_aux": "TGu Utilities" + } + ], + "https://github.com/THtianhao/ComfyUI-FaceChain": [ + [ + "FC CropAndPaste", + "FC CropBottom", + "FC CropToOrigin", + "FC FaceDetectCrop", + "FC FaceFusion", + "FC FaceSegAndReplace", + "FC FaceSegment", + "FC MaskOP", + "FC RemoveCannyFace", + "FC ReplaceByMask", + "FC StyleLoraLoad" + ], + { + "title_aux": "ComfyUI-FaceChain" + } + ], + "https://github.com/THtianhao/ComfyUI-Portrait-Maker": [ + [ + "PM_BoxCropImage", + "PM_ColorTransfer", + "PM_ExpandMaskBox", + "PM_FaceFusion", + "PM_FaceShapMatch", + "PM_FaceSkin", + "PM_GetImageInfo", + "PM_ImageResizeTarget", + "PM_ImageScaleShort", + "PM_MakeUpTransfer", + "PM_MaskDilateErode", + "PM_MaskMerge2Image", + "PM_PortraitEnhancement", + "PM_RatioMerge2Image", + "PM_ReplaceBoxImg", + "PM_RetinaFace", + "PM_Similarity", + "PM_SkinRetouching", + "PM_SuperColorTransfer", + "PM_SuperMakeUpTransfer" + ], + { + "title_aux": "ComfyUI-Portrait-Maker" + } + ], + "https://github.com/TJ16th/comfyUI_TJ_NormalLighting": [ + [ + "EulerLightingNode" + ], + { + "title_aux": "comfyUI_TJ_NormalLighting" + } + ], + "https://github.com/TMElyralab/Comfyui-MusePose": [ + [ + "filenamestring", + "musepose", + "museposealign" + ], + { + "title_aux": "Comfyui-MusePose" + } + ], + "https://github.com/TRI3D-LC/ComfyUI-MiroBoard": [ + [ + "add-image-miro-board" + ], + { + "title_aux": "ComfyUI-MiroBoard" + } + ], + "https://github.com/TRI3D-LC/tri3d-comfyui-nodes": [ + [ + "get_histogram_limits", + "main_light_layer", + "main_scaled_paste", + "simple_rescale_histogram", + "tri3d-HistogramEqualization", + "tri3d-LAB_2_RGB", + "tri3d-RGB_2_LAB", + "tri3d-adjust-neck", + "tri3d-atr-parse", + "tri3d-atr-parse-batch", + "tri3d-bgremove-mega", + "tri3d-clear-memory", + "tri3d-clipdrop-bgremove-api", + "tri3d-clipdrop-bgreplace-api", + "tri3d-composite-image-splitter", + "tri3d-dwpose", + "tri3d-extract-hand", + "tri3d-extract-masks-batch", + "tri3d-extract-parts-batch", + "tri3d-extract-parts-batch2", + "tri3d-extract-parts-mask-batch", + "tri3d-extract-pascal-parts-batch", + "tri3d-face-recognise", + "tri3d-facer_face_segment", + "tri3d-flexible_color_extract", + "tri3d-float-to-image", + "tri3d-fuzzification", + "tri3d-get_histogram_limits", + "tri3d-get_mean_and_standard_deviation", + "tri3d-get_threshold_for_bg_swap", + "tri3d-image-mask-2-box", + "tri3d-image-mask-box-2-image", + "tri3d-interaction-canny", + "tri3d-levindabhi-cloth-seg", + "tri3d-load-pose-json", + "tri3d-load_AEMatter_Model", + "tri3d-load_MVANet_Model", + "tri3d-luminosity-match", + "tri3d-main_transparent_background", + "tri3d-photoroom-bgremove-api", + "tri3d-pose-adaption", + "tri3d-pose-to-image", + "tri3d-position-hands", + "tri3d-position-parts-batch", + "tri3d-position-pascal-parts-batch", + "tri3d-recolor-mask", + "tri3d-recolor-mask-LAB_space", + "tri3d-recolor-mask-LAB_space_manual", + "tri3d-recolor-mask-RGB_space", + "tri3d-renormalize_array", + "tri3d-run_AEMatter_inference", + "tri3d-run_MVANet_inference", + "tri3d-scaled-paste", + "tri3d-simple_bg_swap", + "tri3d-simple_rescale_histogram", + "tri3d-skin-feathered-padded-mask", + "tri3d-swap-pixels" + ], + { + "title_aux": "tri3d-comfyui-nodes" + } + ], + "https://github.com/TW-CUI/TW-CUI-Util": [ + [ + "TWCUI_Util_CommonSDXLResolutions", + "TWCUI_Util_FloatLiteral", + "TWCUI_Util_GenerationParameters", + "TWCUI_Util_GenerationPrompts", + "TWCUI_Util_IntLiteral", + "TWCUI_Util_ModelVAELORALoader", + "TWCUI_Util_ModelVAELoader", + "TWCUI_Util_MultilineStringLiteral", + "TWCUI_Util_SaveImage", + "TWCUI_Util_SaveImageAdvanced", + "TWCUI_Util_StringLiteral" + ], + { + "title_aux": "TW-CUI-Util" + } + ], + "https://github.com/TaiTair/comfyui-simswap": [ + [ + "Simswap", + "SimswapBuildFaceModel", + "SimswapFaceSwapOpt", + "SimswapImageDublicator", + "SimswapLoadFaceModel", + "SimswapMaskHelper", + "SimswapOptions", + "SimswapRestoreFace", + "SimswapSaveFaceModel" + ], + { + "title_aux": "Simswap Node for ComfyUI" + } + ], + "https://github.com/Taremin/comfyui-prompt-extranetworks": [ + [ + "PromptExtraNetworks" + ], + { + "title_aux": "ComfyUI Prompt ExtraNetworks" + } + ], + "https://github.com/Taremin/comfyui-string-tools": [ + [ + "StringToolsBalancedChoice", + "StringToolsConcat", + "StringToolsRandomChoice", + "StringToolsString", + "StringToolsText" + ], + { + "title_aux": "ComfyUI String Tools" + } + ], + "https://github.com/Taremin/webui-monaco-prompt": [ + [ + "WebuiMonacoPromptFind", + "WebuiMonacoPromptReplace" + ], + { + "title_aux": "WebUI Monaco Prompt" + } + ], + "https://github.com/TeaCrab/ComfyUI-TeaNodes": [ + [ + "TC_ColorFill", + "TC_CropTo", + "TC_EqualizeCLAHE", + "TC_ImageResize", + "TC_ImageScale", + "TC_KorniaGamma", + "TC_RandomColorFill", + "TC_SizeApproximation" + ], + { + "title_aux": "ComfyUI-TeaNodes" + } + ], + "https://github.com/TemryL/ComfyS3": [ + [ + "DownloadFileS3", + "LoadImageS3", + "SaveImageS3", + "SaveVideoFilesS3", + "UploadFileS3" + ], + { + "title_aux": "ComfyS3" + } + ], + "https://github.com/TemryL/ComfyUI-IDM-VTON": [ + [ + "IDM-VTON", + "PipelineLoader" + ], + { + "title_aux": "ComfyUI-IDM-VTON [WIP]" + } + ], + "https://github.com/TencentQQGYLab/ComfyUI-ELLA": [ + [ + "CombineClipEllaEmbeds", + "ConcatConditionEllaEmbeds", + "ConditionToEllaEmbeds", + "ELLALoader", + "EllaApply", + "EllaCombineEmbeds", + "EllaEncode", + "EllaTextEncode", + "SetEllaTimesteps", + "T5TextEncode #ELLA", + "T5TextEncoderLoader #ELLA" + ], + { + "title_aux": "ComfyUI-ELLA" + } + ], + "https://github.com/TheBarret/ZSuite": [ + [ + "ZSuite: Prompter", + "ZSuite: RF Noise", + "ZSuite: SeedMod" + ], + { + "title_aux": "ZSuite" + } + ], + "https://github.com/TheBill2001/comfyui-upscale-by-model": [ + [ + "UpscaleImageByUsingModel" + ], + { + "author": "Tr\u1ea7n Nam Tu\u1ea5n", + "description": "This custom node allow upscaling an image by a factor using a model.", + "nickname": "Upscale Image By (Using Model)", + "title": "Upscale Image By (Using Model)", + "title_aux": "comfyui-upscale-by-model" + } + ], + "https://github.com/TheMistoAI/ComfyUI-Anyline": [ + [ + "AnyLinePreprocessor" + ], + { + "title_aux": "Anyline" + } + ], + "https://github.com/ThereforeGames/ComfyUI-Unprompted": [ + [ + "Unprompted" + ], + { + "title_aux": "ComfyUI-Unprompted" + } + ], + "https://github.com/TinyTerra/ComfyUI_tinyterraNodes": [ + [ + "ttN KSampler_v2", + "ttN advPlot combo", + "ttN advPlot range", + "ttN advPlot string", + "ttN advanced xyPlot", + "ttN compareInput", + "ttN concat", + "ttN conditioning", + "ttN debugInput", + "ttN float", + "ttN hiresfixScale", + "ttN imageOutput", + "ttN imageREMBG", + "ttN int", + "ttN multiModelMerge", + "ttN pipe2BASIC", + "ttN pipe2DETAILER", + "ttN pipeEDIT", + "ttN pipeEncodeConcat", + "ttN pipeIN", + "ttN pipeKSampler", + "ttN pipeKSamplerAdvanced", + "ttN pipeKSamplerAdvanced_v2", + "ttN pipeKSamplerSDXL", + "ttN pipeKSamplerSDXL_v2", + "ttN pipeKSampler_v2", + "ttN pipeLoader", + "ttN pipeLoaderSDXL", + "ttN pipeLoaderSDXL_v2", + "ttN pipeLoader_v2", + "ttN pipeLoraStack", + "ttN pipeOUT", + "ttN seed", + "ttN text", + "ttN text3BOX_3WAYconcat", + "ttN text7BOX_concat", + "ttN textCycleLine", + "ttN textDebug", + "ttN tinyLoader", + "ttN xyPlot" + ], + { + "author": "tinyterra", + "description": "This extension offers extensive xyPlot, various pipe nodes, fullscreen image viewer based on node history, dynamic widgets, interface customization, and more.", + "nickname": "\ud83c\udf0f", + "nodename_pattern": "^ttN ", + "title": "tinyterraNodes", + "title_aux": "ComfyUI_tinyterraNodes" + } + ], + "https://github.com/TripleHeadedMonkey/ComfyUI_MileHighStyler": [ + [ + "menus" + ], + { + "title_aux": "ComfyUI_MileHighStyler" + } + ], + "https://github.com/Tropfchen/ComfyUI-Embedding_Picker": [ + [ + "EmbeddingPicker" + ], + { + "title_aux": "Embedding Picker" + } + ], + "https://github.com/Tropfchen/ComfyUI-yaResolutionSelector": [ + [ + "YARS", + "YARSAdv" + ], + { + "title_aux": "YARS: Yet Another Resolution Selector" + } + ], + "https://github.com/Trung0246/ComfyUI-0246": [ + [ + "0246.Beautify", + "0246.BoxRange", + "0246.CastReroute", + "0246.Cloud", + "0246.Convert", + "0246.Count", + "0246.Highway", + "0246.HighwayBatch", + "0246.Hold", + "0246.Hub", + "0246.Junction", + "0246.JunctionBatch", + "0246.Loop", + "0246.Merge", + "0246.Meta", + "0246.Pick", + "0246.RandomInt", + "0246.Script", + "0246.ScriptNode", + "0246.ScriptPile", + "0246.ScriptRule", + "0246.Stringify", + "0246.Switch", + "0246.Tag" + ], + { + "author": "Trung0246", + "description": "Random nodes for ComfyUI I made to solve my struggle with ComfyUI (ex: pipe, process). Have varying quality.", + "nickname": "ComfyUI-0246", + "title": "ComfyUI-0246", + "title_aux": "ComfyUI-0246" + } + ], + "https://github.com/Ttl/ComfyUi_NNLatentUpscale": [ + [ + "NNLatentUpscale" + ], + { + "preemptions": [ + "NNLatentUpscale" + ], + "title_aux": "ComfyUI Neural Network Latent Upscale" + } + ], + "https://github.com/TylerZoro/SD3-Scaling": [ + [ + "SD3ImageScaleToTotalPixels" + ], + { + "title_aux": "SD3-Scaling" + } + ], + "https://github.com/Umikaze-job/select_folder_path_easy": [ + [ + "SelectFolderPathEasy" + ], + { + "title_aux": "select_folder_path_easy" + } + ], + "https://github.com/VAST-AI-Research/ComfyUI-Tripo": [ + [ + "TripoAPIImageToMeshNode", + "TripoAPITextToMeshNode", + "TripoGLBViewer" + ], + { + "title_aux": "Tripo for ComfyUI" + } + ], + "https://github.com/WASasquatch/ASTERR": [ + [ + "ASTERR", + "SaveASTERR" + ], + { + "title_aux": "ASTERR" + } + ], + "https://github.com/WASasquatch/ComfyUI_Preset_Merger": [ + [ + "Preset_Model_Merge" + ], + { + "title_aux": "ComfyUI Preset Merger" + } + ], + "https://github.com/WASasquatch/FreeU_Advanced": [ + [ + "FreeU (Advanced)", + "FreeU_V2 (Advanced)" + ], + { + "title_aux": "FreeU_Advanced" + } + ], + "https://github.com/WASasquatch/PPF_Noise_ComfyUI": [ + [ + "Blend Latents (PPF Noise)", + "Cross-Hatch Power Fractal (PPF Noise)", + "Images as Latents (PPF Noise)", + "Perlin Power Fractal Latent (PPF Noise)" + ], + { + "title_aux": "PPF_Noise_ComfyUI" + } + ], + "https://github.com/WASasquatch/PowerNoiseSuite": [ + [ + "Blend Latents (PPF Noise)", + "Cross-Hatch Power Fractal (PPF Noise)", + "Cross-Hatch Power Fractal Settings (PPF Noise)", + "Images as Latents (PPF Noise)", + "Latent Adjustment (PPF Noise)", + "Latents to CPU (PPF Noise)", + "Linear Cross-Hatch Power Fractal (PPF Noise)", + "Perlin Power Fractal Latent (PPF Noise)", + "Perlin Power Fractal Settings (PPF Noise)", + "Power KSampler Advanced (PPF Noise)", + "Power-Law Noise (PPF Noise)" + ], + { + "title_aux": "Power Noise Suite for ComfyUI" + } + ], + "https://github.com/WASasquatch/WAS_Extras": [ + [ + "BLVAEEncode", + "CLIPTextEncodeList", + "CLIPTextEncodeSequence2", + "ConditioningBlend", + "DebugInput", + "KSamplerSeq", + "KSamplerSeq2", + "VAEEncodeForInpaint (WAS)", + "VividSharpen" + ], + { + "title_aux": "WAS_Extras" + } + ], + "https://github.com/WASasquatch/was-node-suite-comfyui": [ + [ + "BLIP Analyze Image", + "BLIP Model Loader", + "Blend Latents", + "Boolean To Text", + "Bounded Image Blend", + "Bounded Image Blend with Mask", + "Bounded Image Crop", + "Bounded Image Crop with Mask", + "Bus Node", + "CLIP Input Switch", + "CLIP Vision Input Switch", + "CLIPSeg Batch Masking", + "CLIPSeg Masking", + "CLIPSeg Model Loader", + "CLIPTextEncode (BlenderNeko Advanced + NSP)", + "CLIPTextEncode (NSP)", + "Cache Node", + "Checkpoint Loader", + "Checkpoint Loader (Simple)", + "Conditioning Input Switch", + "Constant Number", + "Control Net Model Input Switch", + "Convert Masks to Images", + "Create Grid Image", + "Create Grid Image from Batch", + "Create Morph Image", + "Create Morph Image from Path", + "Create Video from Path", + "Debug Number to Console", + "Dictionary to Console", + "Diffusers Hub Model Down-Loader", + "Diffusers Model Loader", + "Export API", + "HSL to Hex", + "Hex to HSL", + "Image Analyze", + "Image Aspect Ratio", + "Image Batch", + "Image Blank", + "Image Blend", + "Image Blend by Mask", + "Image Blending Mode", + "Image Bloom Filter", + "Image Bounds", + "Image Bounds to Console", + "Image Canny Filter", + "Image Chromatic Aberration", + "Image Color Palette", + "Image Crop Face", + "Image Crop Location", + "Image Crop Square Location", + "Image Displacement Warp", + "Image Dragan Photography Filter", + "Image Edge Detection Filter", + "Image Film Grain", + "Image Filter Adjustments", + "Image Flip", + "Image Generate Gradient", + "Image Gradient Map", + "Image High Pass Filter", + "Image History Loader", + "Image Input Switch", + "Image Levels Adjustment", + "Image Load", + "Image Lucy Sharpen", + "Image Median Filter", + "Image Mix RGB Channels", + "Image Monitor Effects Filter", + "Image Nova Filter", + "Image Padding", + "Image Paste Crop", + "Image Paste Crop by Location", + "Image Paste Face", + "Image Perlin Noise", + "Image Perlin Power Fractal", + "Image Pixelate", + "Image Power Noise", + "Image Rembg (Remove Background)", + "Image Remove Background (Alpha)", + "Image Remove Color", + "Image Resize", + "Image Rotate", + "Image Rotate Hue", + "Image SSAO (Ambient Occlusion)", + "Image SSDO (Direct Occlusion)", + "Image Save", + "Image Seamless Texture", + "Image Select Channel", + "Image Select Color", + "Image Send HTTP", + "Image Shadows and Highlights", + "Image Size to Number", + "Image Stitch", + "Image Style Filter", + "Image Threshold", + "Image Tiled", + "Image Transpose", + "Image Voronoi Noise Filter", + "Image fDOF Filter", + "Image to Latent Mask", + "Image to Noise", + "Image to Seed", + "Images to Linear", + "Images to RGB", + "Inset Image Bounds", + "Integer place counter", + "KSampler (WAS)", + "KSampler Cycle", + "Latent Batch", + "Latent Input Switch", + "Latent Noise Injection", + "Latent Size to Number", + "Latent Upscale by Factor (WAS)", + "Load Cache", + "Load Image Batch", + "Load Lora", + "Load Text File", + "Logic Boolean", + "Logic Boolean Primitive", + "Logic Comparison AND", + "Logic Comparison OR", + "Logic Comparison XOR", + "Logic NOT", + "Lora Input Switch", + "Lora Loader", + "Mask Arbitrary Region", + "Mask Batch", + "Mask Batch to Mask", + "Mask Ceiling Region", + "Mask Crop Dominant Region", + "Mask Crop Minority Region", + "Mask Crop Region", + "Mask Dilate Region", + "Mask Dominant Region", + "Mask Erode Region", + "Mask Fill Holes", + "Mask Floor Region", + "Mask Gaussian Region", + "Mask Invert", + "Mask Minority Region", + "Mask Paste Region", + "Mask Smooth Region", + "Mask Threshold Region", + "Masks Add", + "Masks Combine Batch", + "Masks Combine Regions", + "Masks Subtract", + "MiDaS Depth Approximation", + "MiDaS Mask Image", + "MiDaS Model Loader", + "Model Input Switch", + "Number Counter", + "Number Input Condition", + "Number Input Switch", + "Number Multiple Of", + "Number Operation", + "Number PI", + "Number to Float", + "Number to Int", + "Number to Seed", + "Number to String", + "Number to Text", + "Prompt Multiple Styles Selector", + "Prompt Styles Selector", + "Random Number", + "SAM Image Mask", + "SAM Model Loader", + "SAM Parameters", + "SAM Parameters Combine", + "Samples Passthrough (Stat System)", + "Save Text File", + "Seed", + "String to Text", + "Tensor Batch to Image", + "Text Add Token by Input", + "Text Add Tokens", + "Text Compare", + "Text Concatenate", + "Text Contains", + "Text Dictionary Convert", + "Text Dictionary Get", + "Text Dictionary Keys", + "Text Dictionary New", + "Text Dictionary To Text", + "Text Dictionary Update", + "Text File History Loader", + "Text Find", + "Text Find and Replace", + "Text Find and Replace Input", + "Text Find and Replace by Dictionary", + "Text Input Switch", + "Text List", + "Text List Concatenate", + "Text List to Text", + "Text Load Line From File", + "Text Multiline", + "Text Multiline (Code Compatible)", + "Text Parse A1111 Embeddings", + "Text Parse Noodle Soup Prompts", + "Text Parse Tokens", + "Text Random Line", + "Text Random Prompt", + "Text Shuffle", + "Text Sort", + "Text String", + "Text String Truncate", + "Text to Conditioning", + "Text to Console", + "Text to Number", + "Text to String", + "True Random.org Number Generator", + "Upscale Model Loader", + "Upscale Model Switch", + "VAE Input Switch", + "Video Dump Frames", + "Write to GIF", + "Write to Video", + "unCLIP Checkpoint Loader" + ], + { + "title_aux": "WAS Node Suite" + } + ], + "https://github.com/WebDev9000/WebDev9000-Nodes": [ + [ + "IgnoreBraces", + "SettingsSwitch" + ], + { + "title_aux": "WebDev9000-Nodes" + } + ], + "https://github.com/Wicloz/ComfyUI-Simply-Nodes": [ + [ + "WF_ConditionalLoraLoader", + "WF_MultilineText", + "WF_RandomStyle", + "WF_ResolutionSDXL", + "WF_TextFlow" + ], + { + "title_aux": "ComfyUI Simply Nodes" + } + ], + "https://github.com/XmYx/deforum-comfy-nodes": [ + [ + "DeforumAddNoiseNode", + "DeforumAnimParamsNode", + "DeforumAreaPromptNode", + "DeforumBaseParamsNode", + "DeforumCacheLatentNode", + "DeforumCadenceNode", + "DeforumCadenceParamsNode", + "DeforumColorMatchNode", + "DeforumColorParamsNode", + "DeforumConditioningBlendNode", + "DeforumDepthParamsNode", + "DeforumDiffusionParamsNode", + "DeforumFILMInterpolationNode", + "DeforumFrameWarpNode", + "DeforumGetCachedLatentNode", + "DeforumHybridMotionNode", + "DeforumHybridParamsNode", + "DeforumHybridScheduleNode", + "DeforumIteratorNode", + "DeforumKSampler", + "DeforumLoadVideo", + "DeforumNoiseParamsNode", + "DeforumPromptNode", + "DeforumSeedNode", + "DeforumSetVAEDownscaleRatioNode", + "DeforumSimpleInterpolationNode", + "DeforumSingleSampleNode", + "DeforumTranslationParamsNode", + "DeforumVideoSaveNode" + ], + { + "title_aux": "Deforum Nodes" + } + ], + "https://github.com/Xyem/Xycuno-Oobabooga": [ + [ + "Oobabooga" + ], + { + "title_aux": "Xycuno Oobabooga" + } + ], + "https://github.com/YMC-GitHub/ymc-node-suite-comfyui": [ + [ + "canvas-util-cal-size", + "conditioning-util-input-switch", + "cutoff-region-util", + "hks-util-cal-denoise-step", + "img-util-get-image-size", + "img-util-switch-input-image", + "io-image-save", + "io-text-save", + "io-util-file-list-get", + "io-util-file-list-get-text", + "number-util-random-num", + "pipe-util-to-basic-pipe", + "region-util-get-by-center-and-size", + "region-util-get-by-lt", + "region-util-get-crop-location-from-center-size-text", + "region-util-get-pad-out-location-by-size", + "text-preset-colors", + "text-util-join-text", + "text-util-loop-text", + "text-util-path-list", + "text-util-prompt-add-prompt", + "text-util-prompt-adv-dup", + "text-util-prompt-adv-search", + "text-util-prompt-del", + "text-util-prompt-dup", + "text-util-prompt-join", + "text-util-prompt-search", + "text-util-prompt-shuffle", + "text-util-prompt-std", + "text-util-prompt-unweight", + "text-util-random-text", + "text-util-search-text", + "text-util-show-text", + "text-util-switch-text", + "xyz-util-txt-to-int" + ], + { + "title_aux": "ymc-node-suite-comfyui" + } + ], + "https://github.com/YOUR-WORST-TACO/ComfyUI-TacoNodes": [ + [ + "Example", + "TacoAnimatedLoader", + "TacoGifMaker", + "TacoImg2ImgAnimatedLoader", + "TacoImg2ImgAnimatedProcessor", + "TacoLatent" + ], + { + "title_aux": "ComfyUI-TacoNodes" + } + ], + "https://github.com/Yanick112/ComfyUI-ToSVG": [ + [ + "ConvertRasterToVector", + "SaveSVG" + ], + { + "title_aux": "ComfyUI-ToSVG" + } + ], + "https://github.com/YinBailiang/MergeBlockWeighted_fo_ComfyUI": [ + [ + "MergeBlockWeighted" + ], + { + "title_aux": "MergeBlockWeighted_fo_ComfyUI" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR": [ + [ + "APISR_Lterative_Zho", + "APISR_ModelLoader_Zho", + "APISR_Zho" + ], + { + "title_aux": "APISR IN COMFYUI" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Animated-optical-illusions": [ + [ + "AOI_Processing_Zho" + ], + { + "title_aux": "ComfyUI-Animated-optical-illusions" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-ArtGallery": [ + [ + "ArtGallery_Zho", + "ArtistsImage_Zho", + "CamerasImage_Zho", + "FilmsImage_Zho", + "MovementsImage_Zho", + "StylesImage_Zho" + ], + { + "title_aux": "ComfyUI-ArtGallery" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BRIA_AI-RMBG": [ + [ + "BRIA_RMBG_ModelLoader_Zho", + "BRIA_RMBG_Zho" + ], + { + "title_aux": "ComfyUI-BRIA_AI-RMBG" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BiRefNet-ZHO": [ + [ + "BiRefNet_ModelLoader_Zho", + "BiRefNet_Zho" + ], + { + "title_aux": "ComfyUI-BiRefNet-ZHO" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-DepthFM": [ + [ + "DepthFM_Literative_Zho", + "DepthFM_ModelLoader_Zho", + "DepthFM_Zho" + ], + { + "title_aux": "DepthFM IN COMFYUI" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Gemini": [ + [ + "ConcatText_Zho", + "DisplayText_Zho", + "Gemini_15P_API_S_Advance_Zho", + "Gemini_15P_API_S_Chat_Advance_Zho", + "Gemini_API_Chat_Zho", + "Gemini_API_S_Chat_Zho", + "Gemini_API_S_Vsion_ImgURL_Zho", + "Gemini_API_S_Zho", + "Gemini_API_Vsion_ImgURL_Zho", + "Gemini_API_Zho", + "Gemini_FileUpload_API_S_Zho", + "Gemini_File_API_S_Zho" + ], + { + "title_aux": "ComfyUI-Gemini" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-InstantID": [ + [ + "IDBaseModelLoader_fromhub", + "IDBaseModelLoader_local", + "IDControlNetLoader", + "IDGenerationNode", + "ID_Prompt_Styler", + "InsightFaceLoader_Zho", + "Ipadapter_instantidLoader" + ], + { + "title_aux": "ComfyUI-InstantID" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Phi-3-mini": [ + [ + "Phi3mini_4k_Chat_Zho", + "Phi3mini_4k_ModelLoader_Zho", + "Phi3mini_4k_Zho" + ], + { + "title_aux": "Phi-3-mini in ComfyUI" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PhotoMaker-ZHO": [ + [ + "BaseModel_Loader_fromhub", + "BaseModel_Loader_local", + "LoRALoader", + "NEW_PhotoMaker_Generation", + "PhotoMakerAdapter_Loader_fromhub", + "PhotoMakerAdapter_Loader_local", + "PhotoMaker_Generation", + "Prompt_Styler", + "Ref_Image_Preprocessing" + ], + { + "title_aux": "ComfyUI PhotoMaker (ZHO)" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PixArt-alpha-Diffusers": [ + [ + "PA_BaseModelLoader_fromhub_Zho", + "PA_Generation_Zho", + "PA_Styler_Zho" + ], + { + "title_aux": "ComfyUI-PixArt-alpha-Diffusers" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Q-Align": [ + [ + "QAlign_Zho" + ], + { + "title_aux": "ComfyUI-Q-Align" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-2": [ + [ + "Qwen2_Chat_Zho", + "Qwen2_ModelLoader_Zho", + "Qwen2_Zho" + ], + { + "title_aux": "ComfyUI-Qwen-2" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Qwen-VL-API": [ + [ + "QWenVL_API_S_Multi_Zho", + "QWenVL_API_S_Zho" + ], + { + "title_aux": "ComfyUI-Qwen-VL-API" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SVD-ZHO": [ + [ + "SVD_Aspect_Ratio_Zho", + "SVD_Steps_MotionStrength_Seed_Zho", + "SVD_Styler_Zho" + ], + { + "title_aux": "ComfyUI-SVD-ZHO (WIP)" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-SegMoE": [ + [ + "SMoE_Generation_Zho", + "SMoE_ModelLoader_Zho" + ], + { + "title_aux": "ComfyUI SegMoE" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-Text_Image-Composite": [ + [ + "AlphaChanelAddByMask", + "ImageCompositeBy_BG_Zho", + "ImageCompositeBy_Zho", + "ImageComposite_BG_Zho", + "ImageComposite_Zho", + "RGB_Image_Zho", + "Text_Image_Frame_Zho", + "Text_Image_Multiline_Zho", + "Text_Image_Zho" + ], + { + "title_aux": "ComfyUI-Text_Image-Composite [WIP]" + } + ], + "https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM": [ + [ + "ESAM_ModelLoader_Zho", + "Yoloworld_ESAM_DetectorProvider_Zho", + "Yoloworld_ESAM_Zho", + "Yoloworld_ModelLoader_Zho" + ], + { + "title_aux": "ComfyUI YoloWorld-EfficientSAM" + } + ], + "https://github.com/ZHO-ZHO-ZHO/comfyui-portrait-master-zh-cn": [ + [ + "PortraitMaster_\u4e2d\u6587\u7248" + ], + { + "title_aux": "comfyui-portrait-master-zh-cn" + } + ], + "https://github.com/ZZXYWQ/ComfyUI-ZZXYWQ": [ + [ + "VideoFormatConverter" + ], + { + "title_aux": "ZZX Nodes" + } + ], + "https://github.com/ZaneA/ComfyUI-ImageReward": [ + [ + "ImageRewardLoader", + "ImageRewardScore" + ], + { + "title_aux": "ImageReward" + } + ], + "https://github.com/ZeDarkAdam/ComfyUI-Embeddings-Tools": [ + [ + "EmbeddingsNameLoader", + "EmbendingList" + ], + { + "title_aux": "ComfyUI-Embeddings-Tools" + } + ], + "https://github.com/a1lazydog/ComfyUI-AudioScheduler": [ + [ + "AmplitudeToGraph", + "AmplitudeToNumber", + "AudioToAmplitudeGraph", + "AudioToFFTs", + "BatchAmplitudeSchedule", + "ClipAmplitude", + "FloatArrayToGraph", + "GateNormalizedAmplitude", + "LoadAudio", + "LoadVHSAudio", + "NormalizeAmplitude", + "NormalizedAmplitudeDrivenString", + "NormalizedAmplitudeToGraph", + "NormalizedAmplitudeToNumber", + "TransientAmplitudeBasic" + ], + { + "title_aux": "ComfyUI-AudioScheduler" + } + ], + "https://github.com/aburahamu/ComfyUI-IsNiceParts": [ + [ + "NiceHand" + ], + { + "title_aux": "ComfyUI-IsNiceParts" + } + ], + "https://github.com/aburahamu/ComfyUI-RequestsPoster": [ + [ + "GetImageFromSD3byI2I", + "GetImageFromSD3byT2I", + "PostImage2Discord", + "PostImage2X", + "PostText" + ], + { + "title_aux": "ComfyUI-RequestPoster" + } + ], + "https://github.com/abyz22/image_control": [ + [ + "abyz22_AddPrompt", + "abyz22_Convertpipe", + "abyz22_Editpipe", + "abyz22_FirstNonNull", + "abyz22_FromBasicPipe_v2", + "abyz22_Frompipe", + "abyz22_ImpactWildcardEncode", + "abyz22_ImpactWildcardEncode_GetPrompt", + "abyz22_Ksampler", + "abyz22_Padding Image", + "abyz22_RandomMask", + "abyz22_RemoveControlnet", + "abyz22_ResizeOpenpose", + "abyz22_SaveImage", + "abyz22_SetQueue", + "abyz22_ToBasicPipe", + "abyz22_Topipe", + "abyz22_blend_onecolor", + "abyz22_blendimages", + "abyz22_bypass", + "abyz22_censoring", + "abyz22_drawmask", + "abyz22_lamaInpaint", + "abyz22_lamaPreprocessor", + "abyz22_makecircles", + "abyz22_setimageinfo", + "abyz22_smallhead" + ], + { + "title_aux": "image_control" + } + ], + "https://github.com/adbrasi/ComfyUI-TrashNodes-DownloadHuggingface": [ + [ + "DownloadLinkChecker", + "ShowFileNames" + ], + { + "title_aux": "ComfyUI-TrashNodes-DownloadHuggingface" + } + ], + "https://github.com/adieyal/comfyui-dynamicprompts": [ + [ + "DPCombinatorialGenerator", + "DPFeelingLucky", + "DPJinja", + "DPMagicPrompt", + "DPOutput", + "DPRandomGenerator" + ], + { + "title_aux": "DynamicPrompts Custom Nodes" + } + ], + "https://github.com/adigayung/ComfyUI-Translator": [ + [ + "CLIP Text Encode (Auto Translate)" + ], + { + "title_aux": "ComfyUI-Translator" + } + ], + "https://github.com/adriflex/ComfyUI_Blender_Texdiff": [ + [ + "ViewportColor", + "ViewportDepth" + ], + { + "title_aux": "ComfyUI_Blender_Texdiff" + } + ], + "https://github.com/aegis72/aegisflow_utility_nodes": [ + [ + "Add Text To Image", + "Aegisflow CLIP Pass", + "Aegisflow Conditioning Pass", + "Aegisflow Image Pass", + "Aegisflow Latent Pass", + "Aegisflow Mask Pass", + "Aegisflow Model Pass", + "Aegisflow Pos/Neg Pass", + "Aegisflow SDXL Tuple Pass", + "Aegisflow VAE Pass", + "Aegisflow controlnet preprocessor bus", + "Apply Instagram Filter", + "Binary INT Switch", + "Brightness_Contrast_Ally", + "Flatten Colors", + "Gaussian Blur_Ally", + "GlitchThis Effect", + "Hue Rotation", + "Image Flip_ally", + "Placeholder Tuple", + "Swap Color Mode", + "aegisflow Multi_Pass", + "aegisflow Multi_Pass XL", + "af_pipe_in_15", + "af_pipe_in_xl", + "af_pipe_out_15", + "af_pipe_out_xl" + ], + { + "title_aux": "AegisFlow Utility Nodes" + } + ], + "https://github.com/aegis72/comfyui-styles-all": [ + [ + "menus" + ], + { + "title_aux": "ComfyUI-styles-all" + } + ], + "https://github.com/ai-liam/comfyui-liam": [ + [ + "AiStoreAzureGPTLiam", + "GetBetterDepthImage", + "LiamLibDisplayText", + "LiamLibFillImage", + "LiamLibImageToGray", + "LiamLibLoadImage", + "LiamLibMergeText", + "LiamLibSaveImg", + "LiamLibSaveText", + "OllamaApiTNodeLiam", + "PreviewReliefImage", + "SpeechRecognitionLiam", + "SpeechSynthesisLiam" + ], + { + "title_aux": "LiamUtil" + } + ], + "https://github.com/ai-liam/comfyui_liam_util": [ + [ + "LiamLoadImage" + ], + { + "title_aux": "LiamUtil (single node)" + } + ], + "https://github.com/aianimation55/ComfyUI-FatLabels": [ + [ + "FatLabels" + ], + { + "title_aux": "Comfy UI FatLabels" + } + ], + "https://github.com/al-swaiti/ComfyUI-CascadeResolutions": [ + [ + "CascadeResolutions" + ], + { + "title_aux": "ComfyUI-CascadeResolutions" + } + ], + "https://github.com/alessandrozonta/ComfyUI-CenterNode": [ + [ + "BBoxCrop" + ], + { + "title_aux": "Bounding Box Crop Node for ComfyUI" + } + ], + "https://github.com/alessandrozonta/ComfyUI-Layers": [ + [ + "LayersSaver - Save Layer", + "LayersSaver - Save Layer From Images" + ], + { + "title_aux": "Save Layers Node for ComfyUI" + } + ], + "https://github.com/alessandrozonta/ComfyUI-OpenPose": [ + [ + "OpenPose - Get poses" + ], + { + "author": "joe", + "title_aux": "OpenPose Node" + } + ], + "https://github.com/alexopus/ComfyUI-Image-Saver": [ + [ + "Cfg Literal (Image Saver)", + "Checkpoint Loader with Name (Image Saver)", + "Float Literal (Image Saver)", + "Image Saver", + "Int Literal (Image Saver)", + "Sampler Selector (Image Saver)", + "Scheduler Selector (Comfy) (Image Saver)", + "Scheduler Selector (Image Saver)", + "SchedulerComfyToString (Image Saver)", + "SchedulerToString (Image Saver)", + "Seed Generator (Image Saver)", + "String Literal (Image Saver)", + "Width/Height Literal (Image Saver)" + ], + { + "title_aux": "ComfyUI Image Saver" + } + ], + "https://github.com/alisson-anjos/ComfyUI-Ollama-Describer": [ + [ + "InputText", + "OllamaImageDescriber", + "OllamaTextDescriber", + "ShowText", + "TextTransformer" + ], + { + "title_aux": "ComfyUI-Ollama-Describer" + } + ], + "https://github.com/alpertunga-bile/prompt-generator-comfyui": [ + [ + "Prompt Generator" + ], + { + "title_aux": "prompt-generator" + } + ], + "https://github.com/alsritter/asymmetric-tiling-comfyui": [ + [ + "Asymmetric_Tiling_KSampler" + ], + { + "title_aux": "asymmetric-tiling-comfyui" + } + ], + "https://github.com/alt-key-project/comfyui-dream-project": [ + [ + "Analyze Palette [Dream]", + "Beat Curve [Dream]", + "Big Float Switch [Dream]", + "Big Image Switch [Dream]", + "Big Int Switch [Dream]", + "Big Latent Switch [Dream]", + "Big Palette Switch [Dream]", + "Big Text Switch [Dream]", + "Boolean To Float [Dream]", + "Boolean To Int [Dream]", + "Build Prompt [Dream]", + "CSV Curve [Dream]", + "CSV Generator [Dream]", + "Calculation [Dream]", + "Common Frame Dimensions [Dream]", + "Compare Palettes [Dream]", + "FFMPEG Video Encoder [Dream]", + "File Count [Dream]", + "Finalize Prompt [Dream]", + "Float Input [Dream]", + "Float to Log Entry [Dream]", + "Frame Count Calculator [Dream]", + "Frame Counter (Directory) [Dream]", + "Frame Counter (Simple) [Dream]", + "Frame Counter Info [Dream]", + "Frame Counter Offset [Dream]", + "Frame Counter Time Offset [Dream]", + "Image Brightness Adjustment [Dream]", + "Image Color Shift [Dream]", + "Image Contrast Adjustment [Dream]", + "Image Motion [Dream]", + "Image Sequence Blend [Dream]", + "Image Sequence Loader [Dream]", + "Image Sequence Saver [Dream]", + "Image Sequence Tweening [Dream]", + "Int Input [Dream]", + "Int to Log Entry [Dream]", + "Laboratory [Dream]", + "Linear Curve [Dream]", + "Log Entry Joiner [Dream]", + "Log File [Dream]", + "Noise from Area Palettes [Dream]", + "Noise from Palette [Dream]", + "Palette Color Align [Dream]", + "Palette Color Shift [Dream]", + "Sample Image Area as Palette [Dream]", + "Sample Image as Palette [Dream]", + "Saw Curve [Dream]", + "Sine Curve [Dream]", + "Smooth Event Curve [Dream]", + "String Input [Dream]", + "String Tokenizer [Dream]", + "String to Log Entry [Dream]", + "Text Input [Dream]", + "Triangle Curve [Dream]", + "Triangle Event Curve [Dream]", + "WAV Curve [Dream]" + ], + { + "title_aux": "Dream Project Animation Nodes" + } + ], + "https://github.com/alt-key-project/comfyui-dream-video-batches": [ + [ + "Blended Transition [DVB]", + "Calculation [DVB]", + "Create Frame Set [DVB]", + "Divide [DVB]", + "Fade From Black [DVB]", + "Fade To Black [DVB]", + "Float Input [DVB]", + "For Each Done [DVB]", + "For Each Filename [DVB]", + "Frame Set Append [DVB]", + "Frame Set Frame Dimensions Scaled [DVB]", + "Frame Set Index Offset [DVB]", + "Frame Set Merger [DVB]", + "Frame Set Reindex [DVB]", + "Frame Set Repeat [DVB]", + "Frame Set Reverse [DVB]", + "Frame Set Split Beginning [DVB]", + "Frame Set Split End [DVB]", + "Frame Set Splitter [DVB]", + "Generate Inbetween Frames [DVB]", + "Int Input [DVB]", + "Linear Camera Pan [DVB]", + "Linear Camera Roll [DVB]", + "Linear Camera Zoom [DVB]", + "Load Image From Path [DVB]", + "Multiply [DVB]", + "Sine Camera Pan [DVB]", + "Sine Camera Roll [DVB]", + "Sine Camera Zoom [DVB]", + "String Input [DVB]", + "Text Input [DVB]", + "Trace Memory Allocation [DVB]", + "Unwrap Frame Set [DVB]" + ], + { + "title_aux": "Dream Video Batches" + } + ], + "https://github.com/an90ray/ComfyUI_RErouter_CustomNodes": [ + [ + "CLIPTextEncode (RE)", + "CLIPTextEncodeSDXL (RE)", + "CLIPTextEncodeSDXLRefiner (RE)", + "Int (RE)", + "RErouter <=", + "RErouter =>", + "String (RE)" + ], + { + "title_aux": "ComfyUI_RErouter_CustomNodes" + } + ], + "https://github.com/andersxa/comfyui-PromptAttention": [ + [ + "CLIPAttentionMaskEncode" + ], + { + "title_aux": "CLIP Directional Prompt Attention" + } + ], + "https://github.com/angeloshredder/StableCascadeResizer": [ + [ + "CascadeResize" + ], + { + "title_aux": "StableCascadeResizer" + } + ], + "https://github.com/ansonkao/comfyui-geometry": [ + [ + "TransformTemplateOntoFaceMask" + ], + { + "author": "Anson Kao", + "description": "A small collection of custom nodes for use with ComfyUI, by Discopixel", + "nickname": "ComfyUI Discopixel", + "title": "ComfyUI Discopixel", + "title_aux": "comfyui-geometry" + } + ], + "https://github.com/antrobot1234/antrobots-comfyUI-nodepack": [ + [ + "composite", + "crop", + "paste", + "preview_mask", + "scale" + ], + { + "title_aux": "antrobots ComfyUI Nodepack" + } + ], + "https://github.com/asagi4/ComfyUI-Adaptive-Guidance": [ + [ + "AdaptiveGuidance" + ], + { + "title_aux": "Adaptive Guidance for ComfyUI" + } + ], + "https://github.com/asagi4/ComfyUI-CADS": [ + [ + "CADS" + ], + { + "title_aux": "ComfyUI-CADS" + } + ], + "https://github.com/asagi4/comfyui-prompt-control": [ + [ + "EditableCLIPEncode", + "FilterSchedule", + "LoRAScheduler", + "PCApplySettings", + "PCPromptFromSchedule", + "PCScheduleAddMasks", + "PCScheduleSettings", + "PCSplitSampling", + "PCWrapGuider", + "PromptControlSimple", + "PromptToSchedule", + "ScheduleToCond", + "ScheduleToModel" + ], + { + "title_aux": "ComfyUI prompt control" + } + ], + "https://github.com/asagi4/comfyui-utility-nodes": [ + [ + "MUForceCacheClear", + "MUJinjaRender", + "MUReplaceModelWeights", + "MUSimpleWildcard" + ], + { + "title_aux": "asagi4/comfyui-utility-nodes" + } + ], + "https://github.com/aszc-dev/ComfyUI-CoreMLSuite": [ + [ + "Core ML Converter", + "Core ML LCM Converter", + "Core ML LoRA Loader", + "CoreMLModelAdapter", + "CoreMLSampler", + "CoreMLSamplerAdvanced", + "CoreMLUNetLoader" + ], + { + "title_aux": "Core ML Suite for ComfyUI" + } + ], + "https://github.com/audioscavenger/ComfyUI-Thumbnails": [ + [ + "LoadImageThumbnails" + ], + { + "author": "AudioscavengeR", + "description": "Load Image thumbnails and show input subfolders.", + "nickname": "ComfyUI Thumbnails", + "title": "ComfyUI Thumbnails", + "title_aux": "ComfyUI Thumbnails" + } + ], + "https://github.com/audioscavenger/save-image-extended-comfyui": [ + [ + "SaveImageExtended" + ], + { + "title_aux": "Save Image Extended for ComfyUI" + } + ], + "https://github.com/avatechai/avatar-graph-comfyui": [ + [ + "ApplyMeshTransformAsShapeKey", + "B_ENUM", + "B_VECTOR3", + "B_VECTOR4", + "Combine Points", + "CreateShapeFlow", + "ExportBlendshapes", + "ExportGLTF", + "Extract Boundary Points", + "Image Alpha Mask Merge", + "ImageBridge", + "LoadImageFromRequest", + "LoadImageWithAlpha", + "LoadValueFromRequest", + "SAM MultiLayer", + "Save Image With Workflow" + ], + { + "author": "Avatech Limited", + "description": "Include nodes for sam + bpy operation, that allows workflow creations for generative 2d character rig.", + "nickname": "Avatar Graph", + "title": "Avatar Graph", + "title_aux": "Avatar Graph" + } + ], + "https://github.com/aws-samples/comfyui-llm-node-for-amazon-bedrock": [ + [ + "Bedrock - Claude", + "Bedrock - Claude Multimodal", + "Bedrock - SDXL", + "Bedrock - Titan Inpainting", + "Bedrock - Titan Outpainting", + "Bedrock - Titan Text to Image", + "Bedrock - Titan Variation", + "Image From S3", + "Image From URL", + "Image To S3", + "Prompt Regex Remove", + "Prompt Template" + ], + { + "title_aux": "Amazon Bedrock nodes for ComfyUI" + } + ], + "https://github.com/azure-dragon-ai/ComfyUI-ClipScore-Nodes": [ + [ + "HaojihuiClipScoreFakeImageProcessor", + "HaojihuiClipScoreImageProcessor", + "HaojihuiClipScoreImageScore", + "HaojihuiClipScoreLoader", + "HaojihuiClipScoreRealImageProcessor", + "HaojihuiClipScoreTextProcessor" + ], + { + "title_aux": "ComfyUI-ClipScore-Nodes" + } + ], + "https://github.com/badayvedat/ComfyUI-fal-Connector": [ + [ + "RemoteCheckpointLoader_fal", + "RemoteLoraLoader_fal" + ], + { + "title_aux": "ComfyUI-fal-Connector" + } + ], + "https://github.com/badjeff/comfyui_lora_tag_loader": [ + [ + "LoraTagLoader" + ], + { + "title_aux": "LoRA Tag Loader for ComfyUI" + } + ], + "https://github.com/baicai99/ComfyUI-FrameSkipping": [ + [ + "FrameSelector", + "FrameSkipping", + "FrameTruncating", + "IntOperationsNode", + "MaskFrameSkipping", + "MaskGenerator", + "MaskSelector" + ], + { + "title_aux": "ComfyUI-FrameSkipping" + } + ], + "https://github.com/banodoco/steerable-motion": [ + [ + "BatchCreativeInterpolation", + "IpaConfiguration", + "RemoveAndInterpolateFrames" + ], + { + "title_aux": "Steerable Motion" + } + ], + "https://github.com/barckley75/comfyUI_DaVinciResolve/raw/main/custom_nodes/node_text_to_speech.py": [ + [ + "TextToSpeech" + ], + { + "title_aux": "comfyUI_DaVinciResolve" + } + ], + "https://github.com/bash-j/mikey_nodes": [ + [ + "AddMetaData", + "Batch Crop Image", + "Batch Crop Resize Inplace", + "Batch Load Images", + "Batch Resize Image for SDXL", + "Checkpoint Loader Simple Mikey", + "CheckpointHash", + "CinematicLook", + "Empty Latent Ratio Custom SDXL", + "Empty Latent Ratio Select SDXL", + "EvalFloats", + "FaceFixerOpenCV", + "FileNamePrefix", + "FileNamePrefixDateDirFirst", + "Float to String", + "GetSubdirectories", + "HaldCLUT", + "Image Caption", + "ImageBorder", + "ImageOverlay", + "ImagePaste", + "Int to String", + "LMStudioPrompt", + "Load Image Based on Number", + "LoraSyntaxProcessor", + "Mikey Sampler", + "Mikey Sampler Base Only", + "Mikey Sampler Base Only Advanced", + "Mikey Sampler Tiled", + "Mikey Sampler Tiled Base Only", + "MikeyLatentTileSampler", + "MikeyLatentTileSamplerCustom", + "MikeySamplerTiledAdvanced", + "MikeySamplerTiledAdvancedBaseOnly", + "MosaicExpandImage", + "OobaPrompt", + "PresetRatioSelector", + "Prompt With SDXL", + "Prompt With Style", + "Prompt With Style V2", + "Prompt With Style V3", + "Range Float", + "Range Integer", + "Ratio Advanced", + "Resize Image for SDXL", + "SD3TextConditioningWithOptionsOnePrompt", + "SRFloatPromptInput", + "SRIntPromptInput", + "SRStringPromptInput", + "Save Image If True", + "Save Image With Prompt Data", + "Save Images Mikey", + "Save Images No Display", + "SaveMetaData", + "SearchAndReplace", + "Seed String", + "Style Conditioner", + "Style Conditioner Base Only", + "Text2InputOr3rdOption", + "TextCombinations", + "TextCombinations3", + "TextConcat", + "TextPadderMikey", + "TextPreserve", + "Upscale Tile Calculator", + "Wildcard Processor", + "WildcardAndLoraSyntaxProcessor", + "WildcardOobaPrompt" + ], + { + "title_aux": "Mikey Nodes" + } + ], + "https://github.com/bedovyy/ComfyUI_NAIDGenerator": [ + [ + "GenerateNAID", + "Img2ImgOptionNAID", + "InpaintingOptionNAID", + "MaskImageToNAID", + "ModelOptionNAID", + "PromptToNAID", + "VibeTransferOptionNAID" + ], + { + "title_aux": "ComfyUI_NAIDGenerator" + } + ], + "https://github.com/bilal-arikan/ComfyUI_TextAssets": [ + [ + "LoadTextAsset" + ], + { + "title_aux": "ComfyUI_TextAssets" + } + ], + "https://github.com/bitaffinity/ComfyUI_HF_Inference": [ + [ + "Classification", + "FeatureExtraction", + "Generation", + "ObjectDetection", + "QuestionAnswering", + "Segmentation", + "TextToImage", + "Translation" + ], + { + "title_aux": "ComfyUI_HF_Inference" + } + ], + "https://github.com/bkunbargi/BrevImage/raw/main/BrevLoadImage.py": [ + [ + "BrevImage" + ], + { + "title_aux": "BrevImage" + } + ], + "https://github.com/blepping/ComfyUI-bleh": [ + [ + "BlehBlockOps", + "BlehDeepShrink", + "BlehDisableNoise", + "BlehDiscardPenultimateSigma", + "BlehForceSeedSampler", + "BlehHyperTile", + "BlehInsaneChainSampler", + "BlehLatentOps", + "BlehLatentScaleBy", + "BlehModelPatchConditional", + "BlehPlug", + "BlehRefinerAfter" + ], + { + "title_aux": "ComfyUI-bleh" + } + ], + "https://github.com/blepping/ComfyUI-sonar": [ + [ + "NoisyLatentLike", + "SamplerConfigOverride", + "SamplerSonarDPMPPSDE", + "SamplerSonarEuler", + "SamplerSonarEulerA", + "SonarCompositeNoise", + "SonarCustomNoise", + "SonarGuidanceConfig", + "SonarGuidedNoise", + "SonarModulatedNoise", + "SonarRandomNoise", + "SonarRepeatedNoise", + "SonarScheduledNoise" + ], + { + "title_aux": "ComfyUI-sonar" + } + ], + "https://github.com/blepping/comfyui_jankhidiffusion": [ + [ + "ApplyMSWMSAAttention", + "ApplyMSWMSAAttentionSimple", + "ApplyRAUNet", + "ApplyRAUNetSimple" + ], + { + "title_aux": "ComfyUI jank HiDiffusion" + } + ], + "https://github.com/blueraincoatli/comfyUI_SillyNodes": [ + [ + "BooleanJumper|SillyNode", + "QueueSequence|SillyNode", + "Screenshots|SillyNode", + "dummyInput|SillyNode", + "dummyInput|blueraincoat" + ], + { + "title_aux": "comfyUI_SillyNodes" + } + ], + "https://github.com/bluevisor/ComfyUI_PS_Blend_Node": [ + [ + "PSBlendNode" + ], + { + "title_aux": "ComfyUI_PS_Blend_Node" + } + ], + "https://github.com/bmad4ever/comfyui_ab_samplercustom": [ + [ + "AB SamplerCustom (experimental)" + ], + { + "title_aux": "comfyui_ab_sampler" + } + ], + "https://github.com/bmad4ever/comfyui_bmad_nodes": [ + [ + "AdaptiveThresholding", + "Add String To Many", + "AddAlpha", + "AdjustRect", + "AnyToAny", + "BoundingRect (contours)", + "BuildColorRangeAdvanced (hsv)", + "BuildColorRangeHSV (hsv)", + "CLAHE", + "CLIPEncodeMultiple", + "CLIPEncodeMultipleAdvanced", + "ChameleonMask", + "CheckpointLoader (dirty)", + "CheckpointLoaderSimple (dirty)", + "Color (RGB)", + "Color (hexadecimal)", + "Color Clip", + "Color Clip (advanced)", + "Color Clip ADE20k", + "ColorDictionary", + "ColorDictionary (custom)", + "Conditioning (combine multiple)", + "Conditioning (combine selective)", + "Conditioning Grid (cond)", + "Conditioning Grid (string)", + "Conditioning Grid (string) Advanced", + "Contour To Mask", + "Contours", + "ControlNetHadamard", + "ControlNetHadamard (manual)", + "ConvertImg", + "CopyMakeBorder", + "CreateRequestMetadata", + "DistanceTransform", + "Draw Contour(s)", + "EqualizeHistogram", + "ExtendColorList", + "ExtendCondList", + "ExtendFloatList", + "ExtendImageList", + "ExtendIntList", + "ExtendLatentList", + "ExtendMaskList", + "ExtendModelList", + "ExtendStringList", + "FadeMaskEdges", + "Filter Contour", + "FindComplementaryColor", + "FindThreshold", + "FlatLatentsIntoSingleGrid", + "Framed Mask Grab Cut", + "Framed Mask Grab Cut 2", + "FromListGet1Color", + "FromListGet1Cond", + "FromListGet1Float", + "FromListGet1Image", + "FromListGet1Int", + "FromListGet1Latent", + "FromListGet1Mask", + "FromListGet1Model", + "FromListGet1String", + "FromListGetColors", + "FromListGetConds", + "FromListGetFloats", + "FromListGetImages", + "FromListGetInts", + "FromListGetLatents", + "FromListGetMasks", + "FromListGetModels", + "FromListGetStrings", + "Get Contour from list", + "Get Models", + "Get Prompt", + "HypernetworkLoader (dirty)", + "ImageBatchToList", + "InRange (hsv)", + "Inpaint", + "Input/String to Int Array", + "KMeansColor", + "Load 64 Encoded Image", + "LoraLoader (dirty)", + "MaskGrid N KSamplers Advanced", + "MaskOuterBlur", + "Merge Latent Batch Gridwise", + "MonoMerge", + "MorphologicOperation", + "MorphologicSkeletoning", + "NaiveAutoKMeansColor", + "OtsuThreshold", + "RGB to HSV", + "Rect Grab Cut", + "Remap", + "RemapBarrelDistortion", + "RemapFromInsideParabolas", + "RemapFromQuadrilateral (homography)", + "RemapInsideParabolas", + "RemapInsideParabolasAdvanced", + "RemapPinch", + "RemapReverseBarrelDistortion", + "RemapStretch", + "RemapToInnerCylinder", + "RemapToOuterCylinder", + "RemapToQuadrilateral", + "RemapWarpPolar", + "Repeat Into Grid (image)", + "Repeat Into Grid (latent)", + "RequestInputs", + "SampleColorHSV", + "Save Image (api)", + "SeamlessClone", + "SeamlessClone (simple)", + "SetRequestStateToComplete", + "String", + "String to Float", + "String to Integer", + "ToColorList", + "ToCondList", + "ToFloatList", + "ToImageList", + "ToIntList", + "ToLatentList", + "ToMaskList", + "ToModelList", + "ToStringList", + "UnGridify (image)", + "VAEEncodeBatch" + ], + { + "title_aux": "Bmad Nodes" + } + ], + "https://github.com/bmad4ever/comfyui_lists_cartesian_product": [ + [ + "AnyListCartesianProduct" + ], + { + "title_aux": "Lists Cartesian Product" + } + ], + "https://github.com/bmad4ever/comfyui_quilting": [ + [ + "ImageQuilting_Bmad", + "LatentQuilting_Bmad" + ], + { + "title_aux": "comfyui_quilting" + } + ], + "https://github.com/bmad4ever/comfyui_wfc_like": [ + [ + "WFC_CustomTemperature_Bmad", + "WFC_CustomValueWeights_Bmad", + "WFC_Decode_BMad", + "WFC_EmptyState_Bmad", + "WFC_Encode_BMad", + "WFC_Filter_Bmad", + "WFC_GenParallel_Bmad", + "WFC_Generate_BMad", + "WFC_SampleNode_BMad" + ], + { + "title_aux": "comfyui_wfc_like" + } + ], + "https://github.com/bobmagicii/comfykit-custom-nodes": [ + [ + "LoraThree", + "LoraWithMeta", + "TypecasterImage", + "TypecasterLatent" + ], + { + "title_aux": "ComfyKit Custom Nodes" + } + ], + "https://github.com/bradsec/ComfyUI_ResolutionSelector": [ + [ + "ResolutionSelector" + ], + { + "title_aux": "ResolutionSelector for ComfyUI" + } + ], + "https://github.com/bradsec/ComfyUI_StringTools": [ + [ + "ModifyStringNode", + "RandomStringNode", + "ReplaceStringNode", + "ShowStringNode", + "TextStringNode" + ], + { + "title_aux": "ComfyUI_StringTools" + } + ], + "https://github.com/braintacles/braintacles-comfyui-nodes": [ + [ + "CLIPTextEncodeSDXL-Multi-IO", + "CLIPTextEncodeSDXL-Pipe", + "Empty Latent Image from Aspect-Ratio", + "Interval Sampler", + "Random Find and Replace" + ], + { + "title_aux": "braintacles-nodes" + } + ], + "https://github.com/brianfitzgerald/style_aligned_comfy": [ + [ + "StyleAlignedBatchAlign", + "StyleAlignedReferenceSampler", + "StyleAlignedSampleReferenceLatents" + ], + { + "title_aux": "StyleAligned for ComfyUI" + } + ], + "https://github.com/bronkula/comfyui-fitsize": [ + [ + "FS: Crop Image Into Even Pieces", + "FS: Fit Image And Resize", + "FS: Fit Size From Image", + "FS: Fit Size From Int", + "FS: Image Region To Mask", + "FS: Load Image And Resize To Fit", + "FS: Pick Image From Batch", + "FS: Pick Image From Batches", + "FS: Pick Image From List" + ], + { + "title_aux": "comfyui-fitsize" + } + ], + "https://github.com/bruefire/ComfyUI-SeqImageLoader": [ + [ + "VFrame Loader With Mask Editor", + "Video Loader With Mask Editor" + ], + { + "title_aux": "ComfyUI Sequential Image Loader" + } + ], + "https://github.com/budihartono/comfyui_otonx_nodes": [ + [ + "OTX Integer Multiple Inputs 4", + "OTX Integer Multiple Inputs 5", + "OTX Integer Multiple Inputs 6", + "OTX KSampler Feeder", + "OTX Versatile Multiple Inputs 4", + "OTX Versatile Multiple Inputs 5", + "OTX Versatile Multiple Inputs 6" + ], + { + "title_aux": "Otonx's Custom Nodes" + } + ], + "https://github.com/bvhari/ComfyUI_ImageProcessing": [ + [ + "BilateralFilter", + "Brightness", + "Gamma", + "Hue", + "Saturation", + "SigmoidCorrection", + "UnsharpMask" + ], + { + "title_aux": "ImageProcessing" + } + ], + "https://github.com/bvhari/ComfyUI_PerpWeight": [ + [ + "CLIPTextEncodePerpWeight" + ], + { + "title_aux": "ComfyUI_PerpWeight" + } + ], + "https://github.com/bvhari/ComfyUI_SUNoise": [ + [ + "SUNoiseLatent", + "SamplerDPM2Ancestral_SUN", + "SamplerDPMPP2SAncestral_SUN", + "SamplerDPMPP_2M_SDE_SUN", + "SamplerDPMPP_3M_SDE_SUN", + "SamplerDPMPP_SDE_SUN", + "SamplerEulerAncestralCFGpp_SUN", + "SamplerEulerAncestral_SUN", + "SamplersSUNoise", + "SamplersSUNoiseAdvanced" + ], + { + "title_aux": "ComfyUI_SUNoise" + } + ], + "https://github.com/catscandrive/comfyui-imagesubfolders/raw/main/loadImageWithSubfolders.py": [ + [ + "LoadImagewithSubfolders" + ], + { + "title_aux": "Image loader with subfolders" + } + ], + "https://github.com/cdb-boop/ComfyUI-Bringing-Old-Photos-Back-to-Life": [ + [ + "BOPBTL_BlendFaces", + "BOPBTL_DetectEnhanceBlendFaces", + "BOPBTL_DetectFaces", + "BOPBTL_EnhanceFaces", + "BOPBTL_EnhanceFacesAdvanced", + "BOPBTL_LoadFaceDetectorModel", + "BOPBTL_LoadFaceEnhancerModel", + "BOPBTL_LoadRestoreOldPhotosModel", + "BOPBTL_LoadScratchMaskModel", + "BOPBTL_RestoreOldPhotos", + "BOPBTL_ScratchMask" + ], + { + "title_aux": "ComfyUI Bringing Old Photos Back to Life" + } + ], + "https://github.com/cdb-boop/comfyui-image-round": [ + [ + "ComfyUI_Image_Round__ImageCropAdvanced", + "ComfyUI_Image_Round__ImageRound", + "ComfyUI_Image_Round__ImageRoundAdvanced" + ], + { + "title_aux": "comfyui-image-round" + } + ], + "https://github.com/celsojr2013/comfyui_jamworks_client": [ + [ + "Jamworks_Download", + "Jamworks_Login", + "Shell_Command" + ], + { + "title_aux": "comfyui_jamworks_client" + } + ], + "https://github.com/celsojr2013/comfyui_simpletools": [ + [ + "GoogleTranslator", + "Parameters", + "ResolutionSolver" + ], + { + "title_aux": "ComfyUI SimpleTools Suit" + } + ], + "https://github.com/cerspense/ComfyUI_cspnodes": [ + [ + "ImageDirIterator", + "Modelscopet2v", + "Modelscopev2v", + "RemapRange", + "SplitImageChannels", + "TextFileLineIterator", + "VidDirIterator" + ], + { + "title_aux": "cspnodes" + } + ], + "https://github.com/ceruleandeep/ComfyUI-LLaVA-Captioner": [ + [ + "LlavaCaptioner" + ], + { + "title_aux": "ComfyUI LLaVA Captioner" + } + ], + "https://github.com/chakib-belgaid/ComfyUI-autosize": [ + [ + "CustomAutoSize", + "SDXLAutoSize" + ], + { + "title_aux": "ComfyUI-autosize" + } + ], + "https://github.com/chakib-belgaid/Comfyui_Prompt_styler": [ + [ + "Prompt_Styler" + ], + { + "title_aux": "ComfyUI Style Plugin" + } + ], + "https://github.com/chandlergis/ComfyUI-IMG_Query": [ + [ + "ImageRequestNode" + ], + { + "title_aux": "ComfyUI-IMG_Query" + } + ], + "https://github.com/chandlergis/ComfyUI_EmojiOverlay": [ + [ + "Image Emoji Overlay" + ], + { + "title_aux": "ComfyUI_EmojiOverlay" + } + ], + "https://github.com/chaojie/ComfyUI-AniPortrait": [ + [ + "AniPortraitLoader", + "AniPortraitRun", + "Box2Video", + "CoverVideo", + "MaskList2Video" + ], + { + "title_aux": "ComfyUI-AniPortrait" + } + ], + "https://github.com/chaojie/ComfyUI-CameraCtrl-Wrapper": [ + [ + "CameraBasic", + "CameraCombine", + "CameraCtrlLoader", + "CameraCtrlRun", + "CameraJoin", + "CameraTrajectory" + ], + { + "title_aux": "ComfyUI-CameraCtrl-Wrapper" + } + ], + "https://github.com/chaojie/ComfyUI-Champ": [ + [ + "ChampLoader", + "ChampRun", + "ImageCombineOneColumn", + "ImageCombineOneRow" + ], + { + "title_aux": "ComfyUI-Champ" + } + ], + "https://github.com/chaojie/ComfyUI-DragAnything": [ + [ + "DragAnythingLoader", + "DragAnythingPipelineRun", + "DragAnythingPipelineRunRandom", + "DragAnythingRun", + "DragAnythingRunRandom", + "LoadText", + "SaveText", + "VHS_FILENAMES_STRING" + ], + { + "title_aux": "ComfyUI-DragAnything" + } + ], + "https://github.com/chaojie/ComfyUI-DragNUWA": [ + [ + "BrushMotion", + "CompositeMotionBrush", + "CompositeMotionBrushWithoutModel", + "DragNUWA Run", + "DragNUWA Run MotionBrush", + "Get First Image", + "Get Last Image", + "InstantCameraMotionBrush", + "InstantObjectMotionBrush", + "Load CheckPoint DragNUWA", + "Load MotionBrush From Optical Flow", + "Load MotionBrush From Optical Flow Directory", + "Load MotionBrush From Optical Flow Without Model", + "Load MotionBrush From Tracking Points", + "Load MotionBrush From Tracking Points Without Model", + "Load Pose KeyPoints", + "Loop", + "LoopEnd_IMAGE", + "LoopStart_IMAGE", + "Split Tracking Points" + ], + { + "title_aux": "ComfyUI-DragNUWA" + } + ], + "https://github.com/chaojie/ComfyUI-DynamiCrafter": [ + [ + "DynamiCrafter Simple", + "DynamiCrafterInterp Simple", + "DynamiCrafterInterpLoader", + "DynamiCrafterLoader" + ], + { + "title_aux": "ComfyUI-DynamiCrafter" + } + ], + "https://github.com/chaojie/ComfyUI-EasyAnimate": [ + [ + "EasyAnimateLoader", + "EasyAnimateRun" + ], + { + "title_aux": "ComfyUI-EasyAnimate" + } + ], + "https://github.com/chaojie/ComfyUI-Gemma": [ + [ + "GemmaLoader", + "GemmaRun" + ], + { + "title_aux": "ComfyUI-Gemma" + } + ], + "https://github.com/chaojie/ComfyUI-I2VGEN-XL": [ + [ + "I2VGEN-XL Simple", + "Modelscope Pipeline Loader" + ], + { + "title_aux": "ComfyUI-I2VGEN-XL" + } + ], + "https://github.com/chaojie/ComfyUI-Img2Img-Turbo": [ + [ + "Img2ImgTurboEdgeLoader", + "Img2ImgTurboEdgeRun", + "Img2ImgTurboSketchLoader", + "Img2ImgTurboSketchRun" + ], + { + "title_aux": "ComfyUI-Img2Img-Turbo" + } + ], + "https://github.com/chaojie/ComfyUI-LaVIT": [ + [ + "VHS_FILENAMES_STRING_LaVIT", + "VideoLaVITI2I", + "VideoLaVITI2V", + "VideoLaVITI2VLong", + "VideoLaVITLoader", + "VideoLaVITT2V", + "VideoLaVITT2VLong", + "VideoLaVITUnderstandingImage", + "VideoLaVITUnderstandingLoader", + "VideoLaVITUnderstandingVideo", + "VideoLaVITVideoDetokenizerLoader", + "VideoLaVITVideoReconstruction" + ], + { + "title_aux": "ComfyUI-LaVIT" + } + ], + "https://github.com/chaojie/ComfyUI-LightGlue": [ + [ + "LightGlue Loader", + "LightGlue Simple", + "LightGlue Simple Multi" + ], + { + "title_aux": "ComfyUI-LightGlue" + } + ], + "https://github.com/chaojie/ComfyUI-Moore-AnimateAnyone": [ + [ + "Moore-AnimateAnyone Denoising Unet", + "Moore-AnimateAnyone Image Encoder", + "Moore-AnimateAnyone Pipeline Loader", + "Moore-AnimateAnyone Pose Guider", + "Moore-AnimateAnyone Reference Unet", + "Moore-AnimateAnyone Simple", + "Moore-AnimateAnyone VAE" + ], + { + "title_aux": "ComfyUI-Moore-AnimateAnyone" + } + ], + "https://github.com/chaojie/ComfyUI-Motion-Vector-Extractor": [ + [ + "Motion Vector Extractor", + "VideoCombineThenPath" + ], + { + "title_aux": "ComfyUI-Motion-Vector-Extractor" + } + ], + "https://github.com/chaojie/ComfyUI-MotionCtrl": [ + [ + "Load Motion Camera Preset", + "Load Motion Traj Preset", + "Load Motionctrl Checkpoint", + "Motionctrl Cond", + "Motionctrl Sample", + "Motionctrl Sample Simple", + "Select Image Indices" + ], + { + "title_aux": "ComfyUI-MotionCtrl" + } + ], + "https://github.com/chaojie/ComfyUI-MotionCtrl-SVD": [ + [ + "Load Motionctrl-SVD Camera Preset", + "Load Motionctrl-SVD Checkpoint", + "Motionctrl-SVD Sample Simple" + ], + { + "title_aux": "ComfyUI-MotionCtrl-SVD" + } + ], + "https://github.com/chaojie/ComfyUI-MuseTalk": [ + [ + "MuseTalkCupAudio", + "MuseTalkRun", + "VHS_FILENAMES_STRING_MuseTalk" + ], + { + "title_aux": "ComfyUI-MuseTalk" + } + ], + "https://github.com/chaojie/ComfyUI-MuseV": [ + [ + "MuseVRun", + "MuseVRunVid2Vid", + "VHS_FILENAMES_STRING_MuseV" + ], + { + "author": "infguo", + "title_aux": "ComfyUI-MuseV" + } + ], + "https://github.com/chaojie/ComfyUI-Open-Sora": [ + [ + "OpenSoraLoader", + "OpenSoraRun", + "OpenSoraSampler" + ], + { + "title_aux": "ComfyUI-Open-Sora" + } + ], + "https://github.com/chaojie/ComfyUI-Open-Sora-Plan": [ + [ + "OpenSoraPlanDecode", + "OpenSoraPlanLoader", + "OpenSoraPlanRun", + "OpenSoraPlanSample" + ], + { + "title_aux": "ComfyUI-Open-Sora-Plan" + } + ], + "https://github.com/chaojie/ComfyUI-Panda3d": [ + [ + "Panda3dAmbientLight", + "Panda3dAttachNewNode", + "Panda3dBase", + "Panda3dDirectionalLight", + "Panda3dLoadDepthModel", + "Panda3dLoadModel", + "Panda3dLoadTexture", + "Panda3dModelMerge", + "Panda3dTest", + "Panda3dTextureMerge" + ], + { + "title_aux": "ComfyUI-Panda3d" + } + ], + "https://github.com/chaojie/ComfyUI-Pymunk": [ + [ + "PygameRun", + "PygameSurface", + "PymunkDynamicBox", + "PymunkDynamicCircle", + "PymunkRun", + "PymunkShapeMerge", + "PymunkSpace", + "PymunkStaticLine" + ], + { + "title_aux": "ComfyUI-Pymunk" + } + ], + "https://github.com/chaojie/ComfyUI-RAFT": [ + [ + "Load MotionBrush", + "RAFT Run", + "Save MotionBrush", + "VizMotionBrush" + ], + { + "title_aux": "ComfyUI-RAFT" + } + ], + "https://github.com/chaojie/ComfyUI-SimDA": [ + [ + "SimDALoader", + "SimDARun", + "SimDATrain", + "VHS_FILENAMES_STRING_SimDA" + ], + { + "title_aux": "ComfyUI-SimDA" + } + ], + "https://github.com/chaojie/ComfyUI-Trajectory": [ + [ + "Trajectory_Canvas_Tab" + ], + { + "author": "Lerc", + "description": "This extension provides a full page image editor with mask support. There are two nodes, one to receive images from the editor and one to send images to the editor.", + "nickname": "Canvas Tab", + "title": "Canvas Tab", + "title_aux": "ComfyUI-Trajectory" + } + ], + "https://github.com/chaojie/ComfyUI-Video-Editing-X-Attention": [ + [ + "StringList", + "VEXAGuidance", + "VEXALoader", + "VEXARun" + ], + { + "title_aux": "ComfyUI-Video-Editing-X-Attention" + } + ], + "https://github.com/chaojie/ComfyUI-dust3r": [ + [ + "CameraPoseVideo", + "Dust3rLoader", + "Dust3rRun" + ], + { + "title_aux": "ComfyUI-dust3r" + } + ], + "https://github.com/chaojie/ComfyUI_StreamingT2V": [ + [ + "LoadText_StreamingT2V", + "PromptTravelIndex", + "SaveText_StreamingT2V", + "StreamingT2VLoaderAnimateDiff", + "StreamingT2VLoaderAnimateDiffModel", + "StreamingT2VLoaderEnhanceModel", + "StreamingT2VLoaderModelscopeModel", + "StreamingT2VLoaderModelscopeT2V", + "StreamingT2VLoaderSVD", + "StreamingT2VLoaderSVDModel", + "StreamingT2VLoaderStreamModel", + "StreamingT2VLoaderVidXTendModel", + "StreamingT2VRunEnhanceStep", + "StreamingT2VRunI2V", + "StreamingT2VRunLongStep", + "StreamingT2VRunLongStepVidXTendPipeline", + "StreamingT2VRunLongStepVidXTendPipelineCustomRef", + "StreamingT2VRunLongStepVidXTendPipelineCustomRefOutExtendOnly", + "StreamingT2VRunLongStepVidXTendPipelinePromptTravel", + "StreamingT2VRunShortStepAnimateDiff", + "StreamingT2VRunShortStepModelscopeT2V", + "StreamingT2VRunShortStepSVD", + "StreamingT2VRunT2V", + "VHS_FILENAMES_STRING_StreamingT2V" + ], + { + "title_aux": "ComfyUI_StreamingT2V" + } + ], + "https://github.com/chaosaiart/Chaosaiart-Nodes": [ + [ + "chaosaiart_Any_Switch", + "chaosaiart_Any_Switch_Big_Number", + "chaosaiart_Any_Switch_small", + "chaosaiart_CheckpointLoader", + "chaosaiart_CheckpointPrompt", + "chaosaiart_CheckpointPrompt2", + "chaosaiart_CheckpointPrompt_Frame", + "chaosaiart_CheckpointPrompt_FrameMixer", + "chaosaiart_ControlNetApply", + "chaosaiart_ControlNetApply2", + "chaosaiart_ControlNetApply3", + "chaosaiart_Denoising_Switch", + "chaosaiart_EmptyLatentImage", + "chaosaiart_FramePromptCLIPEncode", + "chaosaiart_Frame_Switch", + "chaosaiart_KSampler1", + "chaosaiart_KSampler2", + "chaosaiart_KSampler3", + "chaosaiart_KSampler4", + "chaosaiart_KSampler5", + "chaosaiart_KSampler7", + "chaosaiart_KSampler_a1", + "chaosaiart_KSampler_a1a", + "chaosaiart_KSampler_a2", + "chaosaiart_KSampler_expert_0", + "chaosaiart_KSampler_expert_1", + "chaosaiart_Ksampler_attribut", + "chaosaiart_Load_Image_Batch", + "chaosaiart_Load_Image_Batch_2img", + "chaosaiart_MainPromptCLIPEncode", + "chaosaiart_Number", + "chaosaiart_Number2", + "chaosaiart_Number_Counter", + "chaosaiart_Number_Switch", + "chaosaiart_Prompt", + "chaosaiart_Prompt_Frame", + "chaosaiart_Prompt_mixer_byFrame", + "chaosaiart_SaveImage", + "chaosaiart_Show_Info", + "chaosaiart_Simple_Prompt", + "chaosaiart_Style_Node", + "chaosaiart_TextCLIPEncode", + "chaosaiart_TextCLIPEncode_lora", + "chaosaiart_adjust_color", + "chaosaiart_any_array2input_1Input", + "chaosaiart_any_array2input_all_big", + "chaosaiart_any_array2input_all_small", + "chaosaiart_any_input2array_big", + "chaosaiart_any_input2array_small", + "chaosaiart_controlnet_weidgth", + "chaosaiart_convert", + "chaosaiart_convert_Prompt", + "chaosaiart_forPreview", + "chaosaiart_image_loop", + "chaosaiart_img2gif", + "chaosaiart_img2video", + "chaosaiart_lora", + "chaosaiart_lora_advanced", + "chaosaiart_merge_Folders", + "chaosaiart_oneNode", + "chaosaiart_reloadAny_Load", + "chaosaiart_reloadAny_Save", + "chaosaiart_reloadIMG_Load", + "chaosaiart_reloadIMG_Save", + "chaosaiart_reloadLatent_Load", + "chaosaiart_reloadLatent_Save", + "chaosaiart_restarter", + "chaosaiart_restarter_advanced", + "chaosaiart_video2img1", + "chaosaiart_zoom_frame" + ], + { + "title_aux": "Chaosaiart-Nodes" + } + ], + "https://github.com/chesnokovivan/ComfyUI-Novakid": [ + [ + "Novakid Styler" + ], + { + "title_aux": "ComfyUI-Novakid" + } + ], + "https://github.com/chflame163/ComfyUI_FaceSimilarity": [ + [ + "Face Similarity" + ], + { + "title_aux": "ComfyUI Face Similarity" + } + ], + "https://github.com/chflame163/ComfyUI_LayerStyle": [ + [ + "LayerColor: AutoAdjust", + "LayerColor: AutoBrightness", + "LayerColor: Brightness & Contrast", + "LayerColor: Color of Shadow & Highlight", + "LayerColor: ColorAdapter", + "LayerColor: ColorBalance", + "LayerColor: ColorTemperature", + "LayerColor: Exposure", + "LayerColor: Gamma", + "LayerColor: HSV", + "LayerColor: LAB", + "LayerColor: LUT Apply", + "LayerColor: Levels", + "LayerColor: RGB", + "LayerColor: YUV", + "LayerFilter: AddGrain", + "LayerFilter: ChannelShake", + "LayerFilter: ColorMap", + "LayerFilter: Film", + "LayerFilter: FilmV2", + "LayerFilter: GaussianBlur", + "LayerFilter: HDREffects", + "LayerFilter: LightLeak", + "LayerFilter: MotionBlur", + "LayerFilter: Sharp & Soft", + "LayerFilter: SkinBeauty", + "LayerFilter: SoftLight", + "LayerFilter: WaterColor", + "LayerMask: BiRefNetUltra", + "LayerMask: BlendIf Mask", + "LayerMask: CreateGradientMask", + "LayerMask: ImageToMask", + "LayerMask: MaskBoxDetect", + "LayerMask: MaskByColor", + "LayerMask: MaskByDifferent", + "LayerMask: MaskEdgeShrink", + "LayerMask: MaskEdgeUltraDetail", + "LayerMask: MaskEdgeUltraDetail V2", + "LayerMask: MaskGradient", + "LayerMask: MaskGrain", + "LayerMask: MaskGrow", + "LayerMask: MaskInvert", + "LayerMask: MaskMotionBlur", + "LayerMask: MaskPreview", + "LayerMask: MaskStroke", + "LayerMask: MediapipeFacialSegment", + "LayerMask: PersonMaskUltra", + "LayerMask: PersonMaskUltra V2", + "LayerMask: PixelSpread", + "LayerMask: RemBgUltra", + "LayerMask: RmBgUltra V2", + "LayerMask: SegformerB2ClothesUltra", + "LayerMask: SegmentAnythingUltra", + "LayerMask: SegmentAnythingUltra V2", + "LayerMask: Shadow & Highlight Mask", + "LayerMask: YoloV8Detect", + "LayerStyle: ColorOverlay", + "LayerStyle: ColorOverlay V2", + "LayerStyle: DropShadow", + "LayerStyle: DropShadow V2", + "LayerStyle: GradientOverlay", + "LayerStyle: GradientOverlay V2", + "LayerStyle: InnerGlow", + "LayerStyle: InnerGlow V2", + "LayerStyle: InnerShadow", + "LayerStyle: InnerShadow V2", + "LayerStyle: OuterGlow", + "LayerStyle: OuterGlow V2", + "LayerStyle: Stroke", + "LayerStyle: Stroke V2", + "LayerUtility: AddBlindWaterMark", + "LayerUtility: BatchSelector", + "LayerUtility: Boolean", + "LayerUtility: BooleanOperator", + "LayerUtility: BooleanOperatorV2", + "LayerUtility: CheckMask", + "LayerUtility: ColorImage", + "LayerUtility: ColorImage V2", + "LayerUtility: ColorPicker", + "LayerUtility: CreateQRCode", + "LayerUtility: CropBoxResolve", + "LayerUtility: CropByMask", + "LayerUtility: CropByMask V2", + "LayerUtility: DecodeQRCode", + "LayerUtility: ExtendCanvas", + "LayerUtility: ExtendCanvasV2", + "LayerUtility: Float", + "LayerUtility: GetColorTone", + "LayerUtility: GetColorToneV2", + "LayerUtility: GetImageSize", + "LayerUtility: GradientImage", + "LayerUtility: GradientImage V2", + "LayerUtility: HLFrequencyDetailRestore", + "LayerUtility: HSV Value", + "LayerUtility: If", + "LayerUtility: ImageAutoCrop", + "LayerUtility: ImageAutoCrop V2", + "LayerUtility: ImageBlend", + "LayerUtility: ImageBlend V2", + "LayerUtility: ImageBlendAdvance", + "LayerUtility: ImageBlendAdvance V2", + "LayerUtility: ImageChannelMerge", + "LayerUtility: ImageChannelSplit", + "LayerUtility: ImageCombineAlpha", + "LayerUtility: ImageHub", + "LayerUtility: ImageMaskScaleAs", + "LayerUtility: ImageOpacity", + "LayerUtility: ImageRemoveAlpha", + "LayerUtility: ImageRewardFilter", + "LayerUtility: ImageScaleByAspectRatio", + "LayerUtility: ImageScaleByAspectRatio V2", + "LayerUtility: ImageScaleRestore", + "LayerUtility: ImageScaleRestore V2", + "LayerUtility: ImageShift", + "LayerUtility: Integer", + "LayerUtility: LaMa", + "LayerUtility: LayerImageTransform", + "LayerUtility: LayerMaskTransform", + "LayerUtility: LoadPSD", + "LayerUtility: NumberCalculator", + "LayerUtility: NumberCalculatorV2", + "LayerUtility: PrintInfo", + "LayerUtility: PromptEmbellish", + "LayerUtility: PromptTagger", + "LayerUtility: PurgeVRAM", + "LayerUtility: QWenImage2Prompt", + "LayerUtility: QueueStop", + "LayerUtility: RGB Value", + "LayerUtility: RestoreCropBox", + "LayerUtility: SD3NegativeConditioning", + "LayerUtility: SaveImagePlus", + "LayerUtility: Seed", + "LayerUtility: ShowBlindWaterMark", + "LayerUtility: SimpleTextImage", + "LayerUtility: String", + "LayerUtility: StringCondition", + "LayerUtility: SwitchCase", + "LayerUtility: TextBox", + "LayerUtility: TextImage", + "LayerUtility: TextJoin", + "LayerUtility: XY to Percent" + ], + { + "author": "chflame", + "description": "A set of nodes for ComfyUI that can composite layer and mask to achieve Photoshop like functionality.", + "nickname": "LayerStyle", + "title": "LayerStyle", + "title_aux": "ComfyUI Layer Style" + } + ], + "https://github.com/chflame163/ComfyUI_MSSpeech_TTS": [ + [ + "Input Trigger", + "MicrosoftSpeech_TTS", + "Play Sound", + "Play Sound (loop)" + ], + { + "title_aux": "ComfyUI_MSSpeech_TTS" + } + ], + "https://github.com/chflame163/ComfyUI_WordCloud": [ + [ + "ComfyWordCloud", + "LoadTextFile", + "RGB_Picker" + ], + { + "title_aux": "ComfyUI_WordCloud" + } + ], + "https://github.com/chibiace/ComfyUI-Chibi-Nodes": [ + [ + "ConditionText", + "ConditionTextMulti", + "ImageAddText", + "ImageSimpleResize", + "ImageSizeInfo", + "ImageTool", + "Int2String", + "LoadEmbedding", + "LoadImageExtended", + "Loader", + "Prompts", + "RandomResolutionLatent", + "SaveImages", + "SeedGenerator", + "SimpleSampler", + "TextSplit", + "Textbox", + "Wildcards" + ], + { + "title_aux": "ComfyUI-Chibi-Nodes" + } + ], + "https://github.com/choey/Comfy-Topaz": [ + [ + "TopazPhotoAI", + "TopazSharpenSettings", + "TopazUpscaleSettings" + ], + { + "title_aux": "Comfy-Topaz" + } + ], + "https://github.com/chris-the-wiz/EmbeddingsCurveEditor_ComfyUI": [ + [ + "Embeddings Curve Editor" + ], + { + "title_aux": "EmbeddingsCurveEditor_ComfyUI" + } + ], + "https://github.com/chrisfreilich/virtuoso-nodes": [ + [ + "BlackAndWhite", + "BlendIf", + "BlendModes", + "ColorBalance", + "ColorBalanceAdvanced", + "GaussianBlur", + "GaussianBlurDepth", + "HueSat", + "HueSatAdvanced", + "LensBlur", + "LensBlurDepth", + "Levels", + "MergeRGB", + "MotionBlur", + "MotionBlurDepth", + "SelectiveColor", + "SolidColor", + "SolidColorHSV", + "SolidColorRGB", + "SplitRGB" + ], + { + "author": "Chris Freilich", + "description": "This extension provides a \"Blend If (BlendIf)\" node.", + "nickname": "Virtuoso Pack - Blend If", + "title": "Virtuoso Pack - Blend If", + "title_aux": "Virtuoso Nodes for ComfyUI" + } + ], + "https://github.com/chrisgoringe/cg-image-picker": [ + [ + "Preview Chooser", + "Preview Chooser Fabric" + ], + { + "author": "chrisgoringe", + "description": "Custom nodes that preview images and pause the workflow to allow the user to select one or more to progress", + "nickname": "Image Chooser", + "title": "Image Chooser", + "title_aux": "Image chooser" + } + ], + "https://github.com/chrisgoringe/cg-noise": [ + [ + "Hijack", + "KSampler Advanced with Variations", + "KSampler with Variations", + "UnHijack" + ], + { + "title_aux": "Variation seeds" + } + ], + "https://github.com/chrisgoringe/cg-use-everywhere": [ + [ + "Seed Everywhere" + ], + { + "nodename_pattern": "(^(Prompts|Anything) Everywhere|Simple String)", + "title_aux": "Use Everywhere (UE Nodes)" + } + ], + "https://github.com/christian-byrne/audio-separation-nodes-comfyui": [ + [ + "AudioCombine", + "AudioCrop", + "AudioSeparation", + "AudioTempoMatch", + "AudioVideoCombine" + ], + { + "title_aux": "audio-separation-nodes-comfyui" + } + ], + "https://github.com/christian-byrne/img2colors-comfyui-node": [ + [ + "bmy_Img2ColorNode" + ], + { + "author": "christian-byrne", + "description": "", + "nickname": "img2color", + "title": "Img2Color Node - Detect and describe color palettes in images", + "title_aux": "img2colors-comfyui-node" + } + ], + "https://github.com/christian-byrne/size-match-compositing-nodes": [ + [ + "Composite Alpha Layer", + "Size Match Images/Masks" + ], + { + "title_aux": "Node - Size Matcher" + } + ], + "https://github.com/city96/ComfyUI_ColorMod": [ + [ + "CV2Tonemap", + "CV2TonemapDrago", + "CV2TonemapDurand", + "CV2TonemapMantiuk", + "CV2TonemapReinhard", + "ColorModCompress", + "ColorModEdges", + "ColorModMove", + "ColorModPivot", + "HDRCreate", + "HDRExposureFusion", + "LoadImageHDR", + "LoadImageHighPrec", + "PreviewImageHighPrec", + "SaveImageHDR", + "SaveImageHighPrec" + ], + { + "title_aux": "ComfyUI_ColorMod" + } + ], + "https://github.com/city96/ComfyUI_DiT": [ + [ + "DiTCheckpointLoader", + "DiTCheckpointLoaderSimple", + "DiTLabelCombine", + "DiTLabelSelect", + "DiTSampler" + ], + { + "title_aux": "ComfyUI_DiT [WIP]" + } + ], + "https://github.com/city96/ComfyUI_ExtraModels": [ + [ + "DiTCondLabelEmpty", + "DiTCondLabelSelect", + "DitCheckpointLoader", + "ExtraVAELoader", + "HYDiTCheckpointLoader", + "HYDiTSrcSizeCond", + "HYDiTTextEncode", + "HYDiTTextEncodeSimple", + "HYDiTTextEncoderLoader", + "MiaoBiCLIPLoader", + "MiaoBiDiffusersLoader", + "PixArtCheckpointLoader", + "PixArtCheckpointLoaderSimple", + "PixArtControlNetCond", + "PixArtLoraLoader", + "PixArtResolutionCond", + "PixArtResolutionSelect", + "PixArtT5FromSD3CLIP", + "PixArtT5TextEncode", + "T5TextEncode", + "T5v11Loader" + ], + { + "title_aux": "Extra Models for ComfyUI" + } + ], + "https://github.com/city96/ComfyUI_NetDist": [ + [ + "CombineImageBatch", + "FetchRemote", + "LoadCurrentWorkflowJSON", + "LoadDiskWorkflowJSON", + "LoadImageUrl", + "LoadLatentNumpy", + "LoadLatentUrl", + "RemoteChainEnd", + "RemoteChainStart", + "RemoteQueueSimple", + "RemoteQueueWorker", + "SaveDiskWorkflowJSON", + "SaveImageUrl", + "SaveLatentNumpy" + ], + { + "title_aux": "ComfyUI_NetDist" + } + ], + "https://github.com/city96/SD-Advanced-Noise": [ + [ + "LatentGaussianNoise", + "MathEncode" + ], + { + "title_aux": "SD-Advanced-Noise" + } + ], + "https://github.com/city96/SD-Latent-Interposer": [ + [ + "LatentInterposer" + ], + { + "title_aux": "Latent-Interposer" + } + ], + "https://github.com/city96/SD-Latent-Upscaler": [ + [ + "LatentUpscaler" + ], + { + "title_aux": "SD-Latent-Upscaler" + } + ], + "https://github.com/civitai/comfy-nodes": [ + [ + "CivitAI_Checkpoint_Loader", + "CivitAI_Lora_Loader" + ], + { + "title_aux": "comfy-nodes" + } + ], + "https://github.com/claussteinmassl/ComfyUI-CS-CustomNodes": [ + [ + "CS Transform" + ], + { + "title_aux": "CS Transform Node for ComfyUI" + } + ], + "https://github.com/comfyanonymous/ComfyUI": [ + [ + "AddNoise", + "AlignYourStepsScheduler", + "BasicGuider", + "BasicScheduler", + "CFGGuider", + "CLIPAttentionMultiply", + "CLIPLoader", + "CLIPMergeAdd", + "CLIPMergeSimple", + "CLIPMergeSubtract", + "CLIPSave", + "CLIPSetLastLayer", + "CLIPTextEncode", + "CLIPTextEncodeControlnet", + "CLIPTextEncodeSD3", + "CLIPTextEncodeSDXL", + "CLIPTextEncodeSDXLRefiner", + "CLIPVisionEncode", + "CLIPVisionLoader", + "Canny", + "CheckpointLoader", + "CheckpointLoaderSimple", + "CheckpointSave", + "ConditioningAverage", + "ConditioningCombine", + "ConditioningConcat", + "ConditioningSetArea", + "ConditioningSetAreaPercentage", + "ConditioningSetAreaStrength", + "ConditioningSetMask", + "ConditioningSetTimestepRange", + "ConditioningZeroOut", + "ControlNetApply", + "ControlNetApplyAdvanced", + "ControlNetApplySD3", + "ControlNetLoader", + "CropMask", + "DiffControlNetLoader", + "DifferentialDiffusion", + "DiffusersLoader", + "DisableNoise", + "DualCFGGuider", + "DualCLIPLoader", + "EmptyImage", + "EmptyLatentAudio", + "EmptyLatentImage", + "EmptySD3LatentImage", + "ExponentialScheduler", + "FeatherMask", + "FlipSigmas", + "FreeU", + "FreeU_V2", + "GITSScheduler", + "GLIGENLoader", + "GLIGENTextBoxApply", + "GrowMask", + "HyperTile", + "HypernetworkLoader", + "ImageBatch", + "ImageBlend", + "ImageBlur", + "ImageColorToMask", + "ImageCompositeMasked", + "ImageCrop", + "ImageFromBatch", + "ImageInvert", + "ImageOnlyCheckpointLoader", + "ImageOnlyCheckpointSave", + "ImagePadForOutpaint", + "ImageQuantize", + "ImageScale", + "ImageScaleBy", + "ImageScaleToTotalPixels", + "ImageSharpen", + "ImageToMask", + "ImageUpscaleWithModel", + "InpaintModelConditioning", + "InstructPixToPixConditioning", + "InvertMask", + "JoinImageWithAlpha", + "KSampler", + "KSamplerAdvanced", + "KSamplerSelect", + "KarrasScheduler", + "LatentAdd", + "LatentBatch", + "LatentBatchSeedBehavior", + "LatentBlend", + "LatentComposite", + "LatentCompositeMasked", + "LatentCrop", + "LatentFlip", + "LatentFromBatch", + "LatentInterpolate", + "LatentMultiply", + "LatentRotate", + "LatentSubtract", + "LatentUpscale", + "LatentUpscaleBy", + "LoadAudio", + "LoadImage", + "LoadImageMask", + "LoadLatent", + "LoraLoader", + "LoraLoaderModelOnly", + "MaskComposite", + "MaskToImage", + "ModelMergeAdd", + "ModelMergeBlocks", + "ModelMergeSD1", + "ModelMergeSD2", + "ModelMergeSD3_2B", + "ModelMergeSDXL", + "ModelMergeSimple", + "ModelMergeSubtract", + "ModelSamplingContinuousEDM", + "ModelSamplingContinuousV", + "ModelSamplingDiscrete", + "ModelSamplingSD3", + "ModelSamplingStableCascade", + "Morphology", + "PatchModelAddDownscale", + "PerpNeg", + "PerpNegGuider", + "PerturbedAttentionGuidance", + "PhotoMakerEncode", + "PhotoMakerLoader", + "PolyexponentialScheduler", + "PorterDuffImageComposite", + "PreviewAudio", + "PreviewImage", + "RandomNoise", + "RebatchImages", + "RebatchLatents", + "RepeatImageBatch", + "RepeatLatentBatch", + "RescaleCFG", + "SDTurboScheduler", + "SD_4XUpscale_Conditioning", + "SV3D_Conditioning", + "SVD_img2vid_Conditioning", + "SamplerCustom", + "SamplerCustomAdvanced", + "SamplerDPMAdaptative", + "SamplerDPMPP_2M_SDE", + "SamplerDPMPP_3M_SDE", + "SamplerDPMPP_SDE", + "SamplerEulerAncestral", + "SamplerEulerAncestralCFGPP", + "SamplerEulerCFGpp", + "SamplerLCMUpscale", + "SamplerLMS", + "SaveAnimatedPNG", + "SaveAnimatedWEBP", + "SaveAudio", + "SaveImage", + "SaveImageWebsocket", + "SaveLatent", + "SelfAttentionGuidance", + "SetLatentNoiseMask", + "SolidMask", + "SplitImageWithAlpha", + "SplitSigmas", + "SplitSigmasDenoise", + "StableCascade_EmptyLatentImage", + "StableCascade_StageB_Conditioning", + "StableCascade_StageC_VAEEncode", + "StableCascade_SuperResolutionControlnet", + "StableZero123_Conditioning", + "StableZero123_Conditioning_Batched", + "StyleModelApply", + "StyleModelLoader", + "ThresholdMask", + "TomePatchModel", + "TripleCLIPLoader", + "UNETLoader", + "UNetCrossAttentionMultiply", + "UNetSelfAttentionMultiply", + "UNetTemporalAttentionMultiply", + "UpscaleModelLoader", + "VAEDecode", + "VAEDecodeAudio", + "VAEDecodeTiled", + "VAEEncode", + "VAEEncodeAudio", + "VAEEncodeForInpaint", + "VAEEncodeTiled", + "VAELoader", + "VAESave", + "VPScheduler", + "VideoLinearCFGGuidance", + "VideoTriangleCFGGuidance", + "WebcamCapture", + "unCLIPCheckpointLoader", + "unCLIPConditioning" + ], + { + "title_aux": "ComfyUI" + } + ], + "https://github.com/comfyanonymous/ComfyUI_TensorRT": [ + [ + "DYNAMIC_TRT_MODEL_CONVERSION", + "STATIC_TRT_MODEL_CONVERSION", + "TensorRTLoader" + ], + { + "title_aux": "TensorRT Node for ComfyUI" + } + ], + "https://github.com/comfyanonymous/ComfyUI_experiments": [ + [ + "ModelMergeBlockNumber", + "ModelMergeSDXL", + "ModelMergeSDXLDetailedTransformers", + "ModelMergeSDXLTransformers", + "ModelSamplerTonemapNoiseTest", + "ReferenceOnlySimple", + "RescaleClassifierFreeGuidanceTest", + "TonemapNoiseWithRescaleCFG" + ], + { + "title_aux": "ComfyUI_experiments" + } + ], + "https://github.com/concarne000/ConCarneNode": [ + [ + "BingImageGrabber", + "Hermes", + "Zephyr" + ], + { + "title_aux": "ConCarneNode" + } + ], + "https://github.com/conquestace/ComfyUI-ImageUploader": [ + [ + "ImageUploader" + ], + { + "author": "ConquestAce", + "description": "Upload to temporary websites with API.", + "nickname": "Image Uploader", + "title": "Image Uploader", + "title_aux": "Image Uploader" + } + ], + "https://github.com/coreyryanhanson/ComfyQR": [ + [ + "comfy-qr-by-image-size", + "comfy-qr-by-module-size", + "comfy-qr-by-module-split", + "comfy-qr-mask_errors" + ], + { + "title_aux": "ComfyQR" + } + ], + "https://github.com/coreyryanhanson/ComfyQR-scanning-nodes": [ + [ + "comfy-qr-read", + "comfy-qr-validate" + ], + { + "title_aux": "ComfyQR-scanning-nodes" + } + ], + "https://github.com/cozymantis/cozy-utils-comfyui-nodes": [ + [ + "Cozy Sampler Options" + ], + { + "title_aux": "Cozy Utils" + } + ], + "https://github.com/cozymantis/human-parser-comfyui-node": [ + [ + "Cozy Human Parser ATR", + "Cozy Human Parser LIP", + "Cozy Human Parser Pascal" + ], + { + "title_aux": "Cozy Human Parser" + } + ], + "https://github.com/cozymantis/pose-generator-comfyui-node": [ + [ + "Cozy Pose Body Reference", + "Cozy Pose Face Reference" + ], + { + "title_aux": "Cozy Reference Pose Generator" + } + ], + "https://github.com/crystian/ComfyUI-Crystools": [ + [], + { + "author": "Crystian", + "description": "Plugins for multiples uses, mainly for debugging, you need them! IG: https://www.instagram.com/crystian.ia", + "nickname": "Crystools", + "nodename_pattern": " \\[Crystools\\]$", + "title": "Crystools", + "title_aux": "Crystools" + } + ], + "https://github.com/cubiq/ComfyUI_FaceAnalysis": [ + [ + "FaceAlign", + "FaceAnalysisModels", + "FaceBoundingBox", + "FaceEmbedDistance", + "FaceSegmentation", + "FaceWarp" + ], + { + "title_aux": "Face Analysis for ComfyUI" + } + ], + "https://github.com/cubiq/ComfyUI_IPAdapter_plus": [ + [ + "IPAAdapterFaceIDBatch", + "IPAdapter", + "IPAdapterAdvanced", + "IPAdapterBatch", + "IPAdapterCombineEmbeds", + "IPAdapterCombineParams", + "IPAdapterCombineWeights", + "IPAdapterEmbeds", + "IPAdapterEmbedsBatch", + "IPAdapterEncoder", + "IPAdapterFaceID", + "IPAdapterFromParams", + "IPAdapterInsightFaceLoader", + "IPAdapterLoadEmbeds", + "IPAdapterMS", + "IPAdapterModelLoader", + "IPAdapterNoise", + "IPAdapterPreciseStyleTransfer", + "IPAdapterPreciseStyleTransferBatch", + "IPAdapterPromptScheduleFromWeightsStrategy", + "IPAdapterRegionalConditioning", + "IPAdapterSaveEmbeds", + "IPAdapterStyleComposition", + "IPAdapterStyleCompositionBatch", + "IPAdapterTiled", + "IPAdapterTiledBatch", + "IPAdapterUnifiedLoader", + "IPAdapterUnifiedLoaderCommunity", + "IPAdapterUnifiedLoaderFaceID", + "IPAdapterWeights", + "IPAdapterWeightsFromStrategy", + "PrepImageForClipVision" + ], + { + "title_aux": "ComfyUI_IPAdapter_plus" + } + ], + "https://github.com/cubiq/ComfyUI_InstantID": [ + [ + "ApplyInstantID", + "ApplyInstantIDAdvanced", + "ApplyInstantIDControlNet", + "FaceKeypointsPreprocessor", + "InstantIDAttentionPatch", + "InstantIDFaceAnalysis", + "InstantIDModelLoader" + ], + { + "title_aux": "ComfyUI InstantID (Native Support)" + } + ], + "https://github.com/cubiq/ComfyUI_SimpleMath": [ + [ + "SimpleMath", + "SimpleMathDebug" + ], + { + "title_aux": "Simple Math" + } + ], + "https://github.com/cubiq/ComfyUI_essentials": [ + [ + "ApplyCLIPSeg+", + "BatchCount+", + "CLIPTextEncodeSDXL+", + "ConditioningCombineMultiple+", + "ConsoleDebug+", + "DebugTensorShape+", + "DrawText+", + "ExtractKeyframes+", + "GetImageSize+", + "ImageApplyLUT+", + "ImageBatchMultiple+", + "ImageCASharpening+", + "ImageColorMatch+", + "ImageCompositeFromMaskBatch+", + "ImageCrop+", + "ImageDesaturate+", + "ImageEnhanceDifference+", + "ImageExpandBatch+", + "ImageFlip+", + "ImageFromBatch+", + "ImageHistogramMatch+", + "ImageListToBatch+", + "ImagePosterize+", + "ImagePreviewFromLatent+", + "ImageRandomTransform+", + "ImageRemoveAlpha+", + "ImageRemoveBackground+", + "ImageResize+", + "ImageSeamCarving+", + "ImageTile+", + "ImageToDevice+", + "ImageUntile+", + "KSamplerVariationsStochastic+", + "KSamplerVariationsWithNoise+", + "LoadCLIPSegModels+", + "MaskBatch+", + "MaskBlur+", + "MaskBoundingBox+", + "MaskExpandBatch+", + "MaskFix+", + "MaskFlip+", + "MaskFromBatch+", + "MaskFromColor+", + "MaskFromList+", + "MaskFromRGBCMYBW+", + "MaskFromSegmentation+", + "MaskPreview+", + "MaskSmooth+", + "ModelCompile+", + "NoiseFromImage+", + "PixelOEPixelize+", + "RemBGSession+", + "RemoveLatentMask+", + "SD3NegativeConditioning+", + "SDXLEmptyLatentSizePicker+", + "SimpleMath+", + "TransitionMask+" + ], + { + "title_aux": "ComfyUI Essentials" + } + ], + "https://github.com/cubiq/PuLID_ComfyUI": [ + [ + "ApplyPulid", + "ApplyPulidAdvanced", + "PulidEvaClipLoader", + "PulidInsightFaceLoader", + "PulidModelLoader" + ], + { + "title_aux": "PuLID_ComfyUI" + } + ], + "https://github.com/cuongloveit/comfy_http_request": [ + [ + "Send Http Request", + "Send Http request" + ], + { + "title_aux": "comfy_http_request" + } + ], + "https://github.com/curiousjp/ComfyUI-MaskBatchPermutations": [ + [ + "CombinatorialDetailer", + "FlattenAgainstOriginal", + "PermuteMaskBatch" + ], + { + "title_aux": "ComfyUI-MaskBatchPermutations" + } + ], + "https://github.com/czcz1024/Comfyui-FaceCompare": [ + [ + "FaceCompare" + ], + { + "author": "czcz1024", + "description": "Face Compare", + "nickname": "Face Compare", + "title": "Face Compare", + "title_aux": "Face Compare" + } + ], + "https://github.com/da2el-ai/ComfyUI-d2-size-selector": [ + [ + "D2_SizeSelector" + ], + { + "author": "da2el", + "description": "Easy select image size", + "title": "D2 Size Selector", + "title_aux": "D2 Size Selector" + } + ], + "https://github.com/da2el-ai/ComfyUI-d2-steps": [ + [ + "D2 Refiner Steps", + "D2 Refiner Steps A1111", + "D2 Refiner Steps Tester" + ], + { + "author": "da2el", + "description": "Calculate the steps for the refiner", + "title": "D2 Steps", + "title_aux": "D2 Steps" + } + ], + "https://github.com/dagthomas/comfyui_dagthomas": [ + [ + "PGSD3LatentGenerator", + "PromptGenerator" + ], + { + "title_aux": "SDXL Auto Prompter" + } + ], + "https://github.com/daniabib/ComfyUI_ProPainter_Nodes": [ + [ + "ProPainterInpaint", + "ProPainterOutpaint" + ], + { + "title_aux": "ComfyUI ProPainter Nodes" + } + ], + "https://github.com/daniel-lewis-ab/ComfyUI-Llama": [ + [ + "Call LLM Advanced", + "Call LLM Basic", + "LLM_Create_Completion Advanced", + "LLM_Detokenize", + "LLM_Embed", + "LLM_Eval", + "LLM_Load_State", + "LLM_Reset", + "LLM_Sample", + "LLM_Save_State", + "LLM_Token_BOS", + "LLM_Token_EOS", + "LLM_Tokenize", + "Load LLM Model Advanced", + "Load LLM Model Basic" + ], + { + "title_aux": "ComfyUI-Llama" + } + ], + "https://github.com/daniel-lewis-ab/ComfyUI-TTS": [ + [ + "Load_Piper_Model", + "Piper_Speak_Text" + ], + { + "title_aux": "ComfyUI-TTS" + } + ], + "https://github.com/darkpixel/darkprompts": [ + [ + "DarkCheckpointRandomizer", + "DarkCheckpointSwitcher", + "DarkCombine", + "DarkFaceIndexGenerator", + "DarkFaceIndexShuffle", + "DarkFolders", + "DarkLoRALoader", + "DarkPrompt" + ], + { + "title_aux": "DarkPrompts" + } + ], + "https://github.com/dave-palt/comfyui_DSP_imagehelpers": [ + [ + "dsp-imagehelpers-concat" + ], + { + "title_aux": "comfyui_DSP_imagehelpers" + } + ], + "https://github.com/dawangraoming/ComfyUI_ksampler_gpu/raw/main/ksampler_gpu.py": [ + [ + "KSamplerAdvancedGPU", + "KSamplerGPU" + ], + { + "title_aux": "KSampler GPU" + } + ], + "https://github.com/daxcay/ComfyUI-DataSet": [ + [ + "DataSet_ConceptManager", + "DataSet_CopyFiles", + "DataSet_FindAndReplace", + "DataSet_LoadImage", + "DataSet_OpenAIChat", + "DataSet_OpenAIChatImage", + "DataSet_OpenAIChatImageBatch", + "DataSet_PathSelector", + "DataSet_SaveImage", + "DataSet_TextFilesLoad", + "DataSet_TextFilesLoadFromList", + "DataSet_TextFilesSave", + "DataSet_TriggerWords", + "DataSet_Visualizer" + ], + { + "author": "Daxton Caylor", + "description": "Data Research, Preparation, and Manipulation Nodes for Model Trainers, Artists, Designers, and Animators.", + "nickname": "ComfyUI-DataSet", + "title": "ComfyUI-DataSet", + "title_aux": "ComfyUI-DataSet" + } + ], + "https://github.com/daxcay/ComfyUI-JDCN": [ + [ + "JDCN_AnyCheckpointLoader", + "JDCN_AnyFileList", + "JDCN_AnyFileListHelper", + "JDCN_AnyFileListRandom", + "JDCN_AnyFileSelector", + "JDCN_BatchCounter", + "JDCN_BatchCounterAdvance", + "JDCN_BatchImageLoadFromDir", + "JDCN_BatchImageLoadFromList", + "JDCN_BatchLatentLoadFromDir", + "JDCN_BatchLatentLoadFromList", + "JDCN_BatchSaveLatent", + "JDCN_BoolInt", + "JDCN_EnableDisable", + "JDCN_FileMover", + "JDCN_ImageSaver", + "JDCN_ListToString", + "JDCN_ReBatch", + "JDCN_SeamlessExperience", + "JDCN_ShowAny", + "JDCN_SplitString", + "JDCN_StringManipulator", + "JDCN_StringToList", + "JDCN_SwapInputs", + "JDCN_TXTFileSaver", + "JDCN_VHSFileMover" + ], + { + "author": "Daxton Caylor & Jerry Davos", + "description": "Custom Utility Nodes for Artists, Designers and Animators.", + "nickname": "ComfyUI-JDCN", + "title": "ComfyUI-JDCN", + "title_aux": "ComfyUI-JDCN" + } + ], + "https://github.com/daxthin/DZ-FaceDetailer": [ + [ + "DZ_Face_Detailer" + ], + { + "title_aux": "DZ-FaceDetailer" + } + ], + "https://github.com/dchatel/comfyui_facetools": [ + [ + "BiSeNetMask", + "CropFaces", + "DetectFaces", + "GenderFaceFilter", + "JonathandinuMask", + "MergeWarps", + "OrderedFaceFilter", + "WarpFacesBack" + ], + { + "title_aux": "comfyui_facetools" + } + ], + "https://github.com/denfrost/Den_ComfyUI_Workflow": [ + [ + "Den_BatchIndex_AS", + "Den_CropImage_AS", + "Den_Eval_AS", + "Den_FaceRestoreCFWithModel", + "Den_GPTLoaderSimple_llama", + "Den_GPTSampler_llama", + "Den_ImageMixMasked_As", + "Den_ImageToLatentSpace", + "Den_ImageToMask_AS", + "Den_Int2Any_AS", + "Den_LatentAdd_AS", + "Den_LatentMixMasked_As", + "Den_LatentMix_AS", + "Den_LatentToImages_AS", + "Den_LoadLatent_AS", + "Den_MapRange_AS", + "Den_MaskToImage_AS", + "Den_Math_AS", + "Den_NoiseImage_AS", + "Den_Number2Float_AS", + "Den_Number2Int_AS", + "Den_Number_AS", + "Den_SVD_img2vid", + "Den_SaveLatent_AS", + "Den_TextToImage_AS", + "Den_TextWildcardList_AS", + "Increment_AS" + ], + { + "title_aux": "Den_ComfyUI_Workflows" + } + ], + "https://github.com/deroberon/StableZero123-comfyui": [ + [ + "SDZero ImageSplit", + "Stablezero123", + "Stablezero123WithDepth" + ], + { + "title_aux": "StableZero123-comfyui" + } + ], + "https://github.com/deroberon/demofusion-comfyui": [ + [ + "Batch Unsampler", + "Demofusion", + "Demofusion From Single File", + "Iterative Mixing KSampler" + ], + { + "title_aux": "demofusion-comfyui" + } + ], + "https://github.com/dfl/comfyui-clip-with-break": [ + [ + "AdvancedCLIPTextEncodeWithBreak", + "CLIPTextEncodeWithBreak" + ], + { + "author": "dfl", + "description": "CLIP text encoder that does BREAK prompting like A1111", + "nickname": "CLIP with BREAK", + "title": "CLIP with BREAK syntax", + "title_aux": "CLIP with BREAK syntax" + } + ], + "https://github.com/dfl/comfyui-tcd-scheduler": [ + [ + "SamplerTCD", + "SamplerTCD EulerA", + "TCDScheduler" + ], + { + "title_aux": "ComfyUI-TCD-scheduler" + } + ], + "https://github.com/diStyApps/ComfyUI_FrameMaker": [ + [ + "FrameMaker", + "FrameMakerBatch" + ], + { + "title_aux": "ComfyUI Frame Maker" + } + ], + "https://github.com/dicksondickson/ComfyUI-Dickson-Nodes": [ + [ + "DicksonColorMatch", + "TTPlanet_Tile_Preprocessor_GF", + "TTPlanet_Tile_Preprocessor_Simple", + "TTPlanet_Tile_Preprocessor_cufoff" + ], + { + "description": "This is a set of custom nodes that I've either written myself or adapted from other authors for my own convenience. Currently includes color matching node forked from StableSR and TTPlanet's controlnet preprocessor. https://github.com/dicksondickson", + "nickname": "Dickson Nodes", + "title": "Dickson Nodes", + "title_aux": "ComfyUI-Dickson-Nodes" + } + ], + "https://github.com/digitaljohn/comfyui-propost": [ + [ + "ProPostApplyLUT", + "ProPostDepthMapBlur", + "ProPostFilmGrain", + "ProPostRadialBlur", + "ProPostVignette" + ], + { + "title_aux": "ComfyUI-ProPost" + } + ], + "https://github.com/dimtoneff/ComfyUI-PixelArt-Detector": [ + [ + "PixelArtAddDitherPattern", + "PixelArtDetectorConverter", + "PixelArtDetectorSave", + "PixelArtDetectorToImage", + "PixelArtLoadPalettes" + ], + { + "title_aux": "ComfyUI PixelArt Detector" + } + ], + "https://github.com/diontimmer/ComfyUI-Vextra-Nodes": [ + [ + "Add Text To Image", + "Apply Instagram Filter", + "Create Solid Color", + "Flatten Colors", + "Generate Noise Image", + "GlitchThis Effect", + "Hue Rotation", + "Load Picture Index", + "Pixel Sort", + "Play Sound At Execution", + "Prettify Prompt Using distilgpt2", + "Swap Color Mode" + ], + { + "title_aux": "ComfyUI-Vextra-Nodes" + } + ], + "https://github.com/discopixel-studio/comfyui-discopixel": [ + [ + "TransformTemplateOntoFaceMask" + ], + { + "author": "Anson Kao", + "description": "A small collection of custom nodes for use with ComfyUI, by Discopixel", + "nickname": "ComfyUI Discopixel", + "title": "ComfyUI Discopixel", + "title_aux": "ComfyUI Discopixel Nodes" + } + ], + "https://github.com/discus0434/comfyui-caching-embeddings": [ + [ + "CachingCLIPTextEncode" + ], + { + "title_aux": "ComfyUI Caching Embeddings" + } + ], + "https://github.com/djbielejeski/a-person-mask-generator": [ + [ + "APersonFaceLandmarkMaskGenerator", + "APersonMaskGenerator" + ], + { + "title_aux": "a-person-mask-generator" + } + ], + "https://github.com/dmMaze/sketch2manga": [ + [ + "BlendScreentone", + "EmptyLatentImageAdvanced" + ], + { + "title_aux": "Sketch2Manga" + } + ], + "https://github.com/dmarx/ComfyUI-AudioReactive": [ + [ + "OpAbs", + "OpBandpass", + "OpClamp", + "OpHarmonic", + "OpModulo", + "OpNormalize", + "OpNovelty", + "OpPercussive", + "OpPow", + "OpPow2", + "OpPredominant_pulse", + "OpQuantize", + "OpRms", + "OpSmoosh", + "OpSmooth", + "OpSqrt", + "OpStretch", + "OpSustain", + "OpThreshold" + ], + { + "title_aux": "ComfyUI-AudioReactive" + } + ], + "https://github.com/dmarx/ComfyUI-Keyframed": [ + [ + "Example", + "KfAddCurveToPGroup", + "KfAddCurveToPGroupx10", + "KfApplyCurveToCond", + "KfConditioningAdd", + "KfConditioningAddx10", + "KfCurveConstant", + "KfCurveDraw", + "KfCurveFromString", + "KfCurveFromYAML", + "KfCurveInverse", + "KfCurveToAcnLatentKeyframe", + "KfCurvesAdd", + "KfCurvesAddx10", + "KfCurvesDivide", + "KfCurvesMultiply", + "KfCurvesMultiplyx10", + "KfCurvesSubtract", + "KfDebug_Clip", + "KfDebug_Cond", + "KfDebug_Curve", + "KfDebug_Float", + "KfDebug_Image", + "KfDebug_Int", + "KfDebug_Latent", + "KfDebug_Model", + "KfDebug_Passthrough", + "KfDebug_Segs", + "KfDebug_String", + "KfDebug_Vae", + "KfDrawSchedule", + "KfEvaluateCurveAtT", + "KfGetCurveFromPGroup", + "KfGetScheduleConditionAtTime", + "KfGetScheduleConditionSlice", + "KfKeyframedCondition", + "KfKeyframedConditionWithText", + "KfPGroupCurveAdd", + "KfPGroupCurveMultiply", + "KfPGroupDraw", + "KfPGroupProd", + "KfPGroupSum", + "KfSetCurveLabel", + "KfSetKeyframe", + "KfSinusoidalAdjustAmplitude", + "KfSinusoidalAdjustFrequency", + "KfSinusoidalAdjustPhase", + "KfSinusoidalAdjustWavelength", + "KfSinusoidalEntangledZeroOneFromFrequencyx2", + "KfSinusoidalEntangledZeroOneFromFrequencyx3", + "KfSinusoidalEntangledZeroOneFromFrequencyx4", + "KfSinusoidalEntangledZeroOneFromFrequencyx5", + "KfSinusoidalEntangledZeroOneFromFrequencyx6", + "KfSinusoidalEntangledZeroOneFromFrequencyx7", + "KfSinusoidalEntangledZeroOneFromFrequencyx8", + "KfSinusoidalEntangledZeroOneFromFrequencyx9", + "KfSinusoidalEntangledZeroOneFromWavelengthx2", + "KfSinusoidalEntangledZeroOneFromWavelengthx3", + "KfSinusoidalEntangledZeroOneFromWavelengthx4", + "KfSinusoidalEntangledZeroOneFromWavelengthx5", + "KfSinusoidalEntangledZeroOneFromWavelengthx6", + "KfSinusoidalEntangledZeroOneFromWavelengthx7", + "KfSinusoidalEntangledZeroOneFromWavelengthx8", + "KfSinusoidalEntangledZeroOneFromWavelengthx9", + "KfSinusoidalGetAmplitude", + "KfSinusoidalGetFrequency", + "KfSinusoidalGetPhase", + "KfSinusoidalGetWavelength", + "KfSinusoidalWithFrequency", + "KfSinusoidalWithWavelength" + ], + { + "title_aux": "ComfyUI-Keyframed" + } + ], + "https://github.com/drago87/ComfyUI_Dragos_Nodes": [ + [ + "file_padding", + "image_info", + "lora_loader", + "vae_loader" + ], + { + "title_aux": "ComfyUI_Dragos_Nodes" + } + ], + "https://github.com/drustan-hawk/primitive-types": [ + [ + "float", + "int", + "string", + "string_multiline" + ], + { + "title_aux": "primitive-types" + } + ], + "https://github.com/e7mac/ComfyUI-ShadertoyGL": [ + [ + "ColorChannelOffset", + "Shader", + "Shadertoy" + ], + { + "title_aux": "ComfyUI-ShadertoyGL" + } + ], + "https://github.com/ealkanat/comfyui_easy_padding": [ + [ + "comfyui-easy-padding" + ], + { + "title_aux": "ComfyUI Easy Padding" + } + ], + "https://github.com/edenartlab/eden_comfy_pipelines": [ + [ + "Animation_RGB_Mask", + "CLIP_Interrogator", + "ConvertToGrayscale", + "Eden_Bool", + "Eden_Compare", + "Eden_DebugPrint", + "Eden_Float", + "Eden_Int", + "Eden_Lora_Loader", + "Eden_String", + "FolderScanner", + "GetRandomFile", + "Get_Prefixed_Imgs", + "HistogramMatching", + "IMG_blender", + "IMG_padder", + "IMG_resolution_multiple_of", + "IMG_scaler", + "IMG_unpadder", + "If ANY execute A else B", + "ImageDescriptionNode", + "LatentTypeConversion", + "Linear_Combine_IP_Embeds", + "LoadImagesByFilename", + "LoadRandomImage", + "Load_Embeddings_From_Folder", + "MaskFromRGB", + "MaskFromRGB_KMeans", + "Random_Style_Mixture", + "SaveImageAdvanced", + "SavePosEmbeds", + "VAEDecode_to_folder", + "VideoFrameSelector", + "WidthHeightPicker" + ], + { + "title_aux": "Various custom nodes by Eden.art" + } + ], + "https://github.com/evanspearman/ComfyMath": [ + [ + "CM_BoolBinaryOperation", + "CM_BoolToInt", + "CM_BoolUnaryOperation", + "CM_BreakoutVec2", + "CM_BreakoutVec3", + "CM_BreakoutVec4", + "CM_ComposeVec2", + "CM_ComposeVec3", + "CM_ComposeVec4", + "CM_FloatBinaryCondition", + "CM_FloatBinaryOperation", + "CM_FloatToInt", + "CM_FloatToNumber", + "CM_FloatUnaryCondition", + "CM_FloatUnaryOperation", + "CM_IntBinaryCondition", + "CM_IntBinaryOperation", + "CM_IntToBool", + "CM_IntToFloat", + "CM_IntToNumber", + "CM_IntUnaryCondition", + "CM_IntUnaryOperation", + "CM_NearestSDXLResolution", + "CM_NumberBinaryCondition", + "CM_NumberBinaryOperation", + "CM_NumberToFloat", + "CM_NumberToInt", + "CM_NumberUnaryCondition", + "CM_NumberUnaryOperation", + "CM_SDXLResolution", + "CM_Vec2BinaryCondition", + "CM_Vec2BinaryOperation", + "CM_Vec2ScalarOperation", + "CM_Vec2ToScalarBinaryOperation", + "CM_Vec2ToScalarUnaryOperation", + "CM_Vec2UnaryCondition", + "CM_Vec2UnaryOperation", + "CM_Vec3BinaryCondition", + "CM_Vec3BinaryOperation", + "CM_Vec3ScalarOperation", + "CM_Vec3ToScalarBinaryOperation", + "CM_Vec3ToScalarUnaryOperation", + "CM_Vec3UnaryCondition", + "CM_Vec3UnaryOperation", + "CM_Vec4BinaryCondition", + "CM_Vec4BinaryOperation", + "CM_Vec4ScalarOperation", + "CM_Vec4ToScalarBinaryOperation", + "CM_Vec4ToScalarUnaryOperation", + "CM_Vec4UnaryCondition", + "CM_Vec4UnaryOperation" + ], + { + "title_aux": "ComfyMath" + } + ], + "https://github.com/exdysa/comfyui-selector": [ + [ + "Fork", + "ForkClip", + "Recourse", + "Recourse+/-", + "RecourseCkpt", + "RecourseImage", + "Selector", + "Unite" + ], + { + "author": "\"\u02f6\ud835\udfa2\u292c\u2ad2\u2d56s\u143c\u02f6\"", + "description": "\"EXDYSA. Selector and Recourse. Presets & failsafes. Work flow.\"", + "nickname": "\"Selector\"", + "title": "\"Selector\"", + "title_aux": "comfyui-selector" + } + ], + "https://github.com/fablestudio/ComfyUI-Showrunner-Utils": [ + [ + "AlignFace" + ], + { + "title_aux": "ComfyUI-Showrunner-Utils" + } + ], + "https://github.com/fearnworks/ComfyUI_FearnworksNodes/raw/main/fw_nodes.py": [ + [ + "Count Files in Directory (FW)", + "Count Tokens (FW)", + "Token Count Ranker(FW)", + "Trim To Tokens (FW)" + ], + { + "title_aux": "Fearnworks Custom Nodes" + } + ], + "https://github.com/fexli/fexli-util-node-comfyui": [ + [ + "FEBCPrompt", + "FEBatchGenStringBCDocker", + "FEColor2Image", + "FEColorOut", + "FEDataInsertor", + "FEDataPacker", + "FEDataUnpacker", + "FEDeepClone", + "FEDictPacker", + "FEDictUnpacker", + "FEEncLoraLoader", + "FEExtraInfoAdd", + "FEGenStringBCDocker", + "FEGenStringGPT", + "FEImageNoiseGenerate", + "FEImagePadForOutpaint", + "FEImagePadForOutpaintByImage", + "FEOperatorIf", + "FEPythonStrOp", + "FERandomBool", + "FERandomLoraSelect", + "FERandomPrompt", + "FERandomizedColor2Image", + "FERandomizedColorOut", + "FERerouteWithName", + "FESaveEncryptImage", + "FETextCombine", + "FETextCombine2Any", + "FETextInput" + ], + { + "title_aux": "fexli-util-node-comfyui" + } + ], + "https://github.com/fexploit/ComfyUI-AutoLabel": [ + [ + "AutoLabel" + ], + { + "title_aux": "ComfyUI-AutoLabel" + } + ], + "https://github.com/fexploit/ComfyUI-AutoTrimBG": [ + [ + "RonLayers/TrimBg: RonLayersTrimBgUltraV2" + ], + { + "title_aux": "ComfyUI-AutoTrimBG" + } + ], + "https://github.com/fexploit/ComfyUI-Classifier": [ + [ + "ClassifierNode" + ], + { + "title_aux": "ComfyUI-Classifier" + } + ], + "https://github.com/filipemeneses/comfy_pixelization": [ + [ + "Pixelization" + ], + { + "title_aux": "Pixelization" + } + ], + "https://github.com/filliptm/ComfyUI_Fill-Nodes": [ + [ + "FL_Ascii", + "FL_AudioConverter", + "FL_AudioFrameCalculator", + "FL_AudioPreview", + "FL_BatchAlign", + "FL_CodeNode", + "FL_DirectoryCrawl", + "FL_Glitch", + "FL_HalftonePattern", + "FL_HexagonalPattern", + "FL_ImageCaptionSaver", + "FL_ImageCollage", + "FL_ImageDimensionDisplay", + "FL_ImageDurationSync", + "FL_ImageNotes", + "FL_ImagePixelator", + "FL_ImageRandomizer", + "FL_InfiniteZoom", + "FL_InpaintCrop", + "FL_Inpaint_Stitch", + "FL_KsamplerSettings", + "FL_NFTGenerator", + "FL_PaperDrawn", + "FL_PasteOnCanvas", + "FL_PixelArtShader", + "FL_PixelSort", + "FL_PromptSelector", + "FL_RandomNumber", + "FL_RetroEffect", + "FL_Ripple", + "FL_SDUltimate_Slices", + "FL_SeparateMaskComponents", + "FL_Shadertoy", + "FL_TD_Sampler", + "FL_VideoCropMask", + "FL_VideoRecompose" + ], + { + "title_aux": "ComfyUI_Fill-Nodes" + } + ], + "https://github.com/fitCorder/fcSuite/raw/main/fcSuite.py": [ + [ + "fcFloat", + "fcFloatMatic", + "fcHex", + "fcInteger" + ], + { + "title_aux": "fcSuite" + } + ], + "https://github.com/florestefano1975/ComfyUI-HiDiffusion": [ + [ + "HiDiffusionSD15", + "HiDiffusionSD21", + "HiDiffusionSDXL", + "HiDiffusionSDXLTurbo" + ], + { + "title_aux": "ComfyUI HiDiffusion" + } + ], + "https://github.com/florestefano1975/ComfyUI-StabilityAI-Suite": [ + [ + "StabilityAI Suite - Creative Upscale", + "StabilityAI Suite - Creative Upscale Recover File", + "StabilityAI Suite - Image Core + Style Preset", + "StabilityAI Suite - Inpainting", + "StabilityAI Suite - Outpainting", + "StabilityAI Suite - Remove Background", + "StabilityAI Suite - SD3", + "StabilityAI Suite - Search and Replace" + ], + { + "title_aux": "ComfyUI StabilityAI Suite" + } + ], + "https://github.com/florestefano1975/comfyui-portrait-master": [ + [ + "PortraitMaster" + ], + { + "title_aux": "comfyui-portrait-master" + } + ], + "https://github.com/florestefano1975/comfyui-prompt-composer": [ + [ + "PromptComposerCustomLists", + "PromptComposerEffect", + "PromptComposerGrouping", + "PromptComposerMerge", + "PromptComposerStyler", + "PromptComposerTextSingle", + "promptComposerTextMultiple" + ], + { + "title_aux": "comfyui-prompt-composer" + } + ], + "https://github.com/flowtyone/ComfyUI-Flowty-CRM": [ + [ + "CCMSampler", + "CRMModelLoader", + "CRMModeler", + "CRMModelerCuda", + "CRMPoseSampler", + "CRMPoserConfig", + "CRMPreprocessForPoser", + "CRMViewer" + ], + { + "title_aux": "ComfyUI-Flowty-CRM" + } + ], + "https://github.com/flowtyone/ComfyUI-Flowty-LDSR": [ + [ + "LDSRModelLoader", + "LDSRUpscale", + "LDSRUpscaler" + ], + { + "title_aux": "ComfyUI-Flowty-LDSR" + } + ], + "https://github.com/flowtyone/ComfyUI-Flowty-TripoSR": [ + [ + "TripoSRModelLoader", + "TripoSRSampler", + "TripoSRViewer" + ], + { + "title_aux": "ComfyUI-Flowty-TripoSR" + } + ], + "https://github.com/flyingshutter/As_ComfyUI_CustomNodes": [ + [ + "BatchIndex_AS", + "CropImage_AS", + "Eval_AS", + "ImageMixMasked_As", + "ImageToMask_AS", + "Increment_AS", + "Int2Any_AS", + "LatentAdd_AS", + "LatentMixMasked_As", + "LatentMix_AS", + "LatentToImages_AS", + "LoadLatent_AS", + "MapRange_AS", + "MaskToImage_AS", + "Math_AS", + "NoiseImage_AS", + "Number2Float_AS", + "Number2Int_AS", + "Number_AS", + "SaveLatent_AS", + "TextToImage_AS", + "TextWildcardList_AS" + ], + { + "title_aux": "As_ComfyUI_CustomNodes" + } + ], + "https://github.com/fmatray/ComfyUI_BattlemapGrid": [ + [ + "Battlemap Grid", + "Compass", + "Map Generator", + "Map Generator(Outdoors)" + ], + { + "title_aux": "ComfyUI_BattlemapGrid" + } + ], + "https://github.com/fofr/ComfyUI-HyperSDXL1StepUnetScheduler": [ + [ + "HyperSDXL1StepUnetScheduler" + ], + { + "title_aux": "ComfyUI-HyperSDXL1StepUnetScheduler (ByteDance)" + } + ], + "https://github.com/fofr/ComfyUI-Prompter-fofrAI": [ + [ + "List sampler \ud83e\udeb4", + "Prompt from template \ud83e\udeb4" + ], + { + "title_aux": "ComfyUI-Prompter-fofrAI" + } + ], + "https://github.com/forever22777/comfyui-self-guidance": [ + [ + "CLIPConditioning", + "CheckpointLoaderMixWithDiffusers", + "SelfGuidanceSampler" + ], + { + "title_aux": "Self-Guidance nodes" + } + ], + "https://github.com/foxtrot-roger/comfyui-rf-nodes": [ + [ + "LogBool", + "LogFloat", + "LogInt", + "LogNumber", + "LogString", + "LogVec2", + "LogVec3", + "RF_AtIndexString", + "RF_BoolToString", + "RF_FloatToString", + "RF_IntToString", + "RF_JsonStyleLoader", + "RF_MergeLines", + "RF_NumberToString", + "RF_OptionsString", + "RF_RangeFloat", + "RF_RangeInt", + "RF_RangeNumber", + "RF_SavePromptInfo", + "RF_SplitLines", + "RF_TextConcatenate", + "RF_TextInput", + "RF_TextReplace", + "RF_Timestamp", + "RF_ToString", + "RF_Vec2ToString", + "RF_Vec3ToString", + "TextLine" + ], + { + "title_aux": "RF Nodes" + } + ], + "https://github.com/frankchieng/ComfyUI_Aniportrait": [ + [ + "AniPortrait_Audio2Video", + "AniPortrait_Audio_Path", + "AniPortrait_LoadVideoPath", + "AniPortrait_Pose_Gen_Video", + "AniPortrait_Ref_Image_Path", + "AniPortrait_Video_Gen_Pose" + ], + { + "title_aux": "ComfyUI_Aniportrait" + } + ], + "https://github.com/frankchieng/ComfyUI_MagicClothing": [ + [ + "MagicClothing_Animatediff", + "MagicClothing_Generate", + "MagicClothing_Inpainting" + ], + { + "title_aux": "ComfyUI_MagicClothing" + } + ], + "https://github.com/frankchieng/ComfyUI_llm_easyanimiate": [ + [], + { + "nodename_pattern": "^FrankChiengEasyAnimate", + "title_aux": "ComfyUI_llm_easyanimiate" + } + ], + "https://github.com/fsdymy1024/ComfyUI_fsdymy": [ + [ + "IPAdapterLayerWeight", + "Preview Image Without Metadata", + "PreviewImageWithoutMetadata", + "Save Image Without Metadata", + "SaveImageWithoutMetadata", + "ShowText", + "ZhiPuAiNode" + ], + { + "title_aux": "ComfyUI_fsdymy" + } + ], + "https://github.com/gemell1/ComfyUI_GMIC": [ + [ + "GmicCliWrapper", + "GmicQtWrapper" + ], + { + "title_aux": "ComfyUI_GMIC" + } + ], + "https://github.com/get-salt-AI/SaltAI": [ + [ + "SAIPrimitiveConverter", + "SAIStringRegexSearchMatch", + "SAIStringRegexSearchReplace", + "SaltAIStableVideoDiffusion", + "SaltBatchCropDataExtractor", + "SaltCLIPSegLoader", + "SaltCLIPSegMasking", + "SaltCropImageLocation", + "SaltDisplayAny", + "SaltImagePasteCrop", + "SaltInfo", + "SaltInput", + "SaltLoadImageZip", + "SaltMaskCropRegion", + "SaltMasksToImages", + "SaltOutput", + "SaltRGBAFromMask", + "SaltWebsiteScreenshot" + ], + { + "title_aux": "SaltAI-Open-Resources" + } + ], + "https://github.com/get-salt-AI/SaltAI_Language_Toolkit": [ + [ + "AddTool", + "ChangeSystemMessage", + "ClearMemory", + "ConversableAgentCreator", + "ConversableAgentCreatorAdvanced", + "ConvertAgentAsTool", + "ConvertAgentToLlamaindex", + "CreateTavilySearchTool", + "Example", + "GenerateReply", + "GroupChat", + "GroupChatAdvanced", + "GroupChatManagerCreator", + "LLMCSVReader", + "LLMChat", + "LLMChatBot", + "LLMChatEngine", + "LLMChatMessageConcat", + "LLMChatMessages", + "LLMChatMessagesAdv", + "LLMComplete", + "LLMCustomNodeComposer", + "LLMDirectoryReader", + "LLMDocumentListAppend", + "LLMDocxReader", + "LLMEpubReader", + "LLMFlatReader", + "LLMHTMLTagReader", + "LLMHWPReader", + "LLMHtmlComposer", + "LLMHtmlRepair", + "LLMIPYNBReader", + "LLMImageCaptionReader", + "LLMImageTabularChartReader", + "LLMImageTextReader", + "LLMImageVisionLLMReader", + "LLMInputToDocuments", + "LLMJsonComposer", + "LLMJsonRepair", + "LLMLLaVANextImageEvaluator", + "LLMLLaVANextModelLoader", + "LLMMarkdownComposer", + "LLMMarkdownReader", + "LLMMarkdownRepair", + "LLMMboxReader", + "LLMMultiModalImageEvaluation", + "LLMNotionReader", + "LLMOpenAIModel", + "LLMOpenAIModelOpts", + "LLMPDFReader", + "LLMPagedCSVReader", + "LLMPandasCSVReader", + "LLMParquetDatasetSearcher", + "LLMPostProcessDocuments", + "LLMPptxReader", + "LLMPyMuPDFReader", + "LLMQueryEngine", + "LLMQueryEngineAdv", + "LLMQueryEngineAsTool", + "LLMRTFReader", + "LLMRegexCreator", + "LLMRegexRepair", + "LLMRssReaderNode", + "LLMSaltWebCrawler", + "LLMScaleSERPSearch", + "LLMSemanticSplitterNodeParser", + "LLMSentenceSplitterNodeCreator", + "LLMServiceContextAdv", + "LLMServiceContextDefault", + "LLMSimpleWebPageReader", + "LLMSimpleWebPageReaderAdv", + "LLMSummaryIndex", + "LLMTavilyResearch", + "LLMTrafilaturaWebReader", + "LLMTrafilaturaWebReaderAdv", + "LLMTreeIndex", + "LLMUnstructuredReader", + "LLMVectorStoreIndex", + "LLMVectorStoreIndexAdv", + "LLMVideoAudioReader", + "LLMXMLReader", + "LLMYamlComposer", + "LLMYamlRepair", + "SaltJSONQueryEngine", + "SendMessage", + "SimpleChat" + ], + { + "title_aux": "SaltAI Language Toolkit" + } + ], + "https://github.com/get-salt-AI/SaltAI_LlamaIndex": [ + [ + "AddTool", + "ChangeSystemMessage", + "ClearMemory", + "ConversableAgentCreator", + "ConversableAgentCreatorAdvanced", + "ConvertAgentAsTool", + "ConvertAgentToLlamaindex", + "CreateTavilySearchTool", + "Example", + "GenerateReply", + "GroupChat", + "GroupChatAdvanced", + "GroupChatManagerCreator", + "LLMCSVReader", + "LLMChat", + "LLMChatBot", + "LLMChatEngine", + "LLMChatMessageConcat", + "LLMChatMessages", + "LLMChatMessagesAdv", + "LLMComplete", + "LLMCustomNodeComposer", + "LLMDirectoryReader", + "LLMDocumentListAppend", + "LLMDocxReader", + "LLMEpubReader", + "LLMFlatReader", + "LLMHTMLTagReader", + "LLMHWPReader", + "LLMHtmlComposer", + "LLMHtmlRepair", + "LLMIPYNBReader", + "LLMImageCaptionReader", + "LLMImageTabularChartReader", + "LLMImageTextReader", + "LLMImageVisionLLMReader", + "LLMInputToDocuments", + "LLMJsonComposer", + "LLMJsonRepair", + "LLMLLaVANextImageEvaluator", + "LLMLLaVANextModelLoader", + "LLMMarkdownComposer", + "LLMMarkdownReader", + "LLMMarkdownRepair", + "LLMMboxReader", + "LLMMultiModalImageEvaluation", + "LLMNotionReader", + "LLMOpenAIModel", + "LLMOpenAIModelOpts", + "LLMPDFReader", + "LLMPagedCSVReader", + "LLMPandasCSVReader", + "LLMParquetDatasetSearcher", + "LLMPostProcessDocuments", + "LLMPptxReader", + "LLMPyMuPDFReader", + "LLMQueryEngine", + "LLMQueryEngineAdv", + "LLMQueryEngineAsTool", + "LLMRTFReader", + "LLMRegexCreator", + "LLMRegexRepair", + "LLMRssReaderNode", + "LLMSaltWebCrawler", + "LLMScaleSERPSearch", + "LLMSemanticSplitterNodeParser", + "LLMSentenceSplitterNodeCreator", + "LLMServiceContextAdv", + "LLMServiceContextDefault", + "LLMSimpleWebPageReader", + "LLMSimpleWebPageReaderAdv", + "LLMSummaryIndex", + "LLMTavilyResearch", + "LLMTrafilaturaWebReader", + "LLMTrafilaturaWebReaderAdv", + "LLMTreeIndex", + "LLMUnstructuredReader", + "LLMVectorStoreIndex", + "LLMVectorStoreIndexAdv", + "LLMVideoAudioReader", + "LLMXMLReader", + "LLMYamlComposer", + "LLMYamlRepair", + "SaltJSONQueryEngine", + "SendMessage", + "SimpleChat" + ], + { + "title_aux": "SaltAI_LlamaIndex" + } + ], + "https://github.com/giriss/comfy-image-saver": [ + [ + "Cfg Literal", + "Checkpoint Selector", + "Int Literal", + "Sampler Selector", + "Save Image w/Metadata", + "Scheduler Selector", + "Seed Generator", + "String Literal", + "Width/Height Literal" + ], + { + "title_aux": "Save Image with Generation Metadata" + } + ], + "https://github.com/githubYiheng/ComfyUI_Change_IMAGE_BOREDER": [ + [ + "ChangeImageBorder" + ], + { + "title_aux": "ComfyUI_Change_IMAGE_BOREDER" + } + ], + "https://github.com/githubYiheng/ComfyUI_GetFileNameFromURL": [ + [ + "GetFileNameFromURL" + ], + { + "title_aux": "ComfyUI_GetFileNameFromURL" + } + ], + "https://github.com/githubYiheng/comfyui_kmeans_filter": [ + [ + "ImageKmeansFilter" + ], + { + "title_aux": "comfyui_kmeans_filter" + } + ], + "https://github.com/githubYiheng/comfyui_meanshift_filter": [ + [ + "ImageMeanshiftFilter" + ], + { + "title_aux": "comfyui_meanshift_filter" + } + ], + "https://github.com/githubYiheng/comfyui_private_postprocessor": [ + [ + "ImageCPostprocessor", + "PrivateImageMask" + ], + { + "title_aux": "comfyui_private_postprocessor" + } + ], + "https://github.com/glibsonoran/Plush-for-ComfyUI": [ + [ + "AI Chooser", + "AdvPromptEnhancer", + "DalleImage", + "Enhancer", + "ImgTextSwitch", + "Plush-Exif Wrangler", + "Tagger", + "mulTextSwitch" + ], + { + "title_aux": "Plush-for-ComfyUI" + } + ], + "https://github.com/glifxyz/ComfyUI-GlifNodes": [ + [ + "GlifConsistencyDecoder", + "GlifPatchConsistencyDecoderTiled", + "GlifVariable", + "HFHubEmbeddingLoader", + "HFHubLoraLoader", + "ImageToMultipleOf", + "SDXLAspectRatio" + ], + { + "title_aux": "ComfyUI-GlifNodes" + } + ], + "https://github.com/glowcone/comfyui-base64-to-image": [ + [ + "LoadImageFromBase64" + ], + { + "title_aux": "Load Image From Base64 URI" + } + ], + "https://github.com/godspede/ComfyUI_Substring": [ + [ + "SubstringTheory" + ], + { + "title_aux": "ComfyUI Substring" + } + ], + "https://github.com/gokayfem/ComfyUI-Depth-Visualization": [ + [ + "DepthViewer" + ], + { + "title_aux": "ComfyUI-Depth-Visualization" + } + ], + "https://github.com/gokayfem/ComfyUI-Dream-Interpreter": [ + [ + "DreamViewer" + ], + { + "title_aux": "ComfyUI-Dream-Interpreter" + } + ], + "https://github.com/gokayfem/ComfyUI-Texture-Simple": [ + [ + "TextureViewer" + ], + { + "title_aux": "ComfyUI-Texture-Simple" + } + ], + "https://github.com/gokayfem/ComfyUI_VLM_nodes": [ + [ + "AudioLDM2Node", + "ChatMusician", + "CreativeArtPromptGenerator", + "Internlm", + "Joytag", + "JsonToText", + "KeywordExtraction", + "Kosmos2model", + "LLMLoader", + "LLMPromptGenerator", + "LLMSampler", + "LLava Loader Simple", + "LLavaOptionalMemoryFreeAdvanced", + "LLavaOptionalMemoryFreeSimple", + "LLavaPromptGenerator", + "LLavaSamplerAdvanced", + "LLavaSamplerSimple", + "LlavaClipLoader", + "MCLLaVAModel", + "MoonDream", + "Moondream2model", + "PlayMusic", + "PromptGenerateAPI", + "SaveAudioNode", + "SimpleText", + "StructuredOutput", + "Suggester", + "UformGen2QwenNode", + "ViewText" + ], + { + "title_aux": "VLM_nodes" + } + ], + "https://github.com/gonzalu/ComfyUI_YFG_Comical": [ + [ + "Image10Switcher_node", + "Image15Switcher_node", + "Image20Switcher_node", + "Image3Switcher_node", + "Image5Switcher_node", + "MonoClip_node", + "PixelArt_node", + "VAEDecodePreview_node", + "image2contrastMask_node", + "image2imbgg_node", + "image_halftone", + "image_histograms_node", + "image_histograms_node_compact", + "images_side_by_side", + "imgbbLoader_node", + "smartCheckpointLoader_node", + "storeURL_node", + "textMaskOverlay_node" + ], + { + "author": "Manny Gonzalez", + "description": "Utility custom nodes for special effects, image manipulation and quality of life tools.", + "nickname": "\ud83d\udc2f YFG Comical Nodes", + "title": "\ud83d\udc2f YFG Comical Nodes", + "title_aux": "\ud83d\ude38 YFG Comical Nodes" + } + ], + "https://github.com/griptape-ai/ComfyUI-Griptape": [ + [ + "Griptape Agent Config: Amazon Bedrock", + "Griptape Agent Config: Anthropic", + "Griptape Agent Config: Google", + "Griptape Agent Config: LM Studio", + "Griptape Agent Config: Ollama", + "Griptape Agent Config: OpenAI", + "Griptape Audio Driver: OpenAI", + "Griptape Combine: Merge Inputs", + "Griptape Combine: Merge Texts", + "Griptape Combine: Rules List", + "Griptape Combine: Tool List", + "Griptape Config: Environment Variables", + "Griptape Convert: Text to CLIP Encode", + "Griptape Convert: Text to Combo", + "Griptape Create: Agent", + "Griptape Create: CLIP Text Encode", + "Griptape Create: Image Variation", + "Griptape Create: Image from Text", + "Griptape Create: Rules", + "Griptape Create: Text", + "Griptape Display: Artifact", + "Griptape Display: Data as Text", + "Griptape Display: Image", + "Griptape Display: Text", + "Griptape Driver: Amazon Bedrock Stable Diffusion", + "Griptape Driver: Amazon Bedrock Titan", + "Griptape Driver: Leonardo.AI", + "Griptape Driver: OpenAI Image Generation", + "Griptape Expand: Agent Nodes", + "Griptape Load: Audio", + "Griptape Load: Image From URL", + "Griptape Run: Agent", + "Griptape Run: Audio Transcription", + "Griptape Run: Image Description", + "Griptape Run: Parallel Image Description", + "Griptape Run: Prompt Task", + "Griptape Run: Text Summary", + "Griptape Run: Tool Task", + "Griptape Run: Toolkit Task", + "Griptape Set: Default Agent", + "Griptape Tool: Audio Transcription", + "Griptape Tool: Calculator", + "Griptape Tool: DateTime", + "Griptape Tool: FileManager", + "Griptape Tool: Griptape Cloud KnowledgeBase", + "Griptape Tool: WebScraper", + "Griptape Tool: WebSearch" + ], + { + "author": "Jason Schleifer", + "description": "This extension offers various nodes that allow you to work with LLMs using the Griptape Python Framework (https://griptape.ai)", + "nickname": "ComfyUI-Griptape", + "title": "ComfyUI Griptape Nodes", + "title_aux": "ComfyUI Griptape Nodes" + } + ], + "https://github.com/guill/abracadabra-comfyui": [ + [ + "AbracadabraNode", + "AbracadabraNodeDefSummary" + ], + { + "title_aux": "abracadabra-comfyui" + } + ], + "https://github.com/guoyk93/yk-node-suite-comfyui": [ + [ + "YKImagePadForOutpaint", + "YKMaskToImage" + ], + { + "title_aux": "y.k.'s ComfyUI node suite" + } + ], + "https://github.com/hackkhai/ComfyUI-Image-Matting": [ + [ + "ApplyMatting", + "CreateTrimap", + "MattingModelLoader" + ], + { + "title_aux": "ComfyUI-Image-Matting" + } + ], + "https://github.com/haohaocreates/ComfyUI-HH-Image-Selector": [ + [ + "Image Selector" + ], + { + "title_aux": "ComfyUI-HH-Image-Selector" + } + ], + "https://github.com/hay86/ComfyUI_AceNodes": [ + [ + "ACE_AnyInputSwitchBool", + "ACE_AudioLoad", + "ACE_AudioPlay", + "ACE_AudioSave", + "ACE_Expression_Eval", + "ACE_Float", + "ACE_ImageColorFix", + "ACE_ImageConstrain", + "ACE_ImageFaceCrop", + "ACE_ImageGetSize", + "ACE_ImageLoadFromCloud", + "ACE_ImageQA", + "ACE_ImageRemoveBackground", + "ACE_ImageSaveToCloud", + "ACE_Integer", + "ACE_MaskBlur", + "ACE_Seed", + "ACE_Text", + "ACE_TextConcatenate", + "ACE_TextGoogleTranslate", + "ACE_TextInputSwitch2Way", + "ACE_TextInputSwitch4Way", + "ACE_TextInputSwitch8Way", + "ACE_TextList", + "ACE_TextPreview", + "ACE_TextSelector", + "ACE_TextToResolution", + "ACE_TextTranslate" + ], + { + "title_aux": "ComfyUI AceNodes" + } + ], + "https://github.com/hay86/ComfyUI_DDColor": [ + [ + "D_DDColor" + ], + { + "title_aux": "ComfyUI DDColor" + } + ], + "https://github.com/hay86/ComfyUI_Dreamtalk": [ + [ + "D_DreamTalk" + ], + { + "title_aux": "ComfyUI Dreamtalk" + } + ], + "https://github.com/hay86/ComfyUI_Hallo": [ + [ + "D_HalloNode" + ], + { + "title_aux": "ComfyUI Hallo" + } + ], + "https://github.com/hay86/ComfyUI_MiniCPM-V": [ + [ + "D_MiniCPM_VQA" + ], + { + "title_aux": "ComfyUI MiniCPM-V" + } + ], + "https://github.com/hay86/ComfyUI_OpenVoice": [ + [ + "D_OpenVoice_STS", + "D_OpenVoice_TTS", + "D_OpenVoice_TTS_V2" + ], + { + "title_aux": "ComfyUI OpenVoice" + } + ], + "https://github.com/hben35096/ComfyUI-ToolBox": [ + [ + "AutoDLDownload", + "FolderDeleter", + "FolderViewe" + ], + { + "title_aux": "ComfyUI-ToolBox" + } + ], + "https://github.com/heshengtao/comfyui_LLM_party": [ + [ + "About_us", + "CLIPTextEncode_party", + "CosyVoice", + "Dingding", + "Dingding_tool", + "KG_csv_toolkit_developer", + "KG_csv_toolkit_user", + "KG_json_toolkit_developer", + "KG_json_toolkit_user", + "KG_neo_toolkit_developer", + "KG_neo_toolkit_user", + "KSampler_party", + "LLM", + "LLM_api_loader", + "LLM_local", + "LLM_local_loader", + "LLavaLoader", + "VAEDecode_party", + "accuweather_tool", + "api_tool", + "arxiv_tool", + "bing_tool", + "check_web_tool", + "classify_function", + "classify_function_plus", + "classify_persona", + "classify_persona_plus", + "custom_persona", + "ebd_tool", + "end_dialog", + "end_workflow", + "feishu", + "feishu_tool", + "file_combine", + "file_combine_plus", + "get_string", + "github_tool", + "google_tool", + "image_iterator", + "interpreter_tool", + "json_get_value", + "json_parser", + "keyword_tool", + "listen_audio", + "llama_guff_loader", + "load_embeddings", + "load_excel", + "load_file", + "load_file_folder", + "load_keyword", + "load_name", + "load_persona", + "load_url", + "load_wikipedia", + "new_interpreter_tool", + "omost_decode", + "omost_setting", + "openai_tts", + "openai_whisper", + "play_audio", + "replace_string", + "show_text_party", + "start_dialog", + "start_workflow", + "story_json_tool", + "string_logic", + "substring", + "text_iterator", + "time_tool", + "tool_combine", + "tool_combine_plus", + "translate_persona", + "weather_tool", + "weekday_tool", + "wikipedia_tool", + "work_wechat", + "work_wechat_tool", + "workflow_tool", + "workflow_transfer" + ], + { + "title_aux": "comfyui_LLM_party" + } + ], + "https://github.com/hhhzzyang/Comfyui_Lama": [ + [ + "LamaApply", + "LamaModelLoader", + "YamlConfigLoader" + ], + { + "title_aux": "Comfyui-Lama" + } + ], + "https://github.com/hiforce/comfyui-hiforce-plugin": [ + [ + "HfBoolSwitchKSampleStatus", + "HfImageAutoExpansionSquare", + "HfImageToRGB", + "HfImageToRGBA", + "HfInitImageWithMaxSize", + "HfIterativeLatentUpscale", + "HfLoadImageWithCropper", + "HfLookbackSamplerLoader", + "HfLoopback", + "HfResizeImage", + "HfSampler", + "HfSamplerLoader", + "HfSamplerLoopback", + "HfSaveImage", + "HfSwitchKSampleStatus", + "HfTwoSamplersForMask", + "HfTwoStepSamplers", + "LoadImageFromURL" + ], + { + "title_aux": "Comfyui HiFORCE Plugin" + } + ], + "https://github.com/hinablue/ComfyUI_3dPoseEditor": [ + [ + "Hina.PoseEditor3D" + ], + { + "title_aux": "ComfyUI 3D Pose Editor" + } + ], + "https://github.com/holchan/ComfyUI-ModelDownloader": [ + [ + "LoRADownloader", + "ModelDownloader" + ], + { + "title_aux": "ComfyUI-ModelDownloader" + } + ], + "https://github.com/huagetai/ComfyUI-Gaffer": [ + [ + "ApplyICLight", + "CalculateNormalMap", + "GrayScaler", + "ICLightModelLoader", + "LightSource" + ], + { + "title_aux": "comfyui's gaffer(ComfyUI native implementation of IC-Light. )" + } + ], + "https://github.com/huagetai/ComfyUI_LightGradient": [ + [ + "ImageGradient", + "MaskGradient" + ], + { + "title_aux": "Light Gradient for ComfyUI" + } + ], + "https://github.com/huchenlei/ComfyUI-IC-Light-Native": [ + [ + "ICLightApplyMaskGrey", + "ICLightAppply", + "VAEEncodeArgMax" + ], + { + "title_aux": "ComfyUI-IC-Light-Native" + } + ], + "https://github.com/huchenlei/ComfyUI-layerdiffuse": [ + [ + "LayeredDiffusionApply", + "LayeredDiffusionCondApply", + "LayeredDiffusionCondJointApply", + "LayeredDiffusionDecode", + "LayeredDiffusionDecodeRGBA", + "LayeredDiffusionDecodeSplit", + "LayeredDiffusionDiffApply", + "LayeredDiffusionJointApply" + ], + { + "title_aux": "ComfyUI-layerdiffuse (layerdiffusion)" + } + ], + "https://github.com/huchenlei/ComfyUI-openpose-editor": [ + [ + "huchenlei.LoadOpenposeJSON" + ], + { + "title_aux": "ComfyUI-openpose-editor" + } + ], + "https://github.com/huchenlei/ComfyUI_DanTagGen": [ + [ + "PromptDanTagGen" + ], + { + "title_aux": "ComfyUI_DanTagGen" + } + ], + "https://github.com/huchenlei/ComfyUI_densediffusion": [ + [ + "DenseDiffusionAddCondNode", + "DenseDiffusionApplyNode" + ], + { + "title_aux": "ComfyUI DenseDiffusion" + } + ], + "https://github.com/huchenlei/ComfyUI_omost": [ + [ + "OmostDenseDiffusionLayoutNode", + "OmostGreedyBagsTextEmbeddingNode", + "OmostLLMChatNode", + "OmostLLMHTTPServerNode", + "OmostLLMLoaderNode", + "OmostLayoutCondNode", + "OmostLoadCanvasConditioningNode", + "OmostLoadCanvasPythonCodeNode", + "OmostRenderCanvasConditioningNode" + ], + { + "title_aux": "ComfyUI_omost" + } + ], + "https://github.com/hughescr/ComfyUI-OpenPose-Keypoint-Extractor": [ + [ + "Openpose Keypoint Extractor" + ], + { + "title_aux": "OpenPose Keypoint Extractor" + } + ], + "https://github.com/hustille/ComfyUI_Fooocus_KSampler": [ + [ + "KSampler With Refiner (Fooocus)" + ], + { + "title_aux": "ComfyUI_Fooocus_KSampler" + } + ], + "https://github.com/hustille/ComfyUI_hus_utils": [ + [ + "3way Prompt Styler", + "Batch State", + "Date Time Format", + "Debug Extra", + "Fetch widget value", + "Text Hash" + ], + { + "title_aux": "hus' utils for ComfyUI" + } + ], + "https://github.com/hwhaocool/ComfyUI-Select-Any": [ + [ + "SelectAnyValues" + ], + { + "title_aux": "ComfyUI-Select-Any" + } + ], + "https://github.com/hylarucoder/ComfyUI-Eagle-PNGInfo": [ + [ + "EagleImageNode", + "SDXLPromptStyler", + "SDXLPromptStylerAdvanced", + "SDXLResolutionPresets" + ], + { + "title_aux": "Eagle PNGInfo" + } + ], + "https://github.com/hyunamy/comfy-ui-on-complete-email-me": [ + [ + "OnCompleteEmailMe", + "OnCompleteWebhook" + ], + { + "title_aux": "Comfy-UI on-complete-email-me" + } + ], + "https://github.com/iFREEGROUP/comfyui-undistort": [ + [ + "IG_LoadCheckerboardImageForCalibrateCamera", + "IG_MatrixAndDistCoefToText", + "IG_Undistort" + ], + { + "title_aux": "comfyui-undistort" + } + ], + "https://github.com/icesun963/ComfyUI_HFDownLoad": [ + [ + "HFDownLoad_Tool" + ], + { + "title_aux": "HFDownLoad Node for ComfyUI" + } + ], + "https://github.com/idrirap/ComfyUI-Lora-Auto-Trigger-Words": [ + [ + "FusionText", + "LoraListNames", + "LoraLoaderAdvanced", + "LoraLoaderStackedAdvanced", + "LoraLoaderStackedVanilla", + "LoraLoaderVanilla", + "LoraTagsOnly", + "Randomizer", + "TagsFormater", + "TagsSelector", + "TextInputBasic" + ], + { + "title_aux": "ComfyUI-Lora-Auto-Trigger-Words" + } + ], + "https://github.com/iemesowum/ComfyUI_IsaacNodes": [ + [ + "I_BinaryAmplitudeGate", + "I_UnmixAudio", + "I_WeightsListToWeights" + ], + { + "author": "Isaac Emesowum", + "description": "This extension offers automatic drums extraction from audio files, as well as a few helper nodes to support my audio synchronization AnimateDiff workflows.", + "nickname": "Isaac's Nodes", + "title": "Isaac's Nodes", + "title_aux": "Isaac's Nodes" + } + ], + "https://github.com/if-ai/ComfyUI-IF_AI_HFDownloaderNode": [ + [ + "IF_HFDownload", + "IF_HFDownloadNode" + ], + { + "title_aux": "ComfyUI-IF_AI_HFDownloaderNode" + } + ], + "https://github.com/if-ai/ComfyUI-IF_AI_WishperSpeechNode": [ + [ + "IF_WhisperSpeech" + ], + { + "title_aux": "ComfyUI-IF_AI_WishperSpeechNode" + } + ], + "https://github.com/if-ai/ComfyUI-IF_AI_tools": [ + [ + "IF_ChatPrompt", + "IF_DisplayText", + "IF_ImagePrompt", + "IF_PromptMkr", + "IF_SaveText", + "IF_saveText" + ], + { + "title_aux": "ComfyUI-IF_AI_tools" + } + ], + "https://github.com/imb101/ComfyUI-FaceSwap": [ + [ + "FaceSwapNode" + ], + { + "title_aux": "FaceSwap" + } + ], + "https://github.com/iwanders/ComfyUI_nodes": [ + [ + "IW_JsonPickItem", + "IW_ModelHook", + "IW_StringConcat", + "IW_StringNode", + "IW_StringPrint", + "IW_StringReplace", + "IW_StringSave", + "IW_TokenizerVocab" + ], + { + "title_aux": "iwanders/ComfyUI_nodes" + } + ], + "https://github.com/jags111/ComfyUI_Jags_Audiotools": [ + [ + "BatchJoinAudio", + "BatchToList", + "BitCrushAudioFX", + "BulkVariation", + "ChorusAudioFX", + "ClippingAudioFX", + "CompressorAudioFX", + "ConcatAudioList", + "ConvolutionAudioFX", + "CutAudio", + "DelayAudioFX", + "DistortionAudioFX", + "DuplicateAudio", + "GainAudioFX", + "GenerateAudioSample", + "GenerateAudioWave", + "GetAudioFromFolderIndex", + "GetSingle", + "GetStringByIndex", + "HighShelfFilter", + "HighpassFilter", + "ImageToSpectral", + "InvertAudioFX", + "JoinAudio", + "LadderFilter", + "LimiterAudioFX", + "ListToBatch", + "LoadAudioDir", + "LoadAudioFile", + "LoadAudioModel (DD)", + "LoadVST3", + "LowShelfFilter", + "LowpassFilter", + "MP3CompressorAudioFX", + "MixAudioTensors", + "NoiseGateAudioFX", + "OTTAudioFX", + "PeakFilter", + "PhaserEffectAudioFX", + "PitchShiftAudioFX", + "PlotSpectrogram", + "PreviewAudioFile", + "PreviewAudioTensor", + "ResampleAudio", + "ReverbAudioFX", + "ReverseAudio", + "SaveAudioTensor", + "SequenceVariation", + "SliceAudio", + "SoundPlayer", + "StretchAudio", + "samplerate" + ], + { + "author": "jags111", + "description": "This extension offers various audio generation tools", + "nickname": "Audiotools", + "title": "Jags_Audiotools", + "title_aux": "Jags_Audiotools" + } + ], + "https://github.com/jags111/ComfyUI_Jags_VectorMagic": [ + [ + "CircularVAEDecode", + "JagsCLIPSeg", + "JagsClipseg", + "JagsCombineMasks", + "SVG", + "YoloSEGdetectionNode", + "YoloSegNode", + "color_drop", + "xy_Tiling_KSampler" + ], + { + "author": "jags111", + "description": "This extension offers various vector manipulation and generation tools", + "nickname": "Jags_VectorMagic", + "title": "Jags_VectorMagic", + "title_aux": "Jags_VectorMagic" + } + ], + "https://github.com/jags111/efficiency-nodes-comfyui": [ + [ + "AnimateDiff Script", + "Apply ControlNet Stack", + "Control Net Stacker", + "Eff. Loader SDXL", + "Efficient Loader", + "HighRes-Fix Script", + "Image Overlay", + "Join XY Inputs of Same Type", + "KSampler (Efficient)", + "KSampler Adv. (Efficient)", + "KSampler SDXL (Eff.)", + "LatentUpscaler", + "LoRA Stack to String converter", + "LoRA Stacker", + "Manual XY Entry Info", + "NNLatentUpscale", + "Noise Control Script", + "Pack SDXL Tuple", + "Tiled Upscaler Script", + "Unpack SDXL Tuple", + "XY Input: Add/Return Noise", + "XY Input: Aesthetic Score", + "XY Input: CFG Scale", + "XY Input: Checkpoint", + "XY Input: Clip Skip", + "XY Input: Control Net", + "XY Input: Control Net Plot", + "XY Input: Denoise", + "XY Input: LoRA", + "XY Input: LoRA Plot", + "XY Input: LoRA Stacks", + "XY Input: Manual XY Entry", + "XY Input: Prompt S/R", + "XY Input: Refiner On/Off", + "XY Input: Sampler/Scheduler", + "XY Input: Seeds++ Batch", + "XY Input: Steps", + "XY Input: VAE", + "XY Plot" + ], + { + "title_aux": "Efficiency Nodes for ComfyUI Version 2.0+" + } + ], + "https://github.com/jakechai/ComfyUI-JakeUpgrade": [ + [ + "Animation Prompt JK", + "Animation Value JK", + "Base Image Parameters Extract JK", + "Base Model Parameters Extract JK", + "Base Model Parameters JK", + "Base Model Pipe Extract JK", + "Base Model Pipe JK", + "CM_BoolBinaryOperation JK", + "CM_BoolToInt JK", + "CM_BoolUnaryOperation JK", + "CM_BreakoutVec2 JK", + "CM_BreakoutVec3 JK", + "CM_BreakoutVec4 JK", + "CM_ComposeVec2 JK", + "CM_ComposeVec3 JK", + "CM_ComposeVec4 JK", + "CM_FloatBinaryCondition JK", + "CM_FloatBinaryOperation JK", + "CM_FloatToInt JK", + "CM_FloatToNumber JK", + "CM_FloatUnaryCondition JK", + "CM_FloatUnaryOperation JK", + "CM_IntBinaryCondition JK", + "CM_IntBinaryOperation JK", + "CM_IntToBool JK", + "CM_IntToFloat JK", + "CM_IntToNumber JK", + "CM_IntUnaryCondition JK", + "CM_IntUnaryOperation JK", + "CM_NumberBinaryCondition JK", + "CM_NumberBinaryOperation JK", + "CM_NumberToFloat JK", + "CM_NumberToInt JK", + "CM_NumberUnaryCondition JK", + "CM_NumberUnaryOperation JK", + "CM_Vec2BinaryCondition JK", + "CM_Vec2BinaryOperation JK", + "CM_Vec2FloatOperation_JK", + "CM_Vec2ToFloatBinaryOperation JK", + "CM_Vec2ToFloatUnaryOperation JK", + "CM_Vec2UnaryCondition JK", + "CM_Vec2UnaryOperation JK", + "CM_Vec3BinaryCondition JK", + "CM_Vec3BinaryOperation JK", + "CM_Vec3FloatOperation_JK", + "CM_Vec3ToFloatBinaryOperation JK", + "CM_Vec3ToFloatUnaryOperation JK", + "CM_Vec3UnaryCondition JK", + "CM_Vec3UnaryOperation JK", + "CM_Vec4BinaryCondition JK", + "CM_Vec4BinaryOperation JK", + "CM_Vec4FloatOperation_JK", + "CM_Vec4ToFloatBinaryOperation JK", + "CM_Vec4ToFloatUnaryOperation JK", + "CM_Vec4UnaryCondition JK", + "CM_Vec4UnaryOperation JK", + "CR Apply ControlNet JK", + "CR Apply Multi-ControlNet JK", + "CR Boolean JK", + "CR Clip Input Switch JK", + "CR Conditioning Input Switch JK", + "CR ControlNet Input Switch JK", + "CR Float Input Switch JK", + "CR Image Input Switch JK", + "CR Impact Pipe Input Switch JK", + "CR Int Input Switch JK", + "CR Latent Input Switch JK", + "CR LoRA Stack JK", + "CR Load LoRA JK", + "CR Mask Input Switch JK", + "CR Model Input Switch JK", + "CR Multi-ControlNet Stack JK", + "CR Pipe Input Switch JK", + "CR SD1.5 Aspect Ratio JK", + "CR SDXL Aspect Ratio JK", + "CR Switch Model and CLIP JK", + "CR Text Input Switch JK", + "CR VAE Input Switch JK", + "Ckpt Loader JK", + "Detailer Parameters JK", + "Embedding Picker JK", + "Embedding Picker Multi JK", + "Evaluate Examples JK", + "Evaluate Floats JK", + "Evaluate Ints JK", + "Evaluate Strings JK", + "HintImageEnchance JK", + "Image Upscale Parameters Extract JK", + "Ksampler Parameters JK", + "Latent Upscale Parameters Extract JK", + "Load Image With Metadata JK", + "Metadata Pipe Extract JK", + "Metadata Pipe JK", + "NodesState JK", + "Noise Injection Parameters JK", + "Orbit Poses JK", + "Pipe End JK", + "Project Setting JK", + "Refine 1 Parameters Extract JK", + "Refine 2 Parameters Extract JK", + "Refine Model Parameters JK", + "Refine Pipe Extract JK", + "Refine Pipe JK", + "Reroute Ckpt JK", + "Reroute List JK", + "Reroute Resize JK", + "Reroute Sampler JK", + "Reroute Upscale JK", + "Reroute Vae JK", + "SDXLPromptStylerAll", + "SDXLPromptStylerHorror", + "SDXLPromptStylerMisc", + "SDXLPromptStylerbyArtist", + "SDXLPromptStylerbyCamera", + "SDXLPromptStylerbyComposition", + "SDXLPromptStylerbyCyberpunkSurrealism", + "SDXLPromptStylerbyDepth", + "SDXLPromptStylerbyDiva", + "SDXLPromptStylerbyEnvironment", + "SDXLPromptStylerbyFantasySetting", + "SDXLPromptStylerbyFilter", + "SDXLPromptStylerbyFocus", + "SDXLPromptStylerbyFooocus", + "SDXLPromptStylerbyImpressionism", + "SDXLPromptStylerbyLighting", + "SDXLPromptStylerbyMarc", + "SDXLPromptStylerbyMileHigh", + "SDXLPromptStylerbyMood", + "SDXLPromptStylerbyMre", + "SDXLPromptStylerbyMythicalCreature", + "SDXLPromptStylerbyOriginal", + "SDXLPromptStylerbyQuantumRealism", + "SDXLPromptStylerbySai", + "SDXLPromptStylerbySteamPunkRealism", + "SDXLPromptStylerbySubject", + "SDXLPromptStylerbySurrealism", + "SDXLPromptStylerbyTheme", + "SDXLPromptStylerbyTimeofDay", + "SDXLPromptStylerbyTwri", + "SDXLPromptStylerbyWyvern", + "SDXLPromptbyCelticArt", + "SDXLPromptbyContemporaryNordicArt", + "SDXLPromptbyFashionArt", + "SDXLPromptbyGothicRevival", + "SDXLPromptbyIrishFolkArt", + "SDXLPromptbyRomanticNationalismArt", + "SDXLPromptbySportsArt", + "SDXLPromptbyStreetArt", + "SDXLPromptbyVikingArt", + "SDXLPromptbyWildlifeArt", + "Sampler Loader JK", + "Save Image with Metadata Flow JK", + "Save Image with Metadata JK", + "Upscale Model Loader JK", + "Upscale Model Parameters Extract JK", + "Upscale Model Parameters JK", + "Vae Loader JK" + ], + { + "title_aux": "ComfyUI-JakeUpgrade" + } + ], + "https://github.com/jamal-alkharrat/ComfyUI_rotate_image": [ + [ + "RotateImage" + ], + { + "title_aux": "ComfyUI_rotate_image" + } + ], + "https://github.com/jamesWalker55/comfyui-p2ldgan": [ + [ + "P2LDGAN" + ], + { + "title_aux": "ComfyUI - P2LDGAN Node" + } + ], + "https://github.com/jamesWalker55/comfyui-various": [ + [ + "BatchLoadImage", + "BatchSaveImage", + "GroupInfoExtractFloat", + "GroupInfoExtractInt", + "GroupLoadBatchImages", + "GroupLoadImage", + "JWDatetimeString", + "JWImageBatchCount", + "JWImageContrast", + "JWImageExtractFromBatch", + "JWImageFlip", + "JWImageLevels", + "JWImageLoadRGB", + "JWImageLoadRGBA", + "JWImageLoadRGBIfExists", + "JWImageMix", + "JWImageResize", + "JWImageResizeByFactor", + "JWImageResizeByLongerSide", + "JWImageResizeByShorterSide", + "JWImageResizeToSquare", + "JWImageSaturation", + "JWImageSaveToPath", + "JWImageSequenceExtractFromBatch", + "JWImageStackChannels", + "JWInfoHashExtractFloat", + "JWInfoHashExtractInteger", + "JWInfoHashExtractString", + "JWInfoHashFromInfoHashList", + "JWInfoHashFromRangedInfo", + "JWInfoHashListExtractStringList", + "JWInfoHashListFromRangedInfo", + "JWInfoHashPrint", + "JWLoadImageSequence", + "JWLoadImagesFromString", + "JWLoopImageSequence", + "JWMaskLikeImageSize", + "JWMaskResize", + "JWMaskSequenceApplyToLatent", + "JWMaskSequenceFromMask", + "JWMaskSequenceJoin", + "JWPrintFloat", + "JWPrintImage", + "JWPrintInteger", + "JWPrintLatent", + "JWPrintMask", + "JWPrintString", + "JWRangedInfoCalculateSubBatch", + "JWReferenceOnly", + "JWSaveImageSequence", + "JWStringListCLIPEncode", + "JWStringListFromString", + "JWStringListFromStrings", + "JWStringListJoin", + "JWStringListRepeat", + "JWStringListToFormatedString", + "JWStringListToString", + "JWUncropCrop", + "JWUncropNewRect", + "JWUncropUncrop", + "JamesLoadImageGroup", + "RAFTEstimate", + "RAFTFlowToImage", + "RAFTLoadFlowFromEXRChannels", + "RCReceiveFloat", + "RCReceiveFloatList", + "RCReceiveInt", + "RCReceiveIntList", + "RCReceiveLatent", + "RCSendLatent" + ], + { + "nodename_pattern": "^JW", + "title_aux": "Various ComfyUI Nodes by Type" + } + ], + "https://github.com/jax-explorer/fast_video_comfyui": [ + [ + "FastImageListToImageBatch" + ], + { + "title_aux": "fast_video_comfyui" + } + ], + "https://github.com/jeffy5/comfyui-faceless-node": [ + [ + "FacelessFaceRestore", + "FacelessFaceSwap", + "FacelessLoadFrames", + "FacelessLoadImageUrl", + "FacelessLoadVideo", + "FacelessLoadVideoUrl", + "FacelessMergeVideos", + "FacelessRemoveBackground", + "FacelessSaveVideo", + "FacelessUploadVideo", + "FacelessVideoFaceRestore", + "FacelessVideoFaceSwap", + "FacelessVideoRemoveBackground" + ], + { + "title_aux": "Faceless Node for ComfyUI" + } + ], + "https://github.com/jesenzhang/ComfyUI_StreamDiffusion": [ + [ + "StreamDiffusion_Loader", + "StreamDiffusion_Sampler" + ], + { + "title_aux": "ComfyUI_StreamDiffusion" + } + ], + "https://github.com/jiaxiangc/ComfyUI-ResAdapter": [ + [ + "ResAdapterLoader" + ], + { + "title_aux": "ResAdapter for ComfyUI" + } + ], + "https://github.com/jitcoder/lora-info": [ + [ + "ImageFromURL", + "LoraInfo" + ], + { + "title_aux": "LoraInfo" + } + ], + "https://github.com/jjkramhoeft/ComfyUI-Jjk-Nodes": [ + [ + "JjkConcat", + "JjkShowText", + "JjkText", + "SDXLRecommendedImageSize" + ], + { + "title_aux": "ComfyUI-Jjk-Nodes" + } + ], + "https://github.com/jkrauss82/ultools-comfyui": [ + [ + "CLIPTextEncodeWithStats", + "OpenPoseEditorAdv", + "SaveImgAdv", + "SolidMaskAdv" + ], + { + "title_aux": "ULTools for ComfyUI" + } + ], + "https://github.com/jojkaart/ComfyUI-sampler-lcm-alternative": [ + [ + "LCMScheduler", + "SamplerLCMAlternative", + "SamplerLCMCycle", + "SamplerLCMDualNoise" + ], + { + "title_aux": "ComfyUI-sampler-lcm-alternative" + } + ], + "https://github.com/jordoh/ComfyUI-Deepface": [ + [ + "DeepfaceExtractFaces", + "DeepfaceVerify" + ], + { + "title_aux": "ComfyUI Deepface" + } + ], + "https://github.com/jroc22/ComfyUI-CSV-prompt-builder": [ + [ + "BuildPromptFromCSV" + ], + { + "title_aux": "ComfyUI-CSV-prompt-builder" + } + ], + "https://github.com/jtrue/ComfyUI-JaRue": [ + [ + "Text2Image_jru", + "YouTube2Prompt_jru" + ], + { + "nodename_pattern": "_jru$", + "title_aux": "ComfyUI-JaRue" + } + ], + "https://github.com/jtydhr88/ComfyUI-LayerDivider": [ + [ + "LayerDivider - Color Base", + "LayerDivider - Divide Layer", + "LayerDivider - Load SAM Mask Generator", + "LayerDivider - Segment Mask" + ], + { + "title_aux": "ComfyUI LayerDivider" + } + ], + "https://github.com/jtydhr88/ComfyUI-Unique3D": [ + [ + "Unique3DLoadPipeline", + "Unique3DRun - Geo Reconstruct", + "Unique3DRun - MVPrediction" + ], + { + "title_aux": "ComfyUI Unique3D" + } + ], + "https://github.com/ka-puna/comfyui-yanc": [ + [ + "YANC.ConcatStrings", + "YANC.FormatDatetimeString", + "YANC.GetWidgetValueString", + "YANC.IntegerCaster", + "YANC.MultilineString", + "YANC.TruncateString" + ], + { + "title_aux": "comfyui-yanc" + } + ], + "https://github.com/kaanyalova/ComfyUI_ExtendedImageFormats": [ + [ + "ExtendedSaveImage" + ], + { + "title_aux": "Extended Image Formats for ComfyUI" + } + ], + "https://github.com/kadirnar/ComfyUI-Transformers": [ + [ + "DepthEstimationInference", + "ImageClassificationPipeline", + "ImageSegmentationPipeline", + "LoadDepthModel", + "ObjectDetectionPipeline" + ], + { + "title_aux": "ComfyUI-Transformers" + } + ], + "https://github.com/kadirnar/ComfyUI-YOLO": [ + [ + "BBoxToCoco", + "BBoxToXYWH", + "BBoxVisNode", + "CocoToNumber", + "ConvertToDict", + "CustomUltralyticsModelLoader", + "GetImageSize", + "ImageResizeAdvanced", + "UltralyticsInference", + "UltralyticsModelLoader", + "UltralyticsVisualization", + "ViewText" + ], + { + "title_aux": "ComfyUI-YOLO" + } + ], + "https://github.com/kale4eat/ComfyUI-path-util": [ + [ + "path_util_PathAbspath", + "path_util_PathBasename", + "path_util_PathDirname", + "path_util_PathExists", + "path_util_PathIsdir", + "path_util_PathIsfile", + "path_util_PathJoin", + "path_util_PathRelpath", + "path_util_PathSplitext" + ], + { + "title_aux": "ComfyUI_demucus" + } + ], + "https://github.com/kale4eat/ComfyUI-speech-dataset-toolkit": [ + [ + "SDT_AudioProperty", + "SDT_ConcatAudio", + "SDT_CutAudio", + "SDT_DemucsApply", + "SDT_DemucsLoader", + "SDT_FasterWhisperListSegments", + "SDT_FasterWhisperLoader", + "SDT_FasterWhisperSegmentProperty", + "SDT_FasterWhisperTextFromSegments", + "SDT_FasterWhisperTranscribe", + "SDT_GriffinLim", + "SDT_JoinAudio", + "SDT_KotobaWhisperListSegments", + "SDT_KotobaWhisperLoaderLong", + "SDT_KotobaWhisperLoaderShort", + "SDT_KotobaWhisperSegmentProperty", + "SDT_KotobaWhisperTranscribeLong", + "SDT_KotobaWhisperTranscribeShort", + "SDT_LFCC", + "SDT_LoadAudio", + "SDT_LoadAudios", + "SDT_MFCC", + "SDT_MakeSilenceAudio", + "SDT_MelSpectrogram", + "SDT_NemoAsrListSegments", + "SDT_NemoAsrListSubwords", + "SDT_NemoAsrLoader", + "SDT_NemoAsrSegmentProperty", + "SDT_NemoAsrSubwordProperty", + "SDT_NemoAsrTranscribe", + "SDT_NueAsrLoader", + "SDT_NueAsrTranscribe", + "SDT_PlayAudio", + "SDT_PlotMelFilterBank", + "SDT_PlotPitch", + "SDT_PlotSpecgram", + "SDT_PlotSpectrogram", + "SDT_PlotWaveForm", + "SDT_ResampleAudio", + "SDT_SaveAudio", + "SDT_SaveAudioWithSequentialNumbering", + "SDT_SilenceAudio", + "SDT_SileroVADApply", + "SDT_SileroVADCollectChunks", + "SDT_SileroVADListTimestamps", + "SDT_SileroVADLoader", + "SDT_SileroVADTimestampProperty", + "SDT_Spectrogram", + "SDT_SpeechMOSLoader", + "SDT_SpeechMOSScore", + "SDT_SplitAudio", + "SDT_TrimAudio", + "SDT_TrimAudioBySample" + ], + { + "title_aux": "ComfyUI-speech-dataset-toolkit" + } + ], + "https://github.com/kale4eat/ComfyUI-string-util": [ + [ + "string_util_Str", + "string_util_StrConcat", + "string_util_StrCount", + "string_util_StrEndsWith", + "string_util_StrEqual", + "string_util_StrFind", + "string_util_StrFormat", + "string_util_StrJoin", + "string_util_StrLen", + "string_util_StrLower", + "string_util_StrLstrip", + "string_util_StrNotEqual", + "string_util_StrReplace", + "string_util_StrRstrip", + "string_util_StrSlice", + "string_util_StrSplit", + "string_util_StrStartsWith", + "string_util_StrStrip", + "string_util_StrUpper" + ], + { + "title_aux": "ComfyUI-string-util" + } + ], + "https://github.com/kale4eat/ComfyUI-text-file-util": [ + [ + "text_file_util_ReadAllLines", + "text_file_util_ReadAllText", + "text_file_util_WriteText", + "text_file_util_WriteTextLines", + "text_file_util_WriteTextWithSequentialNumbering" + ], + { + "title_aux": "ComfyUI-text-file-util" + } + ], + "https://github.com/katalist-ai/comfyUI-nsfw-detection": [ + [ + "NudenetDetector" + ], + { + "title_aux": "comfyUI-nsfw-detection" + } + ], + "https://github.com/kealiu/ComfyUI-S3-Tools": [ + [ + "Load Image From S3", + "Save Image To S3" + ], + { + "title_aux": "ComfyUI Load and Save file to S3" + } + ], + "https://github.com/kealiu/ComfyUI-Zero123-Porting": [ + [ + "Zero123: Image Preprocess", + "Zero123: Image Rotate in 3D" + ], + { + "title_aux": "ComfyUI-Zero123-Porting" + } + ], + "https://github.com/kealiu/ComfyUI-ZeroShot-MTrans": [ + [ + "ZeST: Grayout Subject" + ], + { + "title_aux": "ComfyUI-ZeroShot-MTrans" + } + ], + "https://github.com/kenjiqq/qq-nodes-comfyui": [ + [ + "Any List", + "Any List Iterator", + "Any To Any", + "Axis Pack", + "Axis To Any", + "Axis Unpack", + "Image Accumulator End", + "Image Accumulator Start", + "Load Lines From Text File", + "Slice List", + "Text Splitter", + "XY Grid Helper" + ], + { + "title_aux": "qq-nodes-comfyui" + } + ], + "https://github.com/kft334/Knodes": [ + [ + "Image(s) To Websocket (Base64)", + "ImageOutput", + "Load Image (Base64)", + "Load Images (Base64)" + ], + { + "title_aux": "Knodes" + } + ], + "https://github.com/kijai/ComfyUI-ADMotionDirector": [ + [ + "ADMD_AdditionalModelSelect", + "ADMD_CheckpointLoader", + "ADMD_ComfyModelLoader", + "ADMD_DiffusersLoader", + "ADMD_InitializeTraining", + "ADMD_LoadLora", + "ADMD_MakeBatchList", + "ADMD_SaveLora", + "ADMD_TrainLora", + "ADMD_ValidationSampler", + "ADMD_ValidationSettings" + ], + { + "title_aux": "Animatediff MotionLoRA Trainer" + } + ], + "https://github.com/kijai/ComfyUI-APISR-KJ": [ + [ + "APISR_upscale" + ], + { + "title_aux": "ComfyUI-APISR" + } + ], + "https://github.com/kijai/ComfyUI-BrushNet-Wrapper": [ + [ + "brushnet_ella_loader", + "brushnet_ipadapter_matteo", + "brushnet_model_loader", + "brushnet_sampler", + "brushnet_sampler_ella", + "powerpaint_brushnet_sampler" + ], + { + "title_aux": "ComfyUI-BrushNet-Wrapper" + } + ], + "https://github.com/kijai/ComfyUI-CCSR": [ + [ + "CCSR_Model_Select", + "CCSR_Upscale", + "DownloadAndLoadCCSRModel" + ], + { + "title_aux": "ComfyUI-CCSR" + } + ], + "https://github.com/kijai/ComfyUI-DDColor": [ + [ + "DDColor_Colorize" + ], + { + "title_aux": "ComfyUI-DDColor" + } + ], + "https://github.com/kijai/ComfyUI-DepthAnythingV2": [ + [ + "DepthAnything_V2", + "DownloadAndLoadDepthAnythingV2Model" + ], + { + "title_aux": "ComfyUI-DepthAnythingV2" + } + ], + "https://github.com/kijai/ComfyUI-DiffusionLight": [ + [ + "chrome_ball_to_envmap", + "exposure_to_hdr" + ], + { + "title_aux": "DiffusionLight implementation for ComfyUI" + } + ], + "https://github.com/kijai/ComfyUI-DynamiCrafterWrapper": [ + [ + "DownloadAndLoadCLIPModel", + "DownloadAndLoadCLIPVisionModel", + "DownloadAndLoadDynamiCrafterModel", + "DynamiCrafterBatchInterpolation", + "DynamiCrafterI2V", + "DynamiCrafterLoadInitNoise", + "DynamiCrafterModelLoader", + "ToonCrafterDecode", + "ToonCrafterInterpolation" + ], + { + "title_aux": "ComfyUI-DynamiCrafterWrapper" + } + ], + "https://github.com/kijai/ComfyUI-ELLA-wrapper": [ + [ + "diffusers_model_loader", + "diffusers_sampler", + "ella_model_loader", + "ella_sampler", + "ella_t5_embeds" + ], + { + "title_aux": "ComfyUI-ELLA-wrapper" + } + ], + "https://github.com/kijai/ComfyUI-Florence2": [ + [ + "DownloadAndLoadFlorence2Model", + "Florence2Run" + ], + { + "title_aux": "ComfyUI-Florence2" + } + ], + "https://github.com/kijai/ComfyUI-Geowizard": [ + [ + "geowizard_model_loader", + "geowizard_sampler" + ], + { + "title_aux": "Geowizard depth and normal estimation in ComfyUI" + } + ], + "https://github.com/kijai/ComfyUI-IC-Light": [ + [ + "BackgroundScaler", + "CalculateNormalsFromImages", + "DetailTransfer", + "ICLightConditioning", + "LightSource", + "LoadAndApplyICLightUnet", + "LoadHDRImage" + ], + { + "title_aux": "ComfyUI-IC-Light" + } + ], + "https://github.com/kijai/ComfyUI-KJNodes": [ + [ + "AddLabel", + "AppendInstanceDiffusionTracking", + "BatchCLIPSeg", + "BatchCropFromMask", + "BatchCropFromMaskAdvanced", + "BatchUncrop", + "BatchUncropAdvanced", + "BboxToInt", + "BboxVisualize", + "CameraPoseVisualizer", + "CheckpointPerturbWeights", + "ColorMatch", + "ColorToMask", + "CondPassThrough", + "ConditioningMultiCombine", + "ConditioningSetMaskAndCombine", + "ConditioningSetMaskAndCombine3", + "ConditioningSetMaskAndCombine4", + "ConditioningSetMaskAndCombine5", + "CreateAudioMask", + "CreateFadeMask", + "CreateFadeMaskAdvanced", + "CreateFluidMask", + "CreateGradientFromCoords", + "CreateGradientMask", + "CreateInstanceDiffusionTracking", + "CreateMagicMask", + "CreateShapeImageOnPath", + "CreateShapeMask", + "CreateShapeMaskOnPath", + "CreateTextMask", + "CreateTextOnPath", + "CreateVoronoiMask", + "CrossFadeImages", + "CustomSigmas", + "DownloadAndLoadCLIPSeg", + "DrawInstanceDiffusionTracking", + "DummyLatentOut", + "EmptyLatentImagePresets", + "FilterZeroMasksAndCorrespondingImages", + "FlipSigmasAdjusted", + "FloatConstant", + "FloatToMask", + "FloatToSigmas", + "GLIGENTextBoxApplyBatchCoords", + "GenerateNoise", + "GetImageRangeFromBatch", + "GetImageSizeAndCount", + "GetImagesFromBatchIndexed", + "GetLatentsFromBatchIndexed", + "GetMaskSizeAndCount", + "GradientToFloat", + "GrowMaskWithBlur", + "INTConstant", + "ImageAddMulti", + "ImageAndMaskPreview", + "ImageBatchMulti", + "ImageBatchRepeatInterleaving", + "ImageBatchTestPattern", + "ImageConcanate", + "ImageConcatMulti", + "ImageGrabPIL", + "ImageGridComposite2x2", + "ImageGridComposite3x3", + "ImageNormalize_Neg1_To_1", + "ImagePadForOutpaintMasked", + "ImagePadForOutpaintTargetSize", + "ImagePass", + "ImageResizeKJ", + "ImageTransformByNormalizedAmplitude", + "ImageUpscaleWithModelBatched", + "InjectNoiseToLatent", + "InsertImageBatchByIndexes", + "InsertImagesToBatchIndexed", + "InterpolateCoords", + "Intrinsic_lora_sampling", + "JoinStringMulti", + "JoinStrings", + "LoadAndResizeImage", + "LoadResAdapterNormalization", + "MaskBatchMulti", + "MaskOrImageToWeight", + "MergeImageChannels", + "ModelPassThrough", + "NormalizedAmplitudeToFloatList", + "NormalizedAmplitudeToMask", + "OffsetMask", + "OffsetMaskByNormalizedAmplitude", + "PlotCoordinates", + "PreviewAnimation", + "RemapImageRange", + "RemapMaskRange", + "ReplaceImagesInBatch", + "ResizeMask", + "ReverseImageBatch", + "RoundMask", + "SV3D_BatchSchedule", + "SaveImageWithAlpha", + "ScaleBatchPromptSchedule", + "Sleep", + "SomethingToString", + "SoundReactive", + "SplineEditor", + "SplitBboxes", + "SplitImageChannels", + "StabilityAPI_SD3", + "StableZero123_BatchSchedule", + "StringConstant", + "StringConstantMultiline", + "Superprompt", + "VRAM_Debug", + "WeightScheduleConvert", + "WeightScheduleExtend", + "WidgetToString" + ], + { + "title_aux": "KJNodes for ComfyUI" + } + ], + "https://github.com/kijai/ComfyUI-KwaiKolorsWrapper": [ + [ + "DownloadAndLoadChatGLM3", + "DownloadAndLoadKolorsModel", + "KolorsSampler", + "KolorsTextEncode", + "LoadChatGLM3" + ], + { + "title_aux": "ComfyUI-KwaiKolorsWrapper" + } + ], + "https://github.com/kijai/ComfyUI-LaVi-Bridge-Wrapper": [ + [ + "lavi_bridge_llama_encoder", + "lavi_bridge_t5_encoder", + "lavibridge_model_loader", + "lavibridge_sampler" + ], + { + "title_aux": "ComfyUI-LaVi-Bridge-Wrapper" + } + ], + "https://github.com/kijai/ComfyUI-LivePortraitKJ": [ + [ + "DownloadAndLoadLivePortraitModels", + "LivePortraitProcess" + ], + { + "title_aux": "ComfyUI-LivePortraitKJ" + } + ], + "https://github.com/kijai/ComfyUI-LuminaWrapper": [ + [ + "DownloadAndLoadGemmaModel", + "DownloadAndLoadLuminaModel", + "GemmaSampler", + "LuminaGemmaTextEncode", + "LuminaGemmaTextEncodeArea", + "LuminaT2ISampler", + "LuminaTextAreaAppend" + ], + { + "title_aux": "ComfyUI-LuminaWrapper" + } + ], + "https://github.com/kijai/ComfyUI-Marigold": [ + [ + "ColorizeDepthmap", + "MarigoldDepthEstimation", + "MarigoldDepthEstimationVideo", + "MarigoldDepthEstimation_v2", + "MarigoldDepthEstimation_v2_video", + "MarigoldModelLoader", + "RemapDepth", + "SaveImageOpenEXR" + ], + { + "title_aux": "Marigold depth estimation in ComfyUI" + } + ], + "https://github.com/kijai/ComfyUI-MimicMotionWrapper": [ + [ + "DiffusersScheduler", + "DownloadAndLoadMimicMotionModel", + "MimicMotionDecode", + "MimicMotionGetPoses", + "MimicMotionSampler" + ], + { + "title_aux": "ComfyUI-MimicMotionWrapper" + } + ], + "https://github.com/kijai/ComfyUI-OpenDiTWrapper": [ + [ + "DownloadAndLoadOpenDiTT5Model", + "DownloadAndLoadOpenSoraModel", + "DownloadAndLoadOpenSoraVAE", + "OpenDiTConditioning", + "OpenDiTSampler", + "OpenSoraDecode", + "OpenSoraEncodeReference" + ], + { + "title_aux": "ComfyUI-OpenDiTWrapper" + } + ], + "https://github.com/kijai/ComfyUI-SUPIR": [ + [ + "SUPIR_Upscale", + "SUPIR_conditioner", + "SUPIR_decode", + "SUPIR_encode", + "SUPIR_first_stage", + "SUPIR_model_loader", + "SUPIR_model_loader_v2", + "SUPIR_model_loader_v2_clip", + "SUPIR_sample", + "SUPIR_tiles" + ], + { + "title_aux": "ComfyUI-SUPIR" + } + ], + "https://github.com/kijai/ComfyUI-depth-fm": [ + [ + "Depth_fm" + ], + { + "title_aux": "ComfyUI-depth-fm" + } + ], + "https://github.com/kijai/ComfyUI-moondream": [ + [ + "MoondreamQuery", + "MoondreamQueryCaptions" + ], + { + "title_aux": "ComfyUI-moondream" + } + ], + "https://github.com/kinfolk0117/ComfyUI_GradientDeepShrink": [ + [ + "GradientPatchModelAddDownscale", + "GradientPatchModelAddDownscaleAdvanced" + ], + { + "title_aux": "ComfyUI_GradientDeepShrink" + } + ], + "https://github.com/kinfolk0117/ComfyUI_Pilgram": [ + [ + "Pilgram" + ], + { + "title_aux": "ComfyUI_Pilgram" + } + ], + "https://github.com/kinfolk0117/ComfyUI_SimpleTiles": [ + [ + "DynamicTileMerge", + "DynamicTileSplit", + "TileCalc", + "TileMerge", + "TileSplit" + ], + { + "title_aux": "SimpleTiles" + } + ], + "https://github.com/klinter007/klinter_nodes": [ + [ + "Filter", + "Florence2Captions2IPA", + "PresentString", + "SingleString", + "SizeSelector", + "YellowBus", + "concat" + ], + { + "title_aux": "Klinter_nodes" + } + ], + "https://github.com/knuknX/ComfyUI-Image-Tools": [ + [ + "BatchImagePathLoader", + "ImageBgRemoveProcessor", + "ImageCheveretoUploader", + "ImageStandardResizeProcessor", + "JSONMessageNotifyTool", + "PreviewJSONNode", + "SingleImagePathLoader", + "SingleImageUrlLoader" + ], + { + "title_aux": "ComfyUI-Image-Tools" + } + ], + "https://github.com/kohya-ss/ControlNet-LLLite-ComfyUI": [ + [ + "LLLiteLoader" + ], + { + "title_aux": "ControlNet-LLLite-ComfyUI" + } + ], + "https://github.com/komojini/ComfyUI_SDXL_DreamBooth_LoRA_CustomNodes": [ + [ + "S3 Bucket LoRA", + "S3Bucket_Load_LoRA", + "XL DreamBooth LoRA", + "XLDB_LoRA" + ], + { + "title_aux": "ComfyUI_SDXL_DreamBooth_LoRA_CustomNodes" + } + ], + "https://github.com/komojini/komojini-comfyui-nodes": [ + [ + "BatchCreativeInterpolationNodeDynamicSettings", + "CachedGetter", + "DragNUWAImageCanvas", + "FlowBuilder", + "FlowBuilder (adv)", + "FlowBuilder (advanced)", + "FlowBuilder (advanced) Setter", + "FlowBuilderSetter", + "FlowBuilderSetter (adv)", + "Getter", + "ImageCropByRatio", + "ImageCropByRatioAndResize", + "ImageGetter", + "ImageMerger", + "ImagesCropByRatioAndResizeBatch", + "KSamplerAdvancedCacheable", + "KSamplerCacheable", + "Setter", + "UltimateVideoLoader", + "UltimateVideoLoader (simple)", + "YouTubeVideoLoader" + ], + { + "title_aux": "komojini-comfyui-nodes" + } + ], + "https://github.com/kunieone/ComfyUI_alkaid": [ + [ + "A_EmptyLatentImageLongside", + "A_Face3DSwapper", + "A_FaceCrop", + "A_FacePaste", + "A_GetImageSize", + "A_OpenPosePreprocessor", + "AdapterFace", + "AdapterFaceLoader", + "AdapterStyle", + "AdapterStyleLoader", + "AlkaidLoader", + "ApplyAdapter", + "ApplyControlNet_KPS", + "CombineAdapterPatch", + "KSamplerHires" + ], + { + "title_aux": "ComfyUI_alkaid" + } + ], + "https://github.com/kwaroran/abg-comfyui": [ + [ + "Remove Image Background (abg)" + ], + { + "title_aux": "abg-comfyui" + } + ], + "https://github.com/l20richo/ComfyUI-Azure-Blob-Storage": [ + [ + "DownloadFileBLOB", + "LoadImageBLOB", + "SaveImageBLOB", + "SaveVideoFilesBLOB", + "UploadFileBLOB" + ], + { + "title_aux": "ComfyUI-Azure-Blob-Storage" + } + ], + "https://github.com/laksjdjf/Batch-Condition-ComfyUI": [ + [ + "Batch String", + "CLIP Text Encode (Batch)", + "String Input" + ], + { + "title_aux": "Batch-Condition-ComfyUI" + } + ], + "https://github.com/laksjdjf/LCMSampler-ComfyUI": [ + [ + "SamplerLCM", + "TAESDLoader" + ], + { + "title_aux": "LCMSampler-ComfyUI" + } + ], + "https://github.com/laksjdjf/LoRTnoC-ComfyUI": [ + [ + "LortnocLoader" + ], + { + "title_aux": "LoRTnoC-ComfyUI" + } + ], + "https://github.com/laksjdjf/cd-tuner_negpip-ComfyUI": [ + [ + "CDTuner", + "Negapip", + "Negpip" + ], + { + "title_aux": "cd-tuner_negpip-ComfyUI" + } + ], + "https://github.com/laksjdjf/cgem156-ComfyUI": [ + [ + "GradualLatentSampler", + "LCMSamplerRCFG", + "LoadAestheticShadow", + "PredictAesthetic", + "TCDSampler", + "TextScheduler" + ], + { + "title_aux": "cgem156-ComfyUI\ud83c\udf4c" + } + ], + "https://github.com/laksjdjf/pfg-ComfyUI": [ + [ + "PFG" + ], + { + "title_aux": "pfg-ComfyUI" + } + ], + "https://github.com/larsupb/LoRA-Merger-ComfyUI": [ + [ + "PM LoRA Apply", + "PM LoRA Loader", + "PM LoRA Merger", + "PM LoRA Resizer", + "PM LoRA SVD Merger", + "PM LoRA Save", + "XY: PM LoRA Modes", + "XY: PM LoRA SVD Rank", + "XY: PM LoRA Strengths" + ], + { + "title_aux": "LoRA Power-Merger ComfyUI" + } + ], + "https://github.com/latenightlabs/ComfyUI-LNL": [ + [ + "LNL_FrameSelector", + "LNL_FrameSelectorV2", + "LNL_FrameSelectorV3" + ], + { + "title_aux": "LNL Frame Selector" + } + ], + "https://github.com/leiweiqiang/ComfyUI-TRA": [ + [ + "TclEbSynth", + "TclEbSynthBatch", + "TclExtractFramesFromVideo", + "TclExtractFramesFromVideoFile", + "TclFrames2Video", + "TclSaveVideoFromFrames", + "TclYoloV8Segmentation", + "TclYoloV9Segmentation" + ], + { + "title_aux": "ComfyUI-TRA" + } + ], + "https://github.com/leoleelxh/ComfyUI-LLMs": [ + [ + "\ud83d\uddbc\ufe0f LLMs_Vison_Ali", + "\ud83d\uddbc\ufe0f LLMs_Vison_GLM4", + "\ud83d\uddbc\ufe0f LLMs_Vison_Gemini", + "\ud83d\ude00 LLMs_Chat", + "\ud83d\ude00 LLMs_Chat_GLM4_Only" + ], + { + "title_aux": "ComfyUI-LLMs" + } + ], + "https://github.com/linshier/comfyui-remote-tools": [ + [ + "LoadBase64(js)", + "LoadBase64FromRemote", + "SendBase64ToRemote" + ], + { + "title_aux": "comfyui-remote-tools" + } + ], + "https://github.com/liusida/ComfyUI-AutoCropFaces": [ + [ + "AutoCropFaces" + ], + { + "title_aux": "ComfyUI-AutoCropFaces" + } + ], + "https://github.com/liusida/ComfyUI-B-LoRA": [ + [ + "LoadBLoRA" + ], + { + "title_aux": "ComfyUI-B-LoRA" + } + ], + "https://github.com/liusida/ComfyUI-Debug": [ + [ + "DebugInspectorNode", + "DebugModelInspectorNode", + "DebugModelPrintOutNode" + ], + { + "title_aux": "ComfyUI-Debug" + } + ], + "https://github.com/liusida/ComfyUI-Login": [ + [ + "LoadImageIncognito" + ], + { + "title_aux": "ComfyUI-Login" + } + ], + "https://github.com/liusida/ComfyUI-SD3-nodes": [ + [ + "SD3EmptyLatent", + "SD3LoadCLIPs", + "SD3LoadCheckpoint" + ], + { + "title_aux": "ComfyUI-SD3-nodes" + } + ], + "https://github.com/ljleb/comfy-mecha": [ + [ + "Blocks Mecha Hyper", + "Float Mecha Hyper", + "Lora Mecha Recipe", + "Mecha Deserializer", + "Mecha Merger", + "Mecha Recipe List", + "Mecha Serializer", + "Model Mecha Recipe" + ], + { + "title_aux": "Mecha Merge Node Pack" + } + ], + "https://github.com/lks-ai/ComfyUI-StableAudioSampler": [ + [ + "StableAudioConditioning", + "StableAudioLoadModel", + "StableAudioPrompt", + "StableAudioSampler" + ], + { + "author": "lks-ai", + "description": "A Simple integration of Stable Audio Diffusion with knobs and stuff!", + "nickname": "stableaudio", + "title": "StableAudioSampler", + "title_aux": "ComfyUI Stable Audio Open 1.0 Sampler" + } + ], + "https://github.com/lks-ai/anynode": [ + [ + "AnyNode", + "AnyNodeAnthropic", + "AnyNodeCodeViewer", + "AnyNodeExport", + "AnyNodeGemini", + "AnyNodeLocal" + ], + { + "author": "newsbubbles", + "description": "This single node uses an LLM to generate a functionality based on your request. You can make the node do anything.", + "nickname": "AnyNode", + "title": "AnyNode v0.1.1", + "title_aux": "ComfyUI AnyNode: Any Node you ask for" + } + ], + "https://github.com/lldacing/comfyui-easyapi-nodes": [ + [ + "Base64ToImage", + "Base64ToMask", + "ColorPicker", + "GetImageBatchSize", + "ImageEqual", + "ImageToBase64", + "ImageToBase64Advanced", + "InsightFaceBBOXDetect", + "IntToList", + "IntToNumber", + "JoinList", + "ListMerge", + "LoadImageFromURL", + "LoadImageToBase64", + "LoadMaskFromURL", + "MaskImageToBase64", + "MaskToBase64", + "MaskToBase64Image", + "SDBaseVerNumber", + "SamAutoMaskSEGS", + "ShowBoolean", + "ShowFloat", + "ShowInt", + "ShowNumber", + "ShowString", + "StringToList" + ], + { + "title_aux": "comfyui-easyapi-nodes" + } + ], + "https://github.com/logtd/ComfyUI-FLATTEN": [ + [ + "ApplyFlattenAttentionNode", + "CreateFlowNoiseNode", + "FlattenCheckpointLoaderNode", + "KSamplerFlattenNode", + "TrajectoryNode", + "UnsamplerFlattenNode" + ], + { + "title_aux": "ComfyUI-FLATTEN" + } + ], + "https://github.com/logtd/ComfyUI-InstanceDiffusion": [ + [ + "ApplyScaleUModelNode", + "DownloadInstanceDiffusionModels", + "InstanceDiffusionTrackingPrompt", + "LoadInstanceFusersNode", + "LoadInstancePositionNetModel", + "LoadInstanceScaleUNode" + ], + { + "title_aux": "InstanceDiffusion Nodes" + } + ], + "https://github.com/logtd/ComfyUI-InversedNoise": [ + [ + "CombineNoiseLatentNode", + "MixNoiseNode", + "SamplerInversedEulerNode" + ], + { + "title_aux": "ComfyUI-InversedNoise" + } + ], + "https://github.com/logtd/ComfyUI-RAVE_ATTN": [ + [ + "ApplyRaveAttentionNode", + "AttentionOverrideSD15Node", + "AttentionOverrideSDXLNode" + ], + { + "title_aux": "ComfyUI-RAVE Attention" + } + ], + "https://github.com/logtd/ComfyUI-RefSampling": [ + [ + "ApplyRefContentNode", + "ApplyRefStyleNode", + "ApplyRefUNetNode" + ], + { + "title_aux": "ComfyUI-RefSampling" + } + ], + "https://github.com/logtd/ComfyUI-TrackingNodes": [ + [ + "OpenPoseTrackerNode", + "YOLOTrackerNode" + ], + { + "title_aux": "Tracking Nodes for Videos" + } + ], + "https://github.com/longgui0318/comfyui-common-util": [ + [ + "Added Layer Info To Array", + "Enhanced Random Light Source", + "Float Relay", + "Image Relay", + "Init Layer Info Array", + "Int Relay", + "Layer Image Seleted", + "Layer Images IPAdapter Advanced", + "Layer Info Array Fuse", + "Mask Relay", + "String Relay" + ], + { + "title_aux": "comfyui-common-util" + } + ], + "https://github.com/longgui0318/comfyui-llm-assistant": [ + [ + "Chat With LLM", + "Generate Stable Diffsution Prompt With LLM", + "Translate Text With LLM" + ], + { + "title_aux": "comfyui-llm-assistant" + } + ], + "https://github.com/longgui0318/comfyui-magic-clothing": [ + [ + "Add Magic Clothing Attention", + "Change Pipeline Dtype And Device", + "Change Pixel Value Normalization", + "Diffusers Model Makeup &MC", + "Diffusers Scheduler Loader &MC", + "Load Magic Clothing Adapter", + "Load Magic Clothing Model", + "Load Magic Clothing Pipeline", + "Load Magic Clothing Pipeline With Path", + "RUN Magic Clothing Diffusers Model" + ], + { + "title_aux": "comfyui-magic-clothing" + } + ], + "https://github.com/longgui0318/comfyui-mask-util": [ + [ + "Image Adaptive Crop M&R", + "Image Adaptive Crop With Mask", + "Image Change DType", + "Image Change Device", + "Image Resolution Adaptive With X", + "Image Resolution Limit With 8K", + "Load Image With Name", + "Mask Change DType", + "Mask Change Device", + "Mask Selection Of Masks", + "Model Change Device", + "Model Change Device Repeaters", + "Output Image To Input", + "Split Masks" + ], + { + "title_aux": "comfyui-mask-util" + } + ], + "https://github.com/longgui0318/comfyui-oms-diffusion": [ + [ + "Add Magic Clothing Attention", + "Change Pipeline Dtype And Device", + "Change Pixel Value Normalization", + "Diffusers Model Makeup &MC", + "Diffusers Scheduler Loader &MC", + "Load Magic Clothing Adapter", + "Load Magic Clothing Model", + "Load Magic Clothing Pipeline", + "Load Magic Clothing Pipeline With Path", + "RUN Magic Clothing Diffusers Model" + ], + { + "title_aux": "comfyui-oms-diffusion" + } + ], + "https://github.com/lordgasmic/ComfyUI-Wildcards/raw/master/wildcards.py": [ + [ + "CLIPTextEncodeWithWildcards" + ], + { + "title_aux": "Wildcards" + } + ], + "https://github.com/lordgasmic/comfyui_save_image_with_options": [ + [ + "SaveImageWithOptions" + ], + { + "title_aux": "comfyui_save_image_with_options" + } + ], + "https://github.com/lordgasmic/comfyui_wildcards": [ + [ + "CLIPTextEncodeWithWildcards" + ], + { + "title_aux": "comfyui_wildcards" + } + ], + "https://github.com/lquesada/ComfyUI-Inpaint-CropAndStitch": [ + [ + "InpaintCrop", + "InpaintExtendOutpaint", + "InpaintResize", + "InpaintStitch" + ], + { + "title_aux": "ComfyUI-Inpaint-CropAndStitch" + } + ], + "https://github.com/lquesada/ComfyUI-Prompt-Combinator": [ + [ + "PromptCombinator", + "PromptCombinatorExportGallery", + "PromptCombinatorMerger", + "PromptCombinatorRandomPrompt" + ], + { + "title_aux": "ComfyUI-Prompt-Combinator" + } + ], + "https://github.com/lrzjason/ComfyUIJasonNode/raw/main/SDXLMixSampler.py": [ + [ + "SDXLMixSampler" + ], + { + "title_aux": "ComfyUIJasonNode" + } + ], + "https://github.com/ltdrdata/ComfyUI-Impact-Pack": [ + [ + "AddMask", + "BasicPipeToDetailerPipe", + "BasicPipeToDetailerPipeSDXL", + "BboxDetectorCombined", + "BboxDetectorCombined_v2", + "BboxDetectorForEach", + "BboxDetectorSEGS", + "BitwiseAndMask", + "BitwiseAndMaskForEach", + "CLIPSegDetectorProvider", + "CfgScheduleHookProvider", + "CombineRegionalPrompts", + "CoreMLDetailerHookProvider", + "CustomNoiseDetailerHookProvider", + "DenoiseScheduleHookProvider", + "DenoiseSchedulerDetailerHookProvider", + "DetailerForEach", + "DetailerForEachDebug", + "DetailerForEachDebugPipe", + "DetailerForEachPipe", + "DetailerForEachPipeForAnimateDiff", + "DetailerHookCombine", + "DetailerPipeToBasicPipe", + "EditBasicPipe", + "EditDetailerPipe", + "EditDetailerPipeSDXL", + "EmptySegs", + "FaceDetailer", + "FaceDetailerPipe", + "FromBasicPipe", + "FromBasicPipe_v2", + "FromDetailerPipe", + "FromDetailerPipeSDXL", + "FromDetailerPipe_v2", + "GITSSchedulerFuncProvider", + "ImageListToImageBatch", + "ImageMaskSwitch", + "ImageReceiver", + "ImageSender", + "ImpactAssembleSEGS", + "ImpactCombineConditionings", + "ImpactCompare", + "ImpactConcatConditionings", + "ImpactConditionalBranch", + "ImpactConditionalBranchSelMode", + "ImpactConditionalStopIteration", + "ImpactControlBridge", + "ImpactControlNetApplyAdvancedSEGS", + "ImpactControlNetApplySEGS", + "ImpactControlNetClearSEGS", + "ImpactConvertDataType", + "ImpactCount_Elts_in_SEGS", + "ImpactDecomposeSEGS", + "ImpactDilateMask", + "ImpactDilateMaskInSEGS", + "ImpactDilate_Mask_SEG_ELT", + "ImpactDummyInput", + "ImpactEdit_SEG_ELT", + "ImpactFloat", + "ImpactFrom_SEG_ELT", + "ImpactFrom_SEG_ELT_bbox", + "ImpactFrom_SEG_ELT_crop_region", + "ImpactGaussianBlurMask", + "ImpactGaussianBlurMaskInSEGS", + "ImpactHFTransformersClassifierProvider", + "ImpactIPAdapterApplySEGS", + "ImpactIfNone", + "ImpactImageBatchToImageList", + "ImpactImageInfo", + "ImpactInt", + "ImpactInversedSwitch", + "ImpactIsNotEmptySEGS", + "ImpactKSamplerAdvancedBasicPipe", + "ImpactKSamplerBasicPipe", + "ImpactLatentInfo", + "ImpactLogger", + "ImpactLogicalOperators", + "ImpactMakeImageBatch", + "ImpactMakeImageList", + "ImpactMakeTileSEGS", + "ImpactMinMax", + "ImpactNeg", + "ImpactNodeSetMuteState", + "ImpactQueueTrigger", + "ImpactQueueTriggerCountdown", + "ImpactRemoteBoolean", + "ImpactRemoteInt", + "ImpactSEGSClassify", + "ImpactSEGSConcat", + "ImpactSEGSLabelAssign", + "ImpactSEGSLabelFilter", + "ImpactSEGSOrderedFilter", + "ImpactSEGSPicker", + "ImpactSEGSRangeFilter", + "ImpactSEGSToMaskBatch", + "ImpactSEGSToMaskList", + "ImpactScaleBy_BBOX_SEG_ELT", + "ImpactSchedulerAdapter", + "ImpactSegsAndMask", + "ImpactSegsAndMaskForEach", + "ImpactSetWidgetValue", + "ImpactSimpleDetectorSEGS", + "ImpactSimpleDetectorSEGSPipe", + "ImpactSimpleDetectorSEGS_for_AD", + "ImpactSleep", + "ImpactStringSelector", + "ImpactSwitch", + "ImpactValueReceiver", + "ImpactValueSender", + "ImpactWildcardEncode", + "ImpactWildcardProcessor", + "IterativeImageUpscale", + "IterativeLatentUpscale", + "KSamplerAdvancedProvider", + "KSamplerProvider", + "LatentPixelScale", + "LatentReceiver", + "LatentSender", + "LatentSwitch", + "MMDetDetectorProvider", + "MMDetLoader", + "MaskDetailerPipe", + "MaskListToMaskBatch", + "MaskPainter", + "MaskToSEGS", + "MaskToSEGS_for_AnimateDiff", + "MasksToMaskList", + "MediaPipeFaceMeshToSEGS", + "NoiseInjectionDetailerHookProvider", + "NoiseInjectionHookProvider", + "ONNXDetectorProvider", + "ONNXDetectorSEGS", + "PixelKSampleHookCombine", + "PixelKSampleUpscalerProvider", + "PixelKSampleUpscalerProviderPipe", + "PixelTiledKSampleUpscalerProvider", + "PixelTiledKSampleUpscalerProviderPipe", + "PreviewBridge", + "PreviewBridgeLatent", + "PreviewDetailerHookProvider", + "ReencodeLatent", + "ReencodeLatentPipe", + "RegionalPrompt", + "RegionalSampler", + "RegionalSamplerAdvanced", + "RemoveImageFromSEGS", + "RemoveNoiseMask", + "SAMDetectorCombined", + "SAMDetectorSegmented", + "SAMLoader", + "SEGSDetailer", + "SEGSDetailerForAnimateDiff", + "SEGSLabelFilterDetailerHookProvider", + "SEGSOrderedFilterDetailerHookProvider", + "SEGSPaste", + "SEGSPreview", + "SEGSPreviewCNet", + "SEGSRangeFilterDetailerHookProvider", + "SEGSSwitch", + "SEGSToImageList", + "SEGSUpscaler", + "SEGSUpscalerPipe", + "SegmDetectorCombined", + "SegmDetectorCombined_v2", + "SegmDetectorForEach", + "SegmDetectorSEGS", + "Segs Mask", + "Segs Mask ForEach", + "SegsMaskCombine", + "SegsToCombinedMask", + "SetDefaultImageForSEGS", + "StepsScheduleHookProvider", + "StringListToString", + "SubtractMask", + "SubtractMaskForEach", + "TiledKSamplerProvider", + "ToBasicPipe", + "ToBinaryMask", + "ToDetailerPipe", + "ToDetailerPipeSDXL", + "TwoAdvancedSamplersForMask", + "TwoSamplersForMask", + "TwoSamplersForMaskUpscalerProvider", + "TwoSamplersForMaskUpscalerProviderPipe", + "UltralyticsDetectorProvider", + "UnsamplerDetailerHookProvider", + "UnsamplerHookProvider", + "VariationNoiseDetailerHookProvider", + "WildcardPromptFromString" + ], + { + "author": "Dr.Lt.Data", + "description": "This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler.", + "nickname": "Impact Pack", + "preemptions": [ + "SAMLoader" + ], + "title": "Impact Pack", + "title_aux": "ComfyUI Impact Pack" + } + ], + "https://github.com/ltdrdata/ComfyUI-Inspire-Pack": [ + [ + "AnimeLineArt_Preprocessor_Provider_for_SEGS //Inspire", + "ApplyRegionalIPAdapters //Inspire", + "BindImageListPromptList //Inspire", + "CLIPTextEncodeWithWeight //Inspire", + "CacheBackendData //Inspire", + "CacheBackendDataList //Inspire", + "CacheBackendDataNumberKey //Inspire", + "CacheBackendDataNumberKeyList //Inspire", + "Canny_Preprocessor_Provider_for_SEGS //Inspire", + "ChangeImageBatchSize //Inspire", + "ChangeLatentBatchSize //Inspire", + "CheckpointLoaderSimpleShared //Inspire", + "ColorMapToMasks //Inspire", + "ColorMaskToDepthMask //Inspire", + "Color_Preprocessor_Provider_for_SEGS //Inspire", + "CompositeNoise //Inspire", + "ConcatConditioningsWithMultiplier //Inspire", + "ConditioningStretch //Inspire", + "ConditioningUpscale //Inspire", + "DWPreprocessor_Provider_for_SEGS //Inspire", + "FakeScribblePreprocessor_Provider_for_SEGS //Inspire", + "FloatRange //Inspire", + "FromIPAdapterPipe //Inspire", + "GlobalSampler //Inspire", + "GlobalSeed //Inspire", + "HEDPreprocessor_Provider_for_SEGS //Inspire", + "HyperTile //Inspire", + "IPAdapterModelHelper //Inspire", + "ImageBatchSplitter //Inspire", + "InpaintPreprocessor_Provider_for_SEGS //Inspire", + "KSampler //Inspire", + "KSamplerAdvanced //Inspire", + "KSamplerAdvancedPipe //Inspire", + "KSamplerAdvancedProgress //Inspire", + "KSamplerPipe //Inspire", + "KSamplerProgress //Inspire", + "LatentBatchSplitter //Inspire", + "LeRes_DepthMap_Preprocessor_Provider_for_SEGS //Inspire", + "LineArt_Preprocessor_Provider_for_SEGS //Inspire", + "ListCounter //Inspire", + "LoadImage //Inspire", + "LoadImageListFromDir //Inspire", + "LoadImagesFromDir //Inspire", + "LoadPromptsFromDir //Inspire", + "LoadPromptsFromFile //Inspire", + "LoadSinglePromptFromFile //Inspire", + "LoraBlockInfo //Inspire", + "LoraLoaderBlockWeight //Inspire", + "MakeBasicPipe //Inspire", + "Manga2Anime_LineArt_Preprocessor_Provider_for_SEGS //Inspire", + "MediaPipeFaceMeshDetectorProvider //Inspire", + "MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS //Inspire", + "MeshGraphormerDepthMapPreprocessorProvider_for_SEGS //Inspire", + "MiDaS_DepthMap_Preprocessor_Provider_for_SEGS //Inspire", + "OpenPose_Preprocessor_Provider_for_SEGS //Inspire", + "PromptBuilder //Inspire", + "PromptExtractor //Inspire", + "RGB_HexToHSV //Inspire", + "RandomGeneratorForList //Inspire", + "RandomNoise //Inspire", + "RegionalCFG //Inspire", + "RegionalConditioningColorMask //Inspire", + "RegionalConditioningSimple //Inspire", + "RegionalIPAdapterColorMask //Inspire", + "RegionalIPAdapterEncodedColorMask //Inspire", + "RegionalIPAdapterEncodedMask //Inspire", + "RegionalIPAdapterMask //Inspire", + "RegionalPromptColorMask //Inspire", + "RegionalPromptSimple //Inspire", + "RegionalSeedExplorerColorMask //Inspire", + "RegionalSeedExplorerMask //Inspire", + "RemoveBackendData //Inspire", + "RemoveBackendDataNumberKey //Inspire", + "RemoveControlNet //Inspire", + "RemoveControlNetFromRegionalPrompts //Inspire", + "RetrieveBackendData //Inspire", + "RetrieveBackendDataNumberKey //Inspire", + "ScheduledCFGGuider //Inspire", + "ScheduledPerpNegCFGGuider //Inspire", + "SeedExplorer //Inspire", + "SelectNthMask //Inspire", + "ShowCachedInfo //Inspire", + "StableCascade_CheckpointLoader //Inspire", + "TilePreprocessor_Provider_for_SEGS //Inspire", + "ToIPAdapterPipe //Inspire", + "UnzipPrompt //Inspire", + "WildcardEncode //Inspire", + "XY Input: Lora Block Weight //Inspire", + "ZipPrompt //Inspire", + "Zoe_DepthMap_Preprocessor_Provider_for_SEGS //Inspire" + ], + { + "author": "Dr.Lt.Data", + "description": "This extension provides various nodes to support Lora Block Weight and the Impact Pack.", + "nickname": "Inspire Pack", + "nodename_pattern": "Inspire$", + "title": "Inspire Pack", + "title_aux": "ComfyUI Inspire Pack" + } + ], + "https://github.com/luandev/ComfyUI-CrewAI": [ + [ + "\ud83d\udcceCrewAI Agent", + "\ud83d\udcceCrewAI Agent List", + "\ud83d\udcceCrewAI Crew", + "\ud83d\udcceCrewAI LLM Chat GPT", + "\ud83d\udcceCrewAI LLM Hugging Face", + "\ud83d\udcceCrewAI LLM OpenAI", + "\ud83d\udcceCrewAI Task", + "\ud83d\udcceCrewAI Task List" + ], + { + "title_aux": "ComfyUI CrewAI" + } + ], + "https://github.com/m-sokes/ComfyUI-Sokes-Nodes": [ + [ + "Custom Date Format | sokes \ud83e\uddac", + "Latent Switch x9 | sokes \ud83e\uddac" + ], + { + "title_aux": "ComfyUI Sokes Nodes" + } + ], + "https://github.com/m957ymj75urz/ComfyUI-Custom-Nodes/raw/main/clip-text-encode-split/clip_text_encode_split.py": [ + [ + "RawText", + "RawTextCombine", + "RawTextEncode", + "RawTextReplace" + ], + { + "title_aux": "m957ymj75urz/ComfyUI-Custom-Nodes" + } + ], + "https://github.com/mape/ComfyUI-mape-Helpers": [ + [ + "mape Variable" + ], + { + "author": "mape", + "description": "Various QoL improvements like prompt tweaking, variable assignment, image preview, fuzzy search, error reporting, organizing and node navigation.", + "nickname": "\ud83d\udfe1 mape's helpers", + "title": "mape's helpers", + "title_aux": "mape's helpers" + } + ], + "https://github.com/maracman/ComfyUI-SubjectStyle-CSV": [ + [ + "CSVPromptProcessor" + ], + { + "title_aux": "ComfyUI-SubjectStyle-CSV" + } + ], + "https://github.com/marduk191/comfyui-marnodes": [ + [ + "marduk191_5_text_string", + "marduk191_5way_text_switch", + "marduk191_workflow_settings" + ], + { + "author": "\u02f6marduk191", + "description": "marduk191s nodes.", + "nickname": "marduk191 workflow settings", + "title": "marduk191 workflow settings", + "title_aux": "marduk191 workflow settings" + } + ], + "https://github.com/marhensa/sdxl-recommended-res-calc": [ + [ + "RecommendedResCalc" + ], + { + "title_aux": "Recommended Resolution Calculator" + } + ], + "https://github.com/martijnat/comfyui-previewlatent": [ + [ + "PreviewLatent", + "PreviewLatentAdvanced", + "PreviewLatentXL" + ], + { + "title_aux": "comfyui-previewlatent" + } + ], + "https://github.com/massao000/ComfyUI_aspect_ratios": [ + [ + "Aspect Ratios Node" + ], + { + "title_aux": "ComfyUI_aspect_ratios" + } + ], + "https://github.com/matan1905/ComfyUI-Serving-Toolkit": [ + [ + "DiscordServing", + "ServingInputNumber", + "ServingInputText", + "ServingOutput", + "WebSocketServing" + ], + { + "title_aux": "ComfyUI Serving toolkit" + } + ], + "https://github.com/mav-rik/facerestore_cf": [ + [ + "CropFace", + "FaceRestoreCFWithModel", + "FaceRestoreModelLoader" + ], + { + "title_aux": "Facerestore CF (Code Former)" + } + ], + "https://github.com/mbrostami/ComfyUI-HF": [ + [ + "GPT2Node" + ], + { + "title_aux": "ComfyUI-HF" + } + ], + "https://github.com/mbrostami/ComfyUI-TITrain": [ + [ + "TextualInversionTraining", + "TextualInversionTrainingSDXL" + ], + { + "title_aux": "ComfyUI-TITrain" + } + ], + "https://github.com/mcmonkeyprojects/sd-dynamic-thresholding": [ + [ + "DynamicThresholdingFull", + "DynamicThresholdingSimple" + ], + { + "title_aux": "Stable Diffusion Dynamic Thresholding (CFG Scale Fix)" + } + ], + "https://github.com/meap158/ComfyUI-Background-Replacement": [ + [ + "BackgroundReplacement", + "ImageComposite" + ], + { + "title_aux": "ComfyUI-Background-Replacement" + } + ], + "https://github.com/meap158/ComfyUI-GPU-temperature-protection": [ + [ + "GPUTemperatureProtection" + ], + { + "title_aux": "GPU temperature protection" + } + ], + "https://github.com/meap158/ComfyUI-Prompt-Expansion": [ + [ + "PromptExpansion" + ], + { + "title_aux": "ComfyUI-Prompt-Expansion" + } + ], + "https://github.com/melMass/comfy_mtb": [ + [ + "Animation Builder (mtb)", + "Any To String (mtb)", + "Batch Float (mtb)", + "Batch Float Assemble (mtb)", + "Batch Float Fill (mtb)", + "Batch Make (mtb)", + "Batch Merge (mtb)", + "Batch Shake (mtb)", + "Batch Shape (mtb)", + "Batch Transform (mtb)", + "Bbox (mtb)", + "Bbox From Mask (mtb)", + "Blur (mtb)", + "Color Correct (mtb)", + "Colored Image (mtb)", + "Concat Images (mtb)", + "Crop (mtb)", + "Debug (mtb)", + "Deep Bump (mtb)", + "Export With Ffmpeg (mtb)", + "Face Swap (mtb)", + "Film Interpolation (mtb)", + "Fit Number (mtb)", + "Float To Number (mtb)", + "Get Batch From History (mtb)", + "Image Compare (mtb)", + "Image Premultiply (mtb)", + "Image Remove Background Rembg (mtb)", + "Image Resize Factor (mtb)", + "Image Tile Offset (mtb)", + "Int To Bool (mtb)", + "Int To Number (mtb)", + "Interpolate Clip Sequential (mtb)", + "Latent Lerp (mtb)", + "Load Face Analysis Model (mtb)", + "Load Face Enhance Model (mtb)", + "Load Face Swap Model (mtb)", + "Load Film Model (mtb)", + "Load Image From Url (mtb)", + "Load Image Sequence (mtb)", + "Mask To Image (mtb)", + "Math Expression (mtb)", + "Model Patch Seamless (mtb)", + "Pick From Batch (mtb)", + "Qr Code (mtb)", + "Restore Face (mtb)", + "Save Gif (mtb)", + "Save Image Grid (mtb)", + "Save Image Sequence (mtb)", + "Save Tensors (mtb)", + "Sharpen (mtb)", + "Smart Step (mtb)", + "Stack Images (mtb)", + "String Replace (mtb)", + "Styles Loader (mtb)", + "Text To Image (mtb)", + "Transform Image (mtb)", + "Uncrop (mtb)", + "Unsplash Image (mtb)", + "Vae Decode (mtb)" + ], + { + "nodename_pattern": "\\(mtb\\)$", + "title_aux": "MTB Nodes" + } + ], + "https://github.com/mephisto83/petty-paint-comfyui-node": [ + [ + "PettyImageImageColorToMask", + "PettyPaintAppend", + "PettyPaintApplyLoRAStack", + "PettyPaintBlurs", + "PettyPaintComponent", + "PettyPaintConditioningSetMaskAndCombine", + "PettyPaintConvert", + "PettyPaintCountFiles", + "PettyPaintEnsureDirectory", + "PettyPaintExec", + "PettyPaintFakeConvert", + "PettyPaintFileExists", + "PettyPaintImageColorsToMasks", + "PettyPaintImageCompositeMasked", + "PettyPaintImageDims", + "PettyPaintImageMaskCropper", + "PettyPaintImagePlacement", + "PettyPaintImageSave", + "PettyPaintImageStore", + "PettyPaintImageToMask", + "PettyPaintImagesToMasks", + "PettyPaintJsonMap", + "PettyPaintJsonRead", + "PettyPaintJsonReadArray", + "PettyPaintKSampler", + "PettyPaintKSamplerAdvanced", + "PettyPaintLoRAStack", + "PettyPaintLoadImage", + "PettyPaintLoadImageMasks", + "PettyPaintLoadImages", + "PettyPaintMap", + "PettyPaintMasksToImages", + "PettyPaintNot", + "PettyPaintPassThroughNode", + "PettyPaintProcessor", + "PettyPaintRemoveAddText", + "PettyPaintSDTurboScheduler", + "PettyPaintStoryImage", + "PettyPaintText", + "PettyPaintTexts_to_Conditioning", + "PettyPaintToJson", + "PettyPaintVAEDecode" + ], + { + "title_aux": "petty-paint-comfyui-node" + } + ], + "https://github.com/meshmesh-io/ComfyUI-MeshMesh": [ + [ + "ColorPicker", + "MasksToColoredMasks" + ], + { + "title_aux": "ComfyUI-MeshMesh" + } + ], + "https://github.com/meshmesh-io/mm-comfyui-loopback": [ + [ + "Loop", + "LoopEnd", + "LoopEnd_SEGIMAGE", + "LoopStart", + "LoopStart_SEGIMAGE" + ], + { + "title_aux": "mm-comfyui-loopback" + } + ], + "https://github.com/meshmesh-io/mm-comfyui-megamask": [ + [ + "ColorListMaskToImage", + "FlattenAndCombineMaskImages" + ], + { + "title_aux": "mm-comfyui-megamask" + } + ], + "https://github.com/metncelik/comfyui_met_suite": [ + [ + "BBOXPadding", + "BBOXResize", + "ImageResizeKeepRatio", + "PrimitiveBBOX", + "RaiseError" + ], + { + "title_aux": "comfyui_met_suite" + } + ], + "https://github.com/mihaiiancu/ComfyUI_Inpaint": [ + [ + "InpaintMediapipe" + ], + { + "title_aux": "mihaiiancu/Inpaint" + } + ], + "https://github.com/mikkel/ComfyUI-text-overlay": [ + [ + "Image Text Overlay" + ], + { + "title_aux": "ComfyUI - Text Overlay Plugin" + } + ], + "https://github.com/mikkel/comfyui-mask-boundingbox": [ + [ + "Mask Bounding Box" + ], + { + "title_aux": "ComfyUI - Mask Bounding Box" + } + ], + "https://github.com/mingqizhang/ComfyUI_InSPyResNet_zmq": [ + [ + "INSPY removebg Apply", + "INSPY removebg ModelLoader" + ], + { + "title_aux": "ComfyUI_InSPyResNet_zmq" + } + ], + "https://github.com/mirabarukaso/ComfyUI_Mira": [ + [ + "BooleanListInterpreter1", + "BooleanListInterpreter4", + "BooleanListInterpreter8", + "CanvasCreatorAdvanced", + "CanvasCreatorBasic", + "CanvasCreatorSimple", + "CircleCreator", + "CirclesGenerator", + "CreateCircleMask", + "CreateMaskWithCanvas", + "CreateNestedPNGMask", + "CreateSimpleMask", + "CreateTillingPNGMask", + "CreateWatermarkRemovalMask", + "EightBooleanTrigger", + "EightFloats", + "EvenOrOdd", + "EvenOrOddList", + "FloatListInterpreter1", + "FloatListInterpreter4", + "FloatListInterpreter8", + "FloatMultiplication", + "FourBooleanTrigger", + "FourFloats", + "FunctionSwap", + "IntMultiplication", + "IntSubtraction", + "IntToFloatMultiplication", + "LogicNot", + "NoneToZero", + "NumeralToString", + "OneFloat", + "PngColorMasksToMaskList", + "PngColorMasksToRGB", + "PngColorMasksToString", + "PngColorMasksToStringList", + "PngRectanglesToMask", + "PngRectanglesToMaskList", + "RandomNestedLayouts", + "RandomTillingLayouts", + "SN74HC1G86", + "SN74HC86", + "SN74LVC1G125", + "SeedGenerator", + "SingleBooleanTrigger", + "SixBooleanTrigger", + "StepsAndCfg", + "TextBox", + "TextCombinerSix", + "TextCombinerTwo", + "TextWithBooleanSwitchAndCommonTextInput", + "TwoBooleanTrigger", + "TwoFloats" + ], + { + "title_aux": "ComfyUI_Mira" + } + ], + "https://github.com/modusCell/ComfyUI-dimension-node-modusCell": [ + [ + "DimensionProviderFree modusCell", + "DimensionProviderRatio modusCell", + "String Concat modusCell" + ], + { + "title_aux": "Preset Dimensions" + } + ], + "https://github.com/moyi7712/ComfyUI_Seamless_Patten": [ + [ + "SeamlessApply", + "SeamlessKSampler", + "SeamlessKSamplerAdvanced", + "SeamlessVae" + ], + { + "title_aux": "ComfyUI_Seamless_Patten" + } + ], + "https://github.com/mpiquero7164/ComfyUI-SaveImgPrompt": [ + [ + "Save IMG Prompt" + ], + { + "title_aux": "SaveImgPrompt" + } + ], + "https://github.com/mullakhmetov/comfyui_dynamic_util_nodes": [ + [ + "ConcatStrings", + "FormatString", + "GetFiles", + "LoadImageByPath" + ], + { + "title_aux": "comfyui_dynamic_util_nodes" + } + ], + "https://github.com/muzi12888/ComfyUI-PoseKeypoint-Mask": [ + [ + "Image Brightness", + "Openpose Keypoint Mask" + ], + { + "title_aux": "PoseKeypoint Mask" + } + ], + "https://github.com/my-opencode/ComfyUI_IndustrialMagick": [ + [ + "IndustrialMagick", + "IndustrialMagickImageIngest" + ], + { + "title_aux": "ComfyUI_IndustrialMagick" + } + ], + "https://github.com/my-opencode/ComfyUI_KSamplerTimer": [ + [ + "KSamplerTimer" + ], + { + "author": "Ludovic Anterieur", + "description": "This extension provides a wrapper of the native KSampler which outputs generation time.", + "nickname": "\u23f1", + "title": "KSampler (timer)", + "title_aux": "ComfyUI_KSamplerTimer" + } + ], + "https://github.com/nagolinc/ComfyUI_FastVAEDecorder_SDXL": [ + [ + "FastLatentToImage" + ], + { + "title_aux": "ComfyUI_FastVAEDecorder_SDXL" + } + ], + "https://github.com/nagolinc/comfyui_openai_node": [ + [ + "OpenAINode" + ], + { + "title_aux": "comfyui_openai_node" + } + ], + "https://github.com/natto-maki/ComfyUI-NegiTools": [ + [ + "NegiTools_CompositeImages", + "NegiTools_DepthEstimationByMarigold", + "NegiTools_DetectFaceRotationForInpainting", + "NegiTools_ImageProperties", + "NegiTools_LatentProperties", + "NegiTools_NoiseImageGenerator", + "NegiTools_OpenAiDalle3", + "NegiTools_OpenAiGpt", + "NegiTools_OpenAiGpt4v", + "NegiTools_OpenAiTranslate", + "NegiTools_OpenPoseToPointList", + "NegiTools_PointListToMask", + "NegiTools_RandomImageLoader", + "NegiTools_SaveImageToDirectory", + "NegiTools_SeedGenerator", + "NegiTools_StereoImageGenerator", + "NegiTools_StringFunction" + ], + { + "title_aux": "ComfyUI-NegiTools" + } + ], + "https://github.com/nickve28/ComfyUI-Nich-Utils": [ + [ + "Image from Dir Selector (Nich)", + "Select Text with Regular Expression (Nich)" + ], + { + "title_aux": "ComfyUI Nich Utils" + } + ], + "https://github.com/nicolai256/comfyUI_Nodes_nicolai256/raw/main/yugioh-presets.py": [ + [ + "yugioh_Presets" + ], + { + "title_aux": "comfyUI_Nodes_nicolai256" + } + ], + "https://github.com/ningxiaoxiao/comfyui-NDI": [ + [ + "NDI_LoadImage", + "NDI_SendImage" + ], + { + "title_aux": "comfyui-NDI" + } + ], + "https://github.com/nirbhay-faaya/ImgProcessing_ComfyUI": [ + [ + "ImageConcat", + "ImageCropMultEight", + "ImageCut", + "LightingPreprocessor" + ], + { + "title_aux": "ImgProcessing_ComfyUI" + } + ], + "https://github.com/nirex0/ComfyUI_pytorch_openpose": [ + [ + "pytorch_openpose" + ], + { + "title_aux": "ComfyUI_pytorch_openpose" + } + ], + "https://github.com/nkchocoai/ComfyUI-Dart": [ + [ + "DanbooruTagsTransformerBanTagsFromRegex", + "DanbooruTagsTransformerComposePrompt", + "DanbooruTagsTransformerComposePromptV2", + "DanbooruTagsTransformerDecode", + "DanbooruTagsTransformerDecodeBySplitedParts", + "DanbooruTagsTransformerGenerate", + "DanbooruTagsTransformerGenerateAdvanced", + "DanbooruTagsTransformerGenerationConfig", + "DanbooruTagsTransformerGetAspectRatio", + "DanbooruTagsTransformerLoader", + "DanbooruTagsTransformerRearrangedByAnimagine", + "DanbooruTagsTransformerRemoveTagToken" + ], + { + "title_aux": "ComfyUI-Dart" + } + ], + "https://github.com/nkchocoai/ComfyUI-PromptUtilities": [ + [ + "PromptUtilitiesConstString", + "PromptUtilitiesConstStringMultiLine", + "PromptUtilitiesFormatString", + "PromptUtilitiesJoinStringList", + "PromptUtilitiesLoadPreset", + "PromptUtilitiesLoadPresetAdvanced", + "PromptUtilitiesRandomPreset", + "PromptUtilitiesRandomPresetAdvanced" + ], + { + "title_aux": "ComfyUI-PromptUtilities" + } + ], + "https://github.com/nkchocoai/ComfyUI-SaveImageWithMetaData": [ + [ + "SaveImageWithMetaData" + ], + { + "title_aux": "ComfyUI-SaveImageWithMetaData" + } + ], + "https://github.com/nkchocoai/ComfyUI-SizeFromPresets": [ + [ + "EmptyLatentImageFromPresetsSD15", + "EmptyLatentImageFromPresetsSDXL", + "GetSimilarResolution", + "GetSimilarResolutionEmptyLatent", + "RandomEmptyLatentImageFromPresetsSD15", + "RandomEmptyLatentImageFromPresetsSDXL", + "RandomSizeFromPresetsSD15", + "RandomSizeFromPresetsSDXL", + "SizeFromPresetsSD15", + "SizeFromPresetsSDXL" + ], + { + "title_aux": "ComfyUI-SizeFromPresets" + } + ], + "https://github.com/nkchocoai/ComfyUI-TextOnSegs": [ + [ + "CalcMaxFontSize", + "ExtractDominantColor", + "GetComplementaryColor", + "SegsToRegion", + "TextOnSegsFloodFill" + ], + { + "title_aux": "ComfyUI-TextOnSegs" + } + ], + "https://github.com/noembryo/ComfyUI-noEmbryo": [ + [ + "PromptTermList1", + "PromptTermList2", + "PromptTermList3", + "PromptTermList4", + "PromptTermList5", + "PromptTermList6" + ], + { + "author": "noEmbryo", + "description": "Some useful nodes for ComfyUI", + "nickname": "noEmbryo", + "title": "noEmbryo nodes", + "title_aux": "noEmbryo nodes" + } + ], + "https://github.com/nosiu/comfyui-instantId-faceswap": [ + [ + "FaceEmbed", + "FaceSwapGenerationInpaint", + "FaceSwapSetupPipeline", + "LCMLora" + ], + { + "title_aux": "ComfyUI InstantID Faceswapper" + } + ], + "https://github.com/noxinias/ComfyUI_NoxinNodes": [ + [ + "NoxinChime", + "NoxinPromptLoad", + "NoxinPromptSave", + "NoxinScaledResolution", + "NoxinSimpleMath", + "NoxinSplitPrompt" + ], + { + "title_aux": "ComfyUI_NoxinNodes" + } + ], + "https://github.com/ntc-ai/ComfyUI-DARE-LoRA-Merge": [ + [ + "Apply LoRA", + "DARE Merge LoRA Stack", + "Save LoRA" + ], + { + "title_aux": "ComfyUI - Apply LoRA Stacker with DARE" + } + ], + "https://github.com/ntdviet/comfyui-ext/raw/main/custom_nodes/gcLatentTunnel/gcLatentTunnel.py": [ + [ + "gcLatentTunnel" + ], + { + "title_aux": "ntdviet/comfyui-ext" + } + ], + "https://github.com/nuanarchy/ComfyUI-NuA-BIRD": [ + [ + "Bird_Deblurring_NuA", + "Bird_Denoising_NuA", + "Bird_Inpainting_NuA", + "Bird_Loader_NuA", + "Bird_Non_Uniform_Deblurring_NuA", + "Bird_Super_Resolution_NuA" + ], + { + "title_aux": "ComfyUI-NuA-BIRD" + } + ], + "https://github.com/nuanarchy/ComfyUI-NuA-FlashFace": [ + [ + "FlashFace_Loader_NuA", + "FlashFace_Sampler_NuA" + ], + { + "title_aux": "ComfyUI-NuA-FlashFace" + } + ], + "https://github.com/nullquant/ComfyUI-BrushNet": [ + [ + "BlendInpaint", + "BrushNet", + "BrushNetLoader", + "CutForInpaint", + "PowerPaint", + "PowerPaintCLIPLoader", + "RAUNet", + "Terminal" + ], + { + "author": "nullquant", + "description": "These are custom nodes for ComfyUI native implementation of BrushNet, PowerPaint and RAUNet models", + "nickname": "BrushName nodes", + "title": "BrushNet", + "title_aux": "BrushNet" + } + ], + "https://github.com/olduvai-jp/ComfyUI-HfLoader": [ + [ + "Lora Loader From HF" + ], + { + "title_aux": "ComfyUI-HfLoader" + } + ], + "https://github.com/omar92/ComfyUI-QualityOfLifeSuit_Omar92": [ + [ + "CLIPStringEncode _O", + "Chat completion _O", + "ChatGPT Simple _O", + "ChatGPT _O", + "ChatGPT compact _O", + "Chat_Completion _O", + "Chat_Message _O", + "Chat_Message_fromString _O", + "Concat Text _O", + "ConcatRandomNSP_O", + "Debug String _O", + "Debug Text _O", + "Debug Text route _O", + "Edit_image _O", + "Equation1param _O", + "Equation2params _O", + "GetImage_(Width&Height) _O", + "GetLatent_(Width&Height) _O", + "ImageScaleFactor _O", + "ImageScaleFactorSimple _O", + "LatentUpscaleFactor _O", + "LatentUpscaleFactorSimple _O", + "LatentUpscaleMultiply", + "Note _O", + "RandomNSP _O", + "Replace Text _O", + "String _O", + "Text _O", + "Text2Image _O", + "Trim Text _O", + "VAEDecodeParallel _O", + "combine_chat_messages _O", + "compine_chat_messages _O", + "concat Strings _O", + "create image _O", + "create_image _O", + "debug Completeion _O", + "debug messages_O", + "float _O", + "floatToInt _O", + "floatToText _O", + "int _O", + "intToFloat _O", + "load_openAI _O", + "replace String _O", + "replace String advanced _O", + "saveTextToFile _O", + "seed _O", + "selectLatentFromBatch _O", + "string2Image _O", + "trim String _O", + "variation_image _O" + ], + { + "title_aux": "Quality of life Suit:V2" + } + ], + "https://github.com/opvelll/ComfyUI_TextListProduct": [ + [ + "ProductedString", + "TextListProduct", + "TextListProductWithSingleA", + "TextListProductWithSingleB", + "TextListProductWithSingleBoth" + ], + { + "title_aux": "Comfy UI Text List Product" + } + ], + "https://github.com/osi1880vr/prompt_quill_comfyui": [ + [ + "PromptQuillGenerate", + "PromptQuillGenerateConditioning", + "PromptQuillSail", + "PromptQuillSailConditioning" + ], + { + "title_aux": "ComfyUI_Prompt-Quill" + } + ], + "https://github.com/ostris/ostris_nodes_comfyui": [ + [ + "LLM Pipe Loader - Ostris", + "LLM Prompt Upsampling - Ostris", + "One Seed - Ostris", + "Text Box - Ostris" + ], + { + "nodename_pattern": "- Ostris$", + "title_aux": "Ostris Nodes ComfyUI" + } + ], + "https://github.com/ownimage/ComfyUI-ownimage": [ + [ + "Caching Image Loader" + ], + { + "title_aux": "ComfyUI-ownimage" + } + ], + "https://github.com/oyvindg/ComfyUI-TrollSuite": [ + [ + "BinaryImageMask", + "ImagePadding", + "LoadLastImage", + "RandomMask", + "TransparentImage" + ], + { + "title_aux": "ComfyUI-TrollSuite" + } + ], + "https://github.com/oztrkoguz/ComfyUI_StoryCreator": [ + [ + "Kosmos2SamplerSimple2", + "KosmosLoader2", + "StoryLoader", + "StorySamplerSimple", + "Write2" + ], + { + "title_aux": "ComfyUI StoryCreater" + } + ], + "https://github.com/palant/extended-saveimage-comfyui": [ + [ + "SaveImageExtended" + ], + { + "title_aux": "Extended Save Image for ComfyUI" + } + ], + "https://github.com/palant/image-resize-comfyui": [ + [ + "ImageResize" + ], + { + "title_aux": "Image Resize for ComfyUI" + } + ], + "https://github.com/pamparamm/ComfyUI-vectorscope-cc": [ + [ + "NormalizeLatent", + "VectorscopeCC" + ], + { + "title_aux": "ComfyUI Vectorscope CC" + } + ], + "https://github.com/pamparamm/sd-perturbed-attention": [ + [ + "PerturbedAttention" + ], + { + "title_aux": "Perturbed-Attention Guidance" + } + ], + "https://github.com/pants007/comfy-pants": [ + [ + "CLIPTextEncodeAIO", + "Image Make Square" + ], + { + "title_aux": "pants" + } + ], + "https://github.com/paulo-coronado/comfy_clip_blip_node": [ + [ + "CLIPTextEncodeBLIP", + "CLIPTextEncodeBLIP-2", + "Example" + ], + { + "title_aux": "comfy_clip_blip_node" + } + ], + "https://github.com/philz1337x/ComfyUI-ClarityAI": [ + [ + "Clarity AI Upscaler" + ], + { + "title_aux": "\u2728 Clarity AI - Creative Image Upscaler and Enhancer for ComfyUI" + } + ], + "https://github.com/picturesonpictures/comfy_PoP": [ + [ + "AdaptiveCannyDetector_PoP", + "AnyAspectRatio", + "ConditioningMultiplier_PoP", + "ConditioningNormalizer_PoP", + "DallE3_PoP", + "EfficientAttention", + "LoadImageResizer_PoP", + "LoraStackLoader10_PoP", + "LoraStackLoader_PoP", + "VAEDecoderPoP", + "VAEEncoderPoP" + ], + { + "title_aux": "comfy_PoP" + } + ], + "https://github.com/pkpkTech/ComfyUI-SaveAVIF": [ + [ + "SaveAvif" + ], + { + "title_aux": "ComfyUI-SaveAVIF" + } + ], + "https://github.com/pkpkTech/ComfyUI-TemporaryLoader": [ + [ + "LoadTempCheckpoint", + "LoadTempLoRA", + "LoadTempMultiLoRA" + ], + { + "title_aux": "ComfyUI-TemporaryLoader" + } + ], + "https://github.com/portu-sim/comfyui_bmab": [ + [ + "BMAB Alpha Composit", + "BMAB Basic", + "BMAB Blend", + "BMAB Clip Text Encoder SDXL", + "BMAB Conditioning To Bind", + "BMAB Context", + "BMAB ControlNet", + "BMAB ControlNet IPAdapter", + "BMAB ControlNet Openpose", + "BMAB Crop", + "BMAB Detail Anything", + "BMAB Detect And Mask", + "BMAB Detection Crop", + "BMAB Detector", + "BMAB Edge", + "BMAB Extractor", + "BMAB Face Detailer", + "BMAB Google Gemini Prompt", + "BMAB Import Integrator", + "BMAB Integrator", + "BMAB KSampler", + "BMAB KSamplerHiresFix", + "BMAB KSamplerHiresFixWithUpscaler", + "BMAB KSamplerKohyaDeepShrink", + "BMAB Lama Inpaint", + "BMAB LoRA Loader", + "BMAB Load Image", + "BMAB Load Output Image", + "BMAB Masks To Images", + "BMAB Model To Bind", + "BMAB Noise Generator", + "BMAB Openpose Hand Detailer", + "BMAB Person Detailer", + "BMAB Preview Text", + "BMAB Prompt", + "BMAB Remove Background", + "BMAB Resize By Person", + "BMAB Resize By Ratio", + "BMAB Resize and Fill", + "BMAB SD-WebUI API BMAB Extension", + "BMAB SD-WebUI API ControlNet", + "BMAB SD-WebUI API I2I", + "BMAB SD-WebUI API Server", + "BMAB SD-WebUI API T2I", + "BMAB SD-WebUI API T2I Hires.Fix", + "BMAB Save Image", + "BMAB SeedGenerator", + "BMAB Segment Anything", + "BMAB Simple Hand Detailer", + "BMAB Subframe Hand Detailer", + "BMAB Text", + "BMAB Upscale With Model", + "BMAB Upscaler", + "BMAB Watermark" + ], + { + "title_aux": "comfyui_bmab" + } + ], + "https://github.com/prodogape/ComfyUI-EasyOCR": [ + [ + "Apply EasyOCR" + ], + { + "title_aux": "ComfyUI-EasyOCR" + } + ], + "https://github.com/prodogape/ComfyUI-Minio": [ + [ + "Load Image From Minio", + "Save Image To Minio", + "Set Minio Config" + ], + { + "title_aux": "Comfyui-Minio" + } + ], + "https://github.com/prodogape/ComfyUI-OmDet": [ + [ + "Apply OmDet" + ], + { + "title_aux": "ComfyUI-OmDet" + } + ], + "https://github.com/prodogape/Comfyui-Yolov8-JSON": [ + [ + "Apply Yolov8 Model", + "Apply Yolov8 Model Seg", + "Draw Labelme Json", + "Load Yolov8 Model", + "Load Yolov8 Model From Path", + "Save Labelme Json" + ], + { + "title_aux": "Comfyui-Yolov8-JSON" + } + ], + "https://github.com/pythongosssss/ComfyUI-Custom-Scripts": [ + [ + "CheckpointLoader|pysssss", + "ConstrainImageforVideo|pysssss", + "ConstrainImage|pysssss", + "LoadText|pysssss", + "LoraLoader|pysssss", + "MathExpression|pysssss", + "MultiPrimitive|pysssss", + "PlaySound|pysssss", + "Repeater|pysssss", + "ReroutePrimitive|pysssss", + "SaveText|pysssss", + "ShowText|pysssss", + "StringFunction|pysssss", + "SystemNotification|pysssss" + ], + { + "title_aux": "pythongosssss/ComfyUI-Custom-Scripts" + } + ], + "https://github.com/pythongosssss/ComfyUI-WD14-Tagger": [ + [ + "WD14Tagger|pysssss" + ], + { + "title_aux": "ComfyUI WD 1.4 Tagger" + } + ], + "https://github.com/qwixiwp/queuetools": [ + [ + "load images (queue tools)" + ], + { + "title_aux": "queuetools" + } + ], + "https://github.com/ramyma/A8R8_ComfyUI_nodes": [ + [ + "AttentionCouple", + "AttentionCoupleRegion", + "AttentionCoupleRegions", + "Base64ImageInput", + "Base64ImageOutput" + ], + { + "title_aux": "A8R8 ComfyUI Nodes" + } + ], + "https://github.com/randjtw/advance-aesthetic-score": [ + [ + "Adv_Scoring" + ], + { + "title_aux": "advance-aesthetic-score" + } + ], + "https://github.com/ratulrafsan/Comfyui-SAL-VTON": [ + [ + "SALVTON_Apply", + "SV_random" + ], + { + "title_aux": "Comfyui-SAL-VTON" + } + ], + "https://github.com/rcfcu2000/zhihuige-nodes-comfyui": [ + [ + "Combine ZHGMasks", + "Cover ZHGMasks", + "From ZHG pip", + "GroundingDinoModelLoader (zhihuige)", + "GroundingDinoPIPESegment (zhihuige)", + "GroundingDinoSAMSegment (zhihuige)", + "InvertMask (zhihuige)", + "SAMModelLoader (zhihuige)", + "To ZHG pip", + "ZHG FaceIndex", + "ZHG GetMaskArea", + "ZHG Image Levels", + "ZHG SaveImage", + "ZHG SmoothEdge", + "ZHG UltimateSDUpscale" + ], + { + "title_aux": "zhihuige-nodes-comfyui" + } + ], + "https://github.com/rcsaquino/comfyui-custom-nodes": [ + [ + "BackgroundRemover | rcsaquino", + "VAELoader | rcsaquino", + "VAEProcessor | rcsaquino" + ], + { + "title_aux": "rcsaquino/comfyui-custom-nodes" + } + ], + "https://github.com/receyuki/comfyui-prompt-reader-node": [ + [ + "SDAnyConverter", + "SDBatchLoader", + "SDLoraLoader", + "SDLoraSelector", + "SDParameterExtractor", + "SDParameterGenerator", + "SDPromptMerger", + "SDPromptReader", + "SDPromptSaver", + "SDTypeConverter" + ], + { + "author": "receyuki", + "description": "The ultimate solution for managing image metadata and multi-tool compatibility. ComfyUI node version of the SD Prompt Reader", + "nickname": "SD Prompt Reader", + "title": "SD Prompt Reader", + "title_aux": "SD Prompt Reader" + } + ], + "https://github.com/redhottensors/ComfyUI-Prediction": [ + [ + "AvoidErasePrediction", + "CFGPrediction", + "CharacteristicGuidancePrediction", + "CombinePredictions", + "ConditionedPrediction", + "EarlyMiddleLatePrediction", + "InterpolatePredictions", + "LogSigmas", + "PerpNegPrediction", + "SamplerCustomPrediction", + "ScalePrediction", + "ScaledGuidancePrediction", + "SelectSigmas", + "SplitAtSigma", + "SwitchPredictions" + ], + { + "author": "RedHotTensors", + "description": "Fully customizable Classifer Free Guidance for ComfyUI", + "nickname": "ComfyUI-Prediction", + "title": "ComfyUI-Prediction", + "title_aux": "ComfyUI-Prediction" + } + ], + "https://github.com/rgthree/rgthree-comfy": [ + [], + { + "author": "rgthree", + "description": "A bunch of nodes I created that I also find useful.", + "nickname": "rgthree", + "nodename_pattern": " \\(rgthree\\)$", + "title": "Comfy Nodes", + "title_aux": "rgthree's ComfyUI Nodes" + } + ], + "https://github.com/rhdunn/comfyui-bus-plugin": [ + [ + "ComfyBus.CLIPEncodedPromptBusNode", + "ComfyBus.CheckpointBusNode", + "ComfyBus.ImageBusNode", + "ComfyBus.ImageParameterBusNode", + "ComfyBus.ImageScaleToSideParameterBusNode", + "ComfyBus.ImageSizeBusNode", + "ComfyBus.LatentImageBusNode", + "ComfyBus.LatentImageParameterBusNode", + "ComfyBus.PromptBusNode", + "ComfyBus.PromptSDXLBusNode" + ], + { + "title_aux": "comfyui-bus-plugin" + } + ], + "https://github.com/richinsley/Comfy-LFO": [ + [ + "LFO_Pulse", + "LFO_Sawtooth", + "LFO_Sine", + "LFO_Square", + "LFO_Triangle" + ], + { + "title_aux": "Comfy-LFO" + } + ], + "https://github.com/ricklove/comfyui-ricklove": [ + [ + "RL_Crop_Resize", + "RL_Crop_Resize_Batch", + "RL_Finetune_Analyze", + "RL_Finetune_Analyze_Batch", + "RL_Finetune_Variable", + "RL_Image_Shadow", + "RL_Image_Threshold_Channels", + "RL_Internet_Search", + "RL_LoadImageSequence", + "RL_Optical_Flow_Dip", + "RL_SaveImageSequence", + "RL_Uncrop", + "RL_Warp_Image", + "RL_Zoe_Depth_Map_Preprocessor", + "RL_Zoe_Depth_Map_Preprocessor_Raw_Infer", + "RL_Zoe_Depth_Map_Preprocessor_Raw_Process" + ], + { + "title_aux": "comfyui-ricklove" + } + ], + "https://github.com/risunobushi/comfyUI_FrequencySeparation_RGB-HSV": [ + [ + "FrequencyCombination", + "FrequencyCombinationHSV", + "FrequencySeparation", + "FrequencySeparationHSV" + ], + { + "title_aux": "comfyUI_FrequencySeparation_RGB-HSV" + } + ], + "https://github.com/rklaffehn/rk-comfy-nodes": [ + [ + "RK_CivitAIAddHashes", + "RK_CivitAIMetaChecker" + ], + { + "title_aux": "rk-comfy-nodes" + } + ], + "https://github.com/romeobuilderotti/ComfyUI-PNG-Metadata": [ + [ + "SetMetadataAll", + "SetMetadataString" + ], + { + "title_aux": "ComfyUI PNG Metadata" + } + ], + "https://github.com/ronniebasak/ComfyUI-Tara-LLM-Integration": [ + [ + "TaraAdvancedComposition", + "TaraApiKeyLoader", + "TaraApiKeySaver", + "TaraDaisyChainNode", + "TaraLLMConfig", + "TaraPresetLLMConfig", + "TaraPrompter", + "TaraPrompterAdvanced" + ], + { + "title_aux": "ComfyUI-Tara-LLM-Integration" + } + ], + "https://github.com/royceschultz/ComfyUI-Notifications": [ + [ + "Notif-PlaySound", + "Notif-SystemNotification", + "Notif-UnifiedNotification", + "Notif-Webhook" + ], + { + "title_aux": "ComfyUI-Notifications" + } + ], + "https://github.com/royceschultz/ComfyUI-TranscriptionTools": [ + [ + "TT-AudioSink", + "TT-ConvertVhsAudioToAudio", + "TT-LoadAudio", + "TT-LoadBatch", + "TT-LoadVideoAudio", + "TT-LoadWhisperModel", + "TT-WhisperTranscription", + "TT-WhisperTranscriptionBatch" + ], + { + "title_aux": "ComfyUI-TranscriptionTools" + } + ], + "https://github.com/rui40000/RUI-Nodes": [ + [ + "ABCondition", + "CharacterCount" + ], + { + "title_aux": "RUI-Nodes" + } + ], + "https://github.com/ruiqutech/ComfyUI-RuiquNodes": [ + [ + "EvaluateListMultiple1", + "EvaluateListMultiple3", + "EvaluateListMultiple6", + "EvaluateListMultiple9", + "EvaluateMultiple1", + "EvaluateMultiple3", + "EvaluateMultiple6", + "EvaluateMultiple9", + "ImageDilate", + "ImageErode", + "ListPath", + "MaskDilate", + "MaskErode", + "PreviewMask", + "RangeSplit", + "SaveMask", + "StringAsAny", + "StringConcat1", + "StringConcat3", + "StringConcat6", + "StringConcat9", + "StringPathStem", + "TermsToList", + "VAEDecodeSave" + ], + { + "title_aux": "RuiquNodes for ComfyUI" + } + ], + "https://github.com/runtime44/comfyui_r44_nodes": [ + [ + "Runtime44ColorMatch", + "Runtime44DynamicKSampler", + "Runtime44FilmGrain", + "Runtime44ImageEnhance", + "Runtime44ImageOverlay", + "Runtime44ImageResizer", + "Runtime44ImageToNoise", + "Runtime44IterativeUpscaleFactor", + "Runtime44MaskSampler", + "Runtime44TiledMaskSampler", + "Runtime44Upscaler" + ], + { + "title_aux": "Runtime44 ComfyUI Nodes" + } + ], + "https://github.com/s1dlx/comfy_meh/raw/main/meh.py": [ + [ + "MergingExecutionHelper" + ], + { + "title_aux": "comfy_meh" + } + ], + "https://github.com/saftle/suplex_comfy_nodes": [ + [ + "ControlNet Selector", + "ControlNetOptionalLoader", + "DiffusersSelector", + "SaveImageJPGNoMeta" + ], + { + "title_aux": "Suplex Misc ComfyUI Nodes" + } + ], + "https://github.com/sdfxai/SDFXBridgeForComfyUI": [ + [ + "SDFXClipTextEncode" + ], + { + "title_aux": "SDFXBridgeForComfyUI - ComfyUI Custom Node for SDFX Integration" + } + ], + "https://github.com/seanlynch/comfyui-optical-flow": [ + [ + "Apply optical flow", + "Compute optical flow", + "Visualize optical flow" + ], + { + "title_aux": "ComfyUI Optical Flow" + } + ], + "https://github.com/seanlynch/srl-nodes": [ + [ + "SRL Conditional Interrrupt", + "SRL Eval", + "SRL Filter Image List", + "SRL Format String" + ], + { + "title_aux": "SRL's nodes" + } + ], + "https://github.com/seghier/ComfyUI_LibreTranslate/raw/main/translate_node.py": [ + [ + "LibreTranslate" + ], + { + "title_aux": "ComfyUI_LibreTranslate" + } + ], + "https://github.com/sergekatzmann/ComfyUI_Nimbus-Pack": [ + [ + "AdjustAndRoundDimensions", + "AspectRatioMobileDevices", + "ImageResizeAndCropNode", + "ImageSquareAdapterNode", + "PopularScreenResolutions" + ], + { + "title_aux": "ComfyUI_Nimbus-Pack" + } + ], + "https://github.com/shadowcz007/comfyui-Image-reward": [ + [ + "ImageBatchToList_", + "ImageRewardScore_" + ], + { + "title_aux": "comfyui-Image-reward" + } + ], + "https://github.com/shadowcz007/comfyui-consistency-decoder": [ + [ + "VAEDecodeConsistencyDecoder", + "VAELoaderConsistencyDecoder" + ], + { + "title_aux": "Consistency Decoder" + } + ], + "https://github.com/shadowcz007/comfyui-edit-mask": [ + [ + "EditMask" + ], + { + "title_aux": "comfyui-edit-mask" + } + ], + "https://github.com/shadowcz007/comfyui-liveportrait": [ + [ + "FaceCropInfo", + "LivePortraitNode", + "Retargeting" + ], + { + "title_aux": "comfyui-liveportrait" + } + ], + "https://github.com/shadowcz007/comfyui-mixlab-nodes": [ + [ + "3DImage", + "AppInfo", + "ApplyVisualStylePrompting_", + "AreaToMask", + "AudioPlay", + "CenterImage", + "CkptNames_", + "Color", + "ComparingTwoFrames_", + "CompositeImages_", + "DynamicDelayProcessor", + "EmbeddingPrompt", + "EnhanceImage", + "FaceToMask", + "FeatheredMask", + "FloatSlider", + "FloatingVideo", + "Font", + "GLIGENTextBoxApply_Advanced", + "GetImageSize_", + "GradientImage", + "GridDisplayAndSave", + "GridInput", + "GridOutput", + "ImageColorTransfer", + "ImageCropByAlpha", + "ImageListToBatch_", + "ImagesPrompt_", + "IncrementingListNode_", + "IntNumber", + "JoinWithDelimiter", + "LimitNumber", + "ListSplit_", + "LoadImagesFromPath", + "LoadImagesFromURL", + "LoadImagesToBatch", + "LoraNames_", + "LoraPrompt", + "MaskListMerge_", + "MaskListReplace_", + "MergeLayers", + "MirroredImage", + "MultiplicationNode", + "NewLayer", + "NoiseImage", + "OutlineMask", + "PreviewMask_", + "PromptImage", + "PromptSimplification", + "PromptSlide", + "RandomPrompt", + "ResizeImageMixlab", + "SamplerNames_", + "SaveImageAndMetadata_", + "SaveImageToLocal", + "ScreenShare", + "Seed_", + "ShowLayer", + "SmoothMask", + "SpeechRecognition", + "SpeechSynthesis", + "SplitImage", + "SplitLongMask", + "StyleAlignedBatchAlign_", + "StyleAlignedReferenceSampler_", + "StyleAlignedSampleReferenceLatents_", + "SvgImage", + "SwitchByIndex", + "TESTNODE_", + "TESTNODE_TOKEN", + "TextImage", + "TextInput_", + "TextToNumber", + "TransparentImage", + "VAEDecodeConsistencyDecoder", + "VAELoaderConsistencyDecoder" + ], + { + "title_aux": "comfyui-mixlab-nodes" + } + ], + "https://github.com/shadowcz007/comfyui-sound-lab": [ + [ + "AudioPlay", + "Musicgen_", + "StableAudio_" + ], + { + "title_aux": "comfyui-sound-lab" + } + ], + "https://github.com/shadowcz007/comfyui-ultralytics-yolo": [ + [ + "DetectByLabel" + ], + { + "title_aux": "comfyui-ultralytics-yolo" + } + ], + "https://github.com/shi3z/ComfyUI_Memeplex_DALLE": [ + [ + "DallERender", + "GPT", + "MemeplexCustomSDXLRender", + "MemeplexRender", + "TextInput", + "TextSend" + ], + { + "title_aux": "ComfyUI_Memeplex_DALLE" + } + ], + "https://github.com/shiimizu/ComfyUI-PhotoMaker-Plus": [ + [ + "PhotoMakerEncodePlus", + "PhotoMakerStyles", + "PrepImagesForClipVisionFromPath" + ], + { + "title_aux": "ComfyUI PhotoMaker Plus" + } + ], + "https://github.com/shiimizu/ComfyUI-TiledDiffusion": [ + [ + "NoiseInversion", + "TiledDiffusion", + "VAEDecodeTiled_TiledDiffusion", + "VAEEncodeTiled_TiledDiffusion" + ], + { + "title_aux": "Tiled Diffusion & VAE for ComfyUI" + } + ], + "https://github.com/shiimizu/ComfyUI_smZNodes": [ + [ + "smZ CLIPTextEncode", + "smZ Settings" + ], + { + "title_aux": "smZNodes" + } + ], + "https://github.com/shingo1228/ComfyUI-SDXL-EmptyLatentImage": [ + [ + "SDXL Empty Latent Image" + ], + { + "title_aux": "ComfyUI-SDXL-EmptyLatentImage" + } + ], + "https://github.com/shingo1228/ComfyUI-send-eagle-slim": [ + [ + "Send Eagle with text", + "Send Webp Image to Eagle" + ], + { + "title_aux": "ComfyUI-send-Eagle(slim)" + } + ], + "https://github.com/shobhitic/ComfyUI-PlusMinusTextClip": [ + [ + "PlusMinusTextClip" + ], + { + "title_aux": "PlusMinusTextClip - Single node for Positive and Negative Prompts" + } + ], + "https://github.com/shockz0rz/ComfyUI_InterpolateEverything": [ + [ + "OpenposePreprocessorInterpolate" + ], + { + "title_aux": "InterpolateEverything" + } + ], + "https://github.com/shockz0rz/comfy-easy-grids": [ + [ + "FloatToText", + "GridFloatList", + "GridFloats", + "GridIntList", + "GridInts", + "GridLoras", + "GridStringList", + "GridStrings", + "ImageGridCommander", + "IntToText", + "SaveImageGrid", + "TextConcatenator" + ], + { + "title_aux": "comfy-easy-grids" + } + ], + "https://github.com/sipherxyz/comfyui-art-venture": [ + [ + "AV_AwsBedrockClaudeApi", + "AV_AwsBedrockMistralApi", + "AV_CheckpointMerge", + "AV_CheckpointModelsToParametersPipe", + "AV_CheckpointSave", + "AV_ClaudeApi", + "AV_ControlNetEfficientLoader", + "AV_ControlNetEfficientLoaderAdvanced", + "AV_ControlNetEfficientStacker", + "AV_ControlNetEfficientStackerSimple", + "AV_ControlNetLoader", + "AV_ControlNetPreprocessor", + "AV_LLMApiConfig", + "AV_LLMChat", + "AV_LLMCompletion", + "AV_LLMMessage", + "AV_LoraListLoader", + "AV_LoraListStacker", + "AV_LoraLoader", + "AV_OpenAIApi", + "AV_ParametersPipeToCheckpointModels", + "AV_ParametersPipeToPrompts", + "AV_PromptsToParametersPipe", + "AV_SAMLoader", + "AV_VAELoader", + "AspectRatioSelector", + "BLIPCaption", + "BLIPLoader", + "BooleanPrimitive", + "CheckpointNameSelector", + "ColorBlend", + "ColorCorrect", + "DeepDanbooruCaption", + "DependenciesEdit", + "Fooocus_KSampler", + "Fooocus_KSamplerAdvanced", + "GetBoolFromJson", + "GetFloatFromJson", + "GetIntFromJson", + "GetObjectFromJson", + "GetSAMEmbedding", + "GetTextFromJson", + "ISNetLoader", + "ISNetSegment", + "ImageAlphaComposite", + "ImageApplyChannel", + "ImageExtractChannel", + "ImageGaussianBlur", + "ImageMuxer", + "ImageRepeat", + "ImageScaleDown", + "ImageScaleDownBy", + "ImageScaleDownToSize", + "ImageScaleToMegapixels", + "LaMaInpaint", + "LoadImageAsMaskFromUrl", + "LoadImageFromUrl", + "LoadJsonFromUrl", + "MergeModels", + "NumberScaler", + "OverlayInpaintedImage", + "OverlayInpaintedLatent", + "PrepareImageAndMaskForInpaint", + "QRCodeGenerator", + "RandomFloat", + "RandomInt", + "SAMEmbeddingToImage", + "SDXLAspectRatioSelector", + "SDXLPromptStyler", + "SeedSelector", + "StringToInt", + "StringToNumber" + ], + { + "title_aux": "comfyui-art-venture" + } + ], + "https://github.com/skfoo/ComfyUI-Coziness": [ + [ + "LoraTextExtractor-b1f83aa2", + "MultiLoraLoader-70bf3d77" + ], + { + "title_aux": "ComfyUI-Coziness" + } + ], + "https://github.com/slyt/comfyui-ollama-nodes": [ + [ + "BooleanToString", + "DownloadHuggingfaceModel", + "FloatToString", + "GenerateOllama", + "IntToString", + "ListModels", + "ListToString", + "PullModel" + ], + { + "title_aux": "comfyui-ollama-nodes" + } + ], + "https://github.com/smagnetize/kb-comfyui-nodes": [ + [ + "SingleImageDataUrlLoader" + ], + { + "title_aux": "kb-comfyui-nodes" + } + ], + "https://github.com/smthemex/ComfyUI_AnyDoor": [ + [ + "AnyDoor_LoadModel", + "AnyDoor_img2img" + ], + { + "title_aux": "ComfyUI_AnyDoor" + } + ], + "https://github.com/smthemex/ComfyUI_ChatGLM_API": [ + [ + "Glm_4_9b_Chat", + "Glm_4v_9b", + "Glm_Lcoal_Or_Repo", + "ZhipuaiApi_Character", + "ZhipuaiApi_Txt", + "ZhipuaiApi_img" + ], + { + "title_aux": "ComfyUI_ChatGLM_API" + } + ], + "https://github.com/smthemex/ComfyUI_CustomNet": [ + [ + "CustomNet_Plus" + ], + { + "title_aux": "ComfyUI_CustomNet" + } + ], + "https://github.com/smthemex/ComfyUI_HiDiffusion_Pro": [ + [ + "HI_Diffusers_Model_Loader", + "Hi_Sampler" + ], + { + "title_aux": "ComfyUI_HiDiffusion_Pro" + } + ], + "https://github.com/smthemex/ComfyUI_ID_Animator": [ + [ + "ID_Animator", + "ID_Repo_Choice" + ], + { + "title_aux": "ComfyUI_ID_Animator" + } + ], + "https://github.com/smthemex/ComfyUI_Llama3_8B": [ + [ + "ChatQA_1p5_8b", + "Local_Or_Repo_Choice", + "Meta_Llama3_8B", + "MiniCPM_Llama3_V25" + ], + { + "title_aux": "ComfyUI_Llama3_8B" + } + ], + "https://github.com/smthemex/ComfyUI_MS_Diffusion": [ + [ + "MS_Comic_Type", + "MSdiffusion_Model_Loader", + "MSdiffusion_Sampler" + ], + { + "title_aux": "ComfyUI_MS_Diffusion" + } + ], + "https://github.com/smthemex/ComfyUI_ParlerTTS": [ + [ + "PromptToAudio" + ], + { + "title_aux": "ComfyUI_ParlerTTS" + } + ], + "https://github.com/smthemex/ComfyUI_Pic2Story": [ + [ + "Pic2Story" + ], + { + "title_aux": "ComfyUI_Pic2Story" + } + ], + "https://github.com/smthemex/ComfyUI_Pipeline_Tool": [ + [ + "Pipeline_Tool" + ], + { + "title_aux": "ComfyUI_Pipeline_Tool" + } + ], + "https://github.com/smthemex/ComfyUI_Pops": [ + [ + "Imgae_To_Path", + "Pops_Prior_Embedding", + "Pops_Repo_Choice", + "Pops_Sampler" + ], + { + "title_aux": "ComfyUI_Pops" + } + ], + "https://github.com/smthemex/ComfyUI_StableAudio_Open": [ + [ + "StableAudio_Open", + "Use_LocalModel_Or_Repo" + ], + { + "title_aux": "ComfyUI_StableAudio_Open" + } + ], + "https://github.com/smthemex/ComfyUI_StoryDiffusion": [ + [ + "Comic_Type", + "Pre_Translate_prompt", + "Storydiffusion_Model_Loader", + "Storydiffusion_Sampler" + ], + { + "title_aux": "ComfyUI_StoryDiffusion" + } + ], + "https://github.com/smthemex/ComfyUI_Streamv2v_Plus": [ + [ + "Load_Stream", + "Text2IMG", + "Video2Video", + "WebCam2Video" + ], + { + "title_aux": "ComfyUI_Streamv2v_Plus" + } + ], + "https://github.com/space-nuko/ComfyUI-Disco-Diffusion": [ + [ + "DiscoDiffusion_DiscoDiffusion", + "DiscoDiffusion_DiscoDiffusionExtraSettings", + "DiscoDiffusion_GuidedDiffusionLoader", + "DiscoDiffusion_OpenAICLIPLoader" + ], + { + "title_aux": "Disco Diffusion" + } + ], + "https://github.com/space-nuko/ComfyUI-OpenPose-Editor": [ + [ + "Nui.OpenPoseEditor" + ], + { + "title_aux": "OpenPose Editor" + } + ], + "https://github.com/space-nuko/nui-suite": [ + [ + "Nui.DynamicPromptsTextGen", + "Nui.FeelingLuckyTextGen", + "Nui.OutputString" + ], + { + "title_aux": "nui suite" + } + ], + "https://github.com/spacepxl/ComfyUI-Florence-2": [ + [ + "Florence2", + "Florence2Postprocess", + "Florence2PostprocessAll", + "LoadFlorence2Model" + ], + { + "title_aux": "ComfyUI-Florence-2" + } + ], + "https://github.com/spacepxl/ComfyUI-HQ-Image-Save": [ + [ + "LoadEXR", + "LoadEXRFrames", + "LoadLatentEXR", + "SaveEXR", + "SaveEXRFrames", + "SaveLatentEXR", + "SaveTiff" + ], + { + "title_aux": "ComfyUI-HQ-Image-Save" + } + ], + "https://github.com/spacepxl/ComfyUI-Image-Filters": [ + [ + "AdainFilterLatent", + "AdainImage", + "AdainLatent", + "AlphaClean", + "AlphaMatte", + "BatchAlign", + "BatchAverageImage", + "BatchAverageUnJittered", + "BatchNormalizeImage", + "BatchNormalizeLatent", + "BetterFilmGrain", + "BilateralFilterImage", + "BlurImageFast", + "BlurMaskFast", + "ClampOutliers", + "ColorMatchImage", + "ConvertNormals", + "DifferenceChecker", + "DilateErodeMask", + "EnhanceDetail", + "ExposureAdjust", + "FrequencyCombine", + "FrequencySeparate", + "GameOfLife", + "GuidedFilterAlpha", + "GuidedFilterImage", + "ImageConstant", + "ImageConstantHSV", + "InstructPixToPixConditioningAdvanced", + "JitterImage", + "Keyer", + "LatentNormalizeShuffle", + "LatentStats", + "MedianFilterImage", + "NormalMapSimple", + "OffsetLatentImage", + "PrintSigmas", + "RelightSimple", + "RemapRange", + "RestoreDetail", + "SharpenFilterLatent", + "ShuffleChannels", + "Tonemap", + "UnJitterImage", + "UnTonemap", + "VisualizeLatents" + ], + { + "title_aux": "ComfyUI-Image-Filters" + } + ], + "https://github.com/spacepxl/ComfyUI-RAVE": [ + [ + "ConditioningDebug", + "ImageGridCompose", + "ImageGridDecompose", + "KSamplerRAVE", + "LatentGridCompose", + "LatentGridDecompose" + ], + { + "title_aux": "ComfyUI-RAVE" + } + ], + "https://github.com/spacepxl/ComfyUI-StyleGan": [ + [ + "BatchAverageStyleGANLatents", + "BlendStyleGANLatents", + "GenerateStyleGANLatent", + "LoadStyleGAN", + "StyleGANInversion", + "StyleGANLatentFromBatch", + "StyleGANSampler" + ], + { + "title_aux": "ComfyUI-StyleGan" + } + ], + "https://github.com/spinagon/ComfyUI-seam-carving": [ + [ + "SeamCarving" + ], + { + "title_aux": "ComfyUI-seam-carving" + } + ], + "https://github.com/spinagon/ComfyUI-seamless-tiling": [ + [ + "CircularVAEDecode", + "MakeCircularVAE", + "OffsetImage", + "SeamlessTile" + ], + { + "title_aux": "Seamless tiling Node for ComfyUI" + } + ], + "https://github.com/spro/comfyui-mirror": [ + [ + "LatentMirror" + ], + { + "title_aux": "Latent Mirror node for ComfyUI" + } + ], + "https://github.com/ssitu/ComfyUI_UltimateSDUpscale": [ + [ + "UltimateSDUpscale", + "UltimateSDUpscaleCustomSample", + "UltimateSDUpscaleNoUpscale" + ], + { + "title_aux": "UltimateSDUpscale" + } + ], + "https://github.com/ssitu/ComfyUI_fabric": [ + [ + "FABRICPatchModel", + "FABRICPatchModelAdv", + "KSamplerAdvFABRICAdv", + "KSamplerFABRIC", + "KSamplerFABRICAdv" + ], + { + "title_aux": "ComfyUI fabric" + } + ], + "https://github.com/ssitu/ComfyUI_restart_sampling": [ + [ + "KRestartSampler", + "KRestartSamplerAdv", + "KRestartSamplerCustom", + "KRestartSamplerSimple", + "RestartSampler", + "RestartScheduler" + ], + { + "title_aux": "Restart Sampling" + } + ], + "https://github.com/ssitu/ComfyUI_roop": [ + [ + "RoopImproved", + "roop" + ], + { + "title_aux": "ComfyUI roop" + } + ], + "https://github.com/stavsap/comfyui-ollama": [ + [ + "OllamaGenerate", + "OllamaGenerateAdvance", + "OllamaVision" + ], + { + "title_aux": "ComfyUI Ollama" + } + ], + "https://github.com/storyicon/comfyui_musev_evolved": [ + [ + "AnimationZoom (comfyui_musev_evolved)", + "ImageSelector (comfyui_musev_evolved)", + "MuseVImg2Vid V1 (comfyui_musev_evolved)", + "MuseVPredictor V1 (comfyui_musev_evolved)" + ], + { + "author": "infguo", + "title_aux": "ComfyUI MuseV Evolved" + } + ], + "https://github.com/storyicon/comfyui_segment_anything": [ + [ + "GroundingDinoModelLoader (segment anything)", + "GroundingDinoSAMSegment (segment anything)", + "InvertMask (segment anything)", + "IsMaskEmpty", + "SAMModelLoader (segment anything)" + ], + { + "title_aux": "segment anything" + } + ], + "https://github.com/strimmlarn/ComfyUI_Strimmlarns_aesthetic_score": [ + [ + "AesthetlcScoreSorter", + "CalculateAestheticScore", + "LoadAesteticModel", + "ScoreToNumber" + ], + { + "title_aux": "ComfyUI_Strimmlarns_aesthetic_score" + } + ], + "https://github.com/styler00dollar/ComfyUI-deepcache": [ + [ + "DeepCache" + ], + { + "title_aux": "ComfyUI-deepcache" + } + ], + "https://github.com/styler00dollar/ComfyUI-sudo-latent-upscale": [ + [ + "SudoLatentUpscale" + ], + { + "title_aux": "ComfyUI-sudo-latent-upscale" + } + ], + "https://github.com/sugarkwork/comfyui_cohere": [ + [ + "SimpleCohereNode" + ], + { + "title_aux": "comfyui_cohere" + } + ], + "https://github.com/sugarkwork/comfyui_tag_fillter": [ + [ + "TagFilter", + "TagMerger", + "TagRemover", + "TagReplace", + "TagSwitcher" + ], + { + "title_aux": "comfyui_tag_filter" + } + ], + "https://github.com/superyoman/comfyui_lumaAPI": [ + [ + "LUMA_API_YoC", + "LUMA_API_result_YoC" + ], + { + "title_aux": "comfyui_lumaAPI" + } + ], + "https://github.com/syllebra/bilbox-comfyui": [ + [ + "BilboXLut", + "BilboXPhotoPrompt", + "BilboXVignette" + ], + { + "title_aux": "BilboX's ComfyUI Custom Nodes" + } + ], + "https://github.com/sylym/comfy_vid2vid": [ + [ + "CheckpointLoaderSimpleSequence", + "DdimInversionSequence", + "KSamplerSequence", + "LoadImageMaskSequence", + "LoadImageSequence", + "LoraLoaderSequence", + "SetLatentNoiseSequence", + "TrainUnetSequence", + "VAEEncodeForInpaintSequence" + ], + { + "title_aux": "Vid2vid" + } + ], + "https://github.com/szhublox/ambw_comfyui": [ + [ + "Auto Merge Block Weighted", + "CLIPMergeSimple", + "CheckpointSave", + "ModelMergeBlocks", + "ModelMergeSimple" + ], + { + "title_aux": "Auto-MBW" + } + ], + "https://github.com/taabata/Comfy_Syrian_Falcon_Nodes/raw/main/SyrianFalconNodes.py": [ + [ + "CompositeImage", + "KSamplerAlternate", + "KSamplerPromptEdit", + "KSamplerPromptEditAndAlternate", + "LoopBack", + "QRGenerate", + "WordAsImage" + ], + { + "title_aux": "Syrian Falcon Nodes" + } + ], + "https://github.com/taabata/LCM_Inpaint-Outpaint_Comfy": [ + [ + "ComfyNodesToSaveCanvas", + "FloatNumber", + "FreeU_LCM", + "ImageDims", + "ImageOutputToComfyNodes", + "ImageResize", + "ImageShuffle", + "ImageSwitch", + "LCMGenerate", + "LCMGenerate_ReferenceOnly", + "LCMGenerate_SDTurbo", + "LCMGenerate_img2img", + "LCMGenerate_img2img_IPAdapter", + "LCMGenerate_img2img_controlnet", + "LCMGenerate_inpaintv2", + "LCMGenerate_inpaintv3", + "LCMLoader", + "LCMLoader_RefInpaint", + "LCMLoader_ReferenceOnly", + "LCMLoader_SDTurbo", + "LCMLoader_controlnet", + "LCMLoader_controlnet_inpaint", + "LCMLoader_img2img", + "LCMLoraLoader_inpaint", + "LCMLoraLoader_ipadapter", + "LCMLora_inpaint", + "LCMLora_inpaintV2", + "LCMLora_ipadapter", + "LCMT2IAdapter", + "LCM_IPAdapter", + "LCM_IPAdapter_inpaint", + "LCM_outpaint_prep", + "LoadImageNode_LCM", + "Loader_SegmindVega", + "OutpaintCanvasTool", + "SaveImage_Canvas", + "SaveImage_LCM", + "SaveImage_Puzzle", + "SaveImage_PuzzleV2", + "SegmindVega", + "SettingsSwitch", + "stitch" + ], + { + "title_aux": "LCM_Inpaint-Outpaint_Comfy" + } + ], + "https://github.com/talesofai/comfyui-browser": [ + [ + "DifyTextGenerator //Browser", + "LoadImageByUrl //Browser", + "SelectInputs //Browser", + "UploadToRemote //Browser", + "XyzPlot //Browser" + ], + { + "title_aux": "ComfyUI Browser" + } + ], + "https://github.com/teward/ComfyUI-Helper-Nodes": [ + [ + "HelperNodes_CfgScale", + "HelperNodes_CheckpointSelector", + "HelperNodes_MultilineStringLiteral", + "HelperNodes_Prompt", + "HelperNodes_SDXLCommonResolutions", + "HelperNodes_SamplerSelector", + "HelperNodes_SaveImage", + "HelperNodes_SchedulerSelector", + "HelperNodes_SeedSelector", + "HelperNodes_Steps", + "HelperNodes_StringLiteral", + "HelperNodes_VAESelector", + "HelperNodes_WidthHeight" + ], + { + "title_aux": "ComfyUI-Helper-Nodes" + } + ], + "https://github.com/theUpsider/ComfyUI-Logic": [ + [ + "Bool-\ud83d\udd2c", + "Compare-\ud83d\udd2c", + "DebugPrint-\ud83d\udd2c", + "Float-\ud83d\udd2c", + "If ANY return A else B-\ud83d\udd2c", + "Int-\ud83d\udd2c", + "String-\ud83d\udd2c" + ], + { + "title_aux": "ComfyUI-Logic" + } + ], + "https://github.com/theUpsider/ComfyUI-Styles_CSV_Loader": [ + [ + "Load Styles CSV" + ], + { + "title_aux": "Styles CSV Loader Extension for ComfyUI" + } + ], + "https://github.com/thecooltechguy/ComfyUI-MagicAnimate": [ + [ + "MagicAnimate", + "MagicAnimateModelLoader" + ], + { + "title_aux": "ComfyUI-MagicAnimate" + } + ], + "https://github.com/thecooltechguy/ComfyUI-Stable-Video-Diffusion": [ + [ + "SVDDecoder", + "SVDModelLoader", + "SVDSampler", + "SVDSimpleImg2Vid" + ], + { + "title_aux": "ComfyUI Stable Video Diffusion" + } + ], + "https://github.com/tiankuan93/ComfyUI-V-Express": [ + [ + "Load_Audio_Path", + "Load_Audio_Path_From_Video", + "Load_Image_Path", + "Load_Kps_Path", + "Load_Kps_Path_From_Video", + "Load_Video_Path", + "VEINTConstant", + "VEPreview_Video", + "VEStringConstant", + "V_Express_Loader", + "V_Express_Sampler" + ], + { + "title_aux": "V-Express: Conditional Dropout for Progressive Training of Portrait Video Generation" + } + ], + "https://github.com/tianlang0704/ComfyUI-StableProjectorzBridge": [ + [ + "ProjectorzControlnetInput", + "ProjectorzControlnetParameter", + "ProjectorzInitInput", + "ProjectorzOutput", + "ProjectorzParameter", + "ProjectorzStringToFloat", + "ProjectorzStringToInt" + ], + { + "title_aux": "Stable Projectorz Bridge" + } + ], + "https://github.com/time-river/ComfyUI-CLIPSeg/raw/main/custom_nodes/clipseg.py": [ + [ + "CLIPSeg", + "CombineSegMasks" + ], + { + "title_aux": "CLIPSeg" + } + ], + "https://github.com/tmagara/ComfyUI-Prediction-Boost": [ + [ + "PredictionBoost" + ], + { + "title_aux": "ComfyUI-Prediction-Boost" + } + ], + "https://github.com/tocubed/ComfyUI-AudioReactor": [ + [ + "AudioFrameTransformBeats", + "AudioFrameTransformShadertoy", + "AudioLoadPath", + "Shadertoy" + ], + { + "title_aux": "ComfyUI-AudioReactor" + } + ], + "https://github.com/tooldigital/ComfyUI-Yolo-Cropper": [ + [ + "ToolYoloCropper" + ], + { + "title_aux": "Easy automatic (square) image cropper using Yolo" + } + ], + "https://github.com/toxicwind/ComfyUI-TTools": [ + [ + "TTools Extract JSON", + "TTools SD3 Resolution Solver" + ], + { + "title_aux": "TTools for ComfyUI" + } + ], + "https://github.com/toyxyz/ComfyUI_toyxyz_test_nodes": [ + [ + "CaptureWebcam", + "ImageResize_Padding", + "LatentDelay", + "LoadWebcamImage", + "SaveImagetoPath" + ], + { + "title_aux": "ComfyUI_toyxyz_test_nodes" + } + ], + "https://github.com/traugdor/ComfyUI-quadMoons-nodes": [ + [ + "quadmoonCLIPTextEncode", + "quadmoonChangeBackground", + "quadmoonConvertBoolToString", + "quadmoonConvertFloatToString", + "quadmoonConvertIntToString", + "quadmoonConvertNormalizeHW", + "quadmoonConvertNumberToString", + "quadmoonINTConditionalOperation", + "quadmoonKSampler", + "quadmoonKSamplerAdvanced", + "quadmoonLoadConfigs", + "quadmoonModelLoader", + "quadmoonSaveNeg", + "quadmoonSavePrompt", + "quadmoonSmartNeg", + "quadmoonSmartPrompt", + "quadmoonThebutton" + ], + { + "author": "quadmoon (https://github.com/traugdor)", + "description": "These are just some nodes I wanted and couldn't find where anyone else had made them yet.", + "nickname": "quadmoon's Nodes", + "title": "quadmoon's ComfyUI nodes", + "title_aux": "quadmoon's ComfyUI nodes" + } + ], + "https://github.com/tritant/ComfyUI_CreaPrompt": [ + [ + "CreaPrompt", + "CreaPrompt List" + ], + { + "title_aux": "ComfyUI-CreaPrompt" + } + ], + "https://github.com/trojblue/trNodes": [ + [ + "trColorCorrection", + "trLayering", + "trRouter", + "trRouterLonger" + ], + { + "title_aux": "trNodes" + } + ], + "https://github.com/trumanwong/ComfyUI-NSFW-Detection": [ + [ + "NSFWDetection" + ], + { + "title_aux": "ComfyUI-NSFW-Detection" + } + ], + "https://github.com/tsogzark/ComfyUI-load-image-from-url": [ + [ + "LoadImageFromUrlOrPath" + ], + { + "title_aux": "ComfyUI-load-image-from-url" + } + ], + "https://github.com/ttulttul/ComfyUI-Iterative-Mixer": [ + [ + "Batch Unsampler", + "Iterative Mixing KSampler", + "Iterative Mixing KSampler Advanced", + "IterativeMixingSampler", + "IterativeMixingScheduler", + "IterativeMixingSchedulerAdvanced", + "Latent Batch Comparison Plot", + "Latent Batch Statistics Plot", + "MixingMaskGenerator" + ], + { + "title_aux": "ComfyUI Iterative Mixing Nodes" + } + ], + "https://github.com/ttulttul/ComfyUI-Tensor-Operations": [ + [ + "Fast Image to Noise", + "Image Match Normalize", + "Latent Match Normalize" + ], + { + "title_aux": "ComfyUI-Tensor-Operations" + } + ], + "https://github.com/tudal/Hakkun-ComfyUI-nodes/raw/main/hakkun_nodes.py": [ + [ + "Any Converter", + "Calculate Upscale", + "Image Resize To Height", + "Image Resize To Width", + "Image size to string", + "Load Random Image", + "Load Text", + "Multi Text Merge", + "Prompt Parser", + "Random Line", + "Random Line 4" + ], + { + "title_aux": "Hakkun-ComfyUI-nodes" + } + ], + "https://github.com/tusharbhutt/Endless-Nodes": [ + [ + "ESS Aesthetic Scoring", + "ESS Combo Parameterizer", + "ESS Combo Parameterizer & Prompts", + "ESS Eight Input Text Switch", + "ESS Float to Integer", + "ESS Float to Number", + "ESS Float to String", + "ESS Float to X", + "ESS Image Reward", + "ESS Image Saver with JSON", + "ESS Integer to Float", + "ESS Integer to Number", + "ESS Integer to String", + "ESS Integer to X", + "ESS Number to Float", + "ESS Number to Integer", + "ESS Number to String", + "ESS Number to X", + "ESS Parameterizer", + "ESS Parameterizer & Prompts", + "ESS Six Float Output", + "ESS Six Input Text Switch", + "ESS Six Integer IO Switch", + "ESS Six Integer IO Widget", + "ESS String to Float", + "ESS String to Integer", + "ESS String to Num", + "ESS String to X", + "\u267e\ufe0f\ud83c\udf0a\u2728 Image Saver with JSON" + ], + { + "author": "BiffMunky", + "description": "A small set of nodes I created for various numerical and text inputs. Features image saver with ability to have JSON saved to separate folder, parameter collection nodes, two aesthetic scoring models, switches for text and numbers, and conversion of string to numeric and vice versa.", + "nickname": "\u267e\ufe0f\ud83c\udf0a\u2728", + "title": "Endless \ufe0f\ud83c\udf0a\u2728 Nodes", + "title_aux": "Endless \ufe0f\ud83c\udf0a\u2728 Nodes" + } + ], + "https://github.com/twri/sdxl_prompt_styler": [ + [ + "SDXLPromptStyler", + "SDXLPromptStylerAdvanced" + ], + { + "title_aux": "SDXL Prompt Styler" + } + ], + "https://github.com/ty0x2333/ComfyUI-Dev-Utils": [ + [ + "TY_ExecutionTime", + "TY_UploadAnything", + "TY_UrlDownload" + ], + { + "title_aux": "ComfyUI-Dev-Utils" + } + ], + "https://github.com/uarefans/ComfyUI-Fans": [ + [ + "Fans Prompt Styler Negative", + "Fans Prompt Styler Positive", + "Fans Styler", + "Fans Text Concatenate" + ], + { + "title_aux": "ComfyUI-Fans" + } + ], + "https://github.com/uetuluk/comfyui-webcam-node": [ + [ + "webcam_capture_node" + ], + { + "title_aux": "comfyui-webcam-node" + } + ], + "https://github.com/unwdef/unwdef-nodes-comfyui": [ + [ + "RandomTextFromMultiline", + "RandomizeLoras", + "RandomizeLorasStack", + "TextMultilineWithVariables" + ], + { + "title_aux": "unwdef-nodes" + } + ], + "https://github.com/vanche1212/ComfyUI-ZMG-Nodes": [ + [ + "VC_Load_Video_Path_Unified_Output", + "VC_Load_Video_Upload_Unified_Output", + "VC_Video_Combine_Unified_Output", + "Waveform2Audio", + "\ud83d\ude0bAPI Request Node", + "\ud83d\ude0bJSON Parser Node", + "\ud83d\ude0bOld Photo Colorization Node", + "\ud83d\ude0bOllama Request Node", + "\ud83d\ude0bSave Image Unified Output" + ], + { + "title_aux": "ZMG PLUGIN" + } + ], + "https://github.com/vanillacode314/SimpleWildcardsComfyUI": [ + [ + "SimpleConcat", + "SimpleWildcard" + ], + { + "author": "VanillaCode314", + "description": "A simple wildcard node for ComfyUI. Can also be used a style prompt node.", + "nickname": "Simple Wildcard", + "title": "Simple Wildcard", + "title_aux": "Simple Wildcard" + } + ], + "https://github.com/veighnsche/comfyui_gr85": [ + [ + "GR85_ContainsWord", + "GR85_ElementsConcatenator", + "GR85_ImageDimensionResizer", + "GR85_ImageSizer", + "GR85_InsertCharacter", + "GR85_LlmEnhancer", + "GR85_NextSeed", + "GR85_RandomAtmLocOutfit", + "GR85_RandomRatio", + "GR85_RandomTitleCharacter", + "GR85_RandomWildcardTagPicker", + "GR85_ShowText", + "GR85_StrSafe", + "GR85_TagInjector" + ], + { + "title_aux": "comfyui_gr85" + } + ], + "https://github.com/victorchall/comfyui_webcamcapture": [ + [ + "WebcamCapture" + ], + { + "title_aux": "Comfyui Webcam capture node" + } + ], + "https://github.com/vienteck/ComfyUI-Chat-GPT-Integration": [ + [ + "ChatGptPrompt" + ], + { + "title_aux": "ComfyUI-Chat-GPT-Integration" + } + ], + "https://github.com/violet-chen/comfyui-psd2png": [ + [ + "Psd2Png" + ], + { + "title_aux": "comfyui-psd2png" + } + ], + "https://github.com/viperyl/ComfyUI-BiRefNet": [ + [ + "BiRefNet" + ], + { + "title_aux": "ComfyUI-BiRefNet" + } + ], + "https://github.com/viperyl/ComfyUI-RGT": [ + [ + "RGT_Upscale" + ], + { + "title_aux": "ComfyUI-RGT" + } + ], + "https://github.com/vivax3794/ComfyUI-Sub-Nodes": [ + [ + "VIV_Default", + "VIV_Subgraph", + "VIV_Subgraph_Inputs", + "VIV_Subgraph_Outputs" + ], + { + "title_aux": "ComfyUI-Sub-Nodes" + } + ], + "https://github.com/vivax3794/ComfyUI-Vivax-Nodes": [ + [ + "Any String", + "Chunk Up", + "Get Chunk", + "Inspect", + "Join Chunks", + "Model From URL" + ], + { + "title_aux": "ComfyUI-Vivax-Nodes" + } + ], + "https://github.com/vsevolod-oparin/comfyui-kandinsky22": [ + [ + "comfy-kandinsky22-decoder-loader", + "comfy-kandinsky22-hint-combiner", + "comfy-kandinsky22-image-encoder", + "comfy-kandinsky22-img-latents", + "comfy-kandinsky22-latents", + "comfy-kandinsky22-movq-decoder", + "comfy-kandinsky22-positive-text-encoder", + "comfy-kandinsky22-prior-averaging-2", + "comfy-kandinsky22-prior-averaging-3", + "comfy-kandinsky22-prior-averaging-4", + "comfy-kandinsky22-prior-loader", + "comfy-kandinsky22-text-encoder", + "comfy-kandinsky22-unet-decoder" + ], + { + "title_aux": "Kandinsky 2.2 ComfyUI Plugin" + } + ], + "https://github.com/vxinhao/color2rgb/raw/main/color2rgb.py": [ + [ + "color2RGB" + ], + { + "title_aux": "color2rgb" + } + ], + "https://github.com/wTechArtist/ComfyUI-CustomNodes": [ + [ + "Image Blending Mode Mask" + ], + { + "title_aux": "ComfyUI-CustomNodes" + } + ], + "https://github.com/wallish77/wlsh_nodes": [ + [ + "Alternating KSampler (WLSH)", + "Build Filename String (WLSH)", + "CLIP +/- w/Text Unified (WLSH)", + "CLIP Positive-Negative (WLSH)", + "CLIP Positive-Negative XL (WLSH)", + "CLIP Positive-Negative XL w/Text (WLSH)", + "CLIP Positive-Negative w/Text (WLSH)", + "Checkpoint Loader w/Name (WLSH)", + "Empty Latent by Pixels (WLSH)", + "Empty Latent by Ratio (WLSH)", + "Empty Latent by Size (WLSH)", + "Generate Border Mask (WLSH)", + "Grayscale Image (WLSH)", + "Image Load with Metadata (WLSH)", + "Image Save with Prompt (WLSH)", + "Image Save with Prompt File (WLSH)", + "Image Save with Prompt/Info (WLSH)", + "Image Save with Prompt/Info File (WLSH)", + "Image Scale By Factor (WLSH)", + "Image Scale by Shortside (WLSH)", + "KSamplerAdvanced (WLSH)", + "Multiply Integer (WLSH)", + "Outpaint to Image (WLSH)", + "Prompt Weight (WLSH)", + "Quick Resolution Multiply (WLSH)", + "Resolutions by Ratio (WLSH)", + "SDXL Quick Empty Latent (WLSH)", + "SDXL Quick Image Scale (WLSH)", + "SDXL Resolutions (WLSH)", + "SDXL Steps (WLSH)", + "Save Positive Prompt(WLSH)", + "Save Prompt (WLSH)", + "Save Prompt/Info (WLSH)", + "Seed and Int (WLSH)", + "Seed to Number (WLSH)", + "Simple Pattern Replace (WLSH)", + "Simple String Combine (WLSH)", + "Time String (WLSH)", + "Upscale by Factor with Model (WLSH)", + "VAE Encode for Inpaint w/Padding (WLSH)" + ], + { + "title_aux": "wlsh_nodes" + } + ], + "https://github.com/web3nomad/ComfyUI_Invisible_Watermark": [ + [ + "InvisibleWatermarkEncode" + ], + { + "title_aux": "ComfyUI Invisible Watermark" + } + ], + "https://github.com/whatbirdisthat/cyberdolphin": [ + [ + "\ud83d\udc2c Gradio ChatInterface", + "\ud83d\udc2c OpenAI Advanced", + "\ud83d\udc2c OpenAI Compatible", + "\ud83d\udc2c OpenAI DALL\u00b7E", + "\ud83d\udc2c OpenAI Simple" + ], + { + "title_aux": "cyberdolphin" + } + ], + "https://github.com/whmc76/ComfyUI-Openpose-Editor-Plus": [ + [ + "CDL.OpenPoseEditorPlus" + ], + { + "title_aux": "ComfyUI-Openpose-Editor-Plus" + } + ], + "https://github.com/wmatson/easy-comfy-nodes": [ + [ + "EZAssocDictNode", + "EZAssocImgNode", + "EZAssocStrNode", + "EZEmptyDictNode", + "EZHttpPostNode", + "EZLoadImgBatchFromUrlsNode", + "EZLoadImgFromUrlNode", + "EZRemoveImgBackground", + "EZS3Uploader" + ], + { + "title_aux": "easy-comfy-nodes" + } + ], + "https://github.com/wolfden/ComfyUi_PromptStylers": [ + [ + "SDXLPromptStylerAll", + "SDXLPromptStylerHorror", + "SDXLPromptStylerMisc", + "SDXLPromptStylerbyArtist", + "SDXLPromptStylerbyCamera", + "SDXLPromptStylerbyComposition", + "SDXLPromptStylerbyCyberpunkSurrealism", + "SDXLPromptStylerbyDepth", + "SDXLPromptStylerbyEnvironment", + "SDXLPromptStylerbyFantasySetting", + "SDXLPromptStylerbyFilter", + "SDXLPromptStylerbyFocus", + "SDXLPromptStylerbyImpressionism", + "SDXLPromptStylerbyLighting", + "SDXLPromptStylerbyMileHigh", + "SDXLPromptStylerbyMood", + "SDXLPromptStylerbyMythicalCreature", + "SDXLPromptStylerbyOriginal", + "SDXLPromptStylerbyQuantumRealism", + "SDXLPromptStylerbySteamPunkRealism", + "SDXLPromptStylerbySubject", + "SDXLPromptStylerbySurrealism", + "SDXLPromptStylerbyTheme", + "SDXLPromptStylerbyTimeofDay", + "SDXLPromptStylerbyWyvern", + "SDXLPromptbyCelticArt", + "SDXLPromptbyContemporaryNordicArt", + "SDXLPromptbyFashionArt", + "SDXLPromptbyGothicRevival", + "SDXLPromptbyIrishFolkArt", + "SDXLPromptbyRomanticNationalismArt", + "SDXLPromptbySportsArt", + "SDXLPromptbyStreetArt", + "SDXLPromptbyVikingArt", + "SDXLPromptbyWildlifeArt" + ], + { + "title_aux": "SDXL Prompt Styler (customized version by wolfden)" + } + ], + "https://github.com/wolfden/ComfyUi_String_Function_Tree": [ + [ + "StringFunction" + ], + { + "title_aux": "ComfyUi_String_Function_Tree" + } + ], + "https://github.com/wsippel/comfyui_ws/raw/main/sdxl_utility.py": [ + [ + "SDXLResolutionPresets" + ], + { + "title_aux": "SDXLResolutionPresets" + } + ], + "https://github.com/wujm424606/ComfyUi-Ollama-YN": [ + [ + "OllamaGenerate", + "OllamaGenerateAdvance", + "OllamaSpecialGenerateAdvance", + "OllamaVision" + ], + { + "title_aux": "ComfyUi-Ollama-YN" + } + ], + "https://github.com/wutipong/ComfyUI-TextUtils": [ + [ + "Text Utils - Join N-Elements of String List", + "Text Utils - Join String List", + "Text Utils - Join Strings", + "Text Utils - Split String to List" + ], + { + "title_aux": "ComfyUI-TextUtils" + } + ], + "https://github.com/wwwins/ComfyUI-Simple-Aspect-Ratio": [ + [ + "SimpleAspectRatio" + ], + { + "title_aux": "ComfyUI-Simple-Aspect-Ratio" + } + ], + "https://github.com/xXAdonesXx/NodeGPT": [ + [ + "AppendAgent", + "Assistant", + "Chat", + "ChatGPT", + "CombineInput", + "Conditioning", + "CostumeAgent_1", + "CostumeAgent_2", + "CostumeMaster_1", + "Critic", + "DisplayString", + "DisplayTextAsImage", + "EVAL", + "Engineer", + "Executor", + "GroupChat", + "Image_generation_Conditioning", + "LM_Studio", + "LoadAPIconfig", + "LoadTXT", + "MemGPT", + "Memory_Excel", + "Model_1", + "Ollama", + "Output2String", + "Planner", + "Scientist", + "TextCombine", + "TextGeneration", + "TextGenerator", + "TextInput", + "TextOutput", + "UserProxy", + "llama-cpp", + "llava", + "oobaboogaOpenAI" + ], + { + "title_aux": "NodeGPT" + } + ], + "https://github.com/xiaoxiaodesha/hd_node": [ + [ + "Combine HDMasks", + "Cover HDMasks", + "HD FaceIndex", + "HD GetMaskArea", + "HD Image Levels", + "HD SmoothEdge", + "HD UltimateSDUpscale" + ], + { + "title_aux": "hd-nodes-comfyui" + } + ], + "https://github.com/xliry/ComfyUI_SendDiscord": [ + [ + "SendDiscord" + ], + { + "title_aux": "ComfyUI_SendDiscord" + } + ], + "https://github.com/xuhongming251/ComfyUI-GPEN": [ + [ + "FaceEnhancement" + ], + { + "title_aux": "ComfyUI-GPEN" + } + ], + "https://github.com/xuhongming251/ComfyUI-MuseTalkUtils": [ + [ + "MuseTalkPostprocess", + "MuseTalkPreprocess", + "MuseTalkTrain", + "MuseTalkTrainPreprocess", + "MuseTalkUncropMask" + ], + { + "title_aux": "ComfyUI-MuseTalkUtils" + } + ], + "https://github.com/yffyhk/comfyui_auto_danbooru": [ + [ + "GetDanbooru", + "TagEncode" + ], + { + "title_aux": "comfyui_auto_danbooru" + } + ], + "https://github.com/yiwangsimple/ComfyUI_GroqChat": [ + [ + "GroqChatNode", + "PaliGemmaPixelProse" + ], + { + "title_aux": "comfy-groqchat" + } + ], + "https://github.com/yolain/ComfyUI-Easy-Use": [ + [ + "dynamicThresholdingFull", + "easy LLLiteLoader", + "easy XYInputs: CFG Scale", + "easy XYInputs: Checkpoint", + "easy XYInputs: ControlNet", + "easy XYInputs: Denoise", + "easy XYInputs: Lora", + "easy XYInputs: ModelMergeBlocks", + "easy XYInputs: NegativeCond", + "easy XYInputs: NegativeCondList", + "easy XYInputs: PositiveCond", + "easy XYInputs: PositiveCondList", + "easy XYInputs: PromptSR", + "easy XYInputs: Sampler/Scheduler", + "easy XYInputs: Seeds++ Batch", + "easy XYInputs: Steps", + "easy XYPlot", + "easy XYPlotAdvanced", + "easy a1111Loader", + "easy applyBrushNet", + "easy applyFooocusInpaint", + "easy applyInpaint", + "easy applyPowerPaint", + "easy boolean", + "easy cascadeKSampler", + "easy cascadeLoader", + "easy ckptNames", + "easy cleanGpuUsed", + "easy clearCacheAll", + "easy clearCacheKey", + "easy comfyLoader", + "easy compare", + "easy controlnetLoader", + "easy controlnetLoaderADV", + "easy controlnetNames", + "easy controlnetStack", + "easy convertAnything", + "easy detailerFix", + "easy dynamiCrafterLoader", + "easy float", + "easy fullCascadeKSampler", + "easy fullLoader", + "easy fullkSampler", + "easy globalSeed", + "easy hiresFix", + "easy humanSegmentation", + "easy hunyuanDiTLoader", + "easy icLightApply", + "easy if", + "easy imageBatchToImageList", + "easy imageChooser", + "easy imageColorMatch", + "easy imageConcat", + "easy imageCount", + "easy imageCropFromMask", + "easy imageDetailTransfer", + "easy imageInsetCrop", + "easy imageInterrogator", + "easy imageListToImageBatch", + "easy imagePixelPerfect", + "easy imageRatio", + "easy imageRemBg", + "easy imageSave", + "easy imageScaleDown", + "easy imageScaleDownBy", + "easy imageScaleDownToSize", + "easy imageSize", + "easy imageSizeByLongerSide", + "easy imageSizeBySide", + "easy imageSplitGrid", + "easy imageSplitList", + "easy imageSwitch", + "easy imageToBase64", + "easy imageToMask", + "easy imageUncropFromBBOX", + "easy imagesSplitImage", + "easy injectNoiseToLatent", + "easy instantIDApply", + "easy instantIDApplyADV", + "easy int", + "easy ipadapterApply", + "easy ipadapterApplyADV", + "easy ipadapterApplyEmbeds", + "easy ipadapterApplyEncoder", + "easy ipadapterApplyFromParams", + "easy ipadapterApplyRegional", + "easy ipadapterStyleComposition", + "easy isSDXL", + "easy joinImageBatch", + "easy kSampler", + "easy kSamplerDownscaleUnet", + "easy kSamplerInpainting", + "easy kSamplerLayerDiffusion", + "easy kSamplerSDTurbo", + "easy kSamplerTiled", + "easy latentCompositeMaskedWithCond", + "easy latentNoisy", + "easy loadImageBase64", + "easy loraStack", + "easy negative", + "easy pipeBatchIndex", + "easy pipeEdit", + "easy pipeIn", + "easy pipeOut", + "easy pipeToBasicPipe", + "easy pixArtLoader", + "easy portraitMaster", + "easy poseEditor", + "easy positive", + "easy preDetailerFix", + "easy preMaskDetailerFix", + "easy preSampling", + "easy preSamplingAdvanced", + "easy preSamplingCascade", + "easy preSamplingCustom", + "easy preSamplingDynamicCFG", + "easy preSamplingLayerDiffusion", + "easy preSamplingLayerDiffusionADDTL", + "easy preSamplingNoiseIn", + "easy preSamplingSdTurbo", + "easy prompt", + "easy promptConcat", + "easy promptLine", + "easy promptList", + "easy promptReplace", + "easy pulIDApply", + "easy pulIDApplyADV", + "easy rangeFloat", + "easy rangeInt", + "easy removeLocalImage", + "easy samLoaderPipe", + "easy seed", + "easy showAnything", + "easy showLoaderSettingsNames", + "easy showSpentTime", + "easy showTensorShape", + "easy sliderControl", + "easy stableDiffusion3API", + "easy string", + "easy styleAlignedBatchAlign", + "easy stylesSelector", + "easy sv3dLoader", + "easy svdLoader", + "easy textSwitch", + "easy ultralyticsDetectorPipe", + "easy unSampler", + "easy wildcards", + "easy xyAny", + "easy zero123Loader" + ], + { + "title_aux": "ComfyUI Easy Use" + } + ], + "https://github.com/yolanother/DTAIComfyImageSubmit": [ + [ + "DTSimpleSubmitImage", + "DTSubmitImage" + ], + { + "title_aux": "Comfy AI DoubTech.ai Image Sumission Node" + } + ], + "https://github.com/yolanother/DTAIComfyLoaders": [ + [ + "DTCLIPLoader", + "DTCLIPVisionLoader", + "DTCheckpointLoader", + "DTCheckpointLoaderSimple", + "DTControlNetLoader", + "DTDiffControlNetLoader", + "DTDiffusersLoader", + "DTGLIGENLoader", + "DTLoadImage", + "DTLoadImageMask", + "DTLoadLatent", + "DTLoraLoader", + "DTLorasLoader", + "DTStyleModelLoader", + "DTUpscaleModelLoader", + "DTVAELoader", + "DTunCLIPCheckpointLoader" + ], + { + "title_aux": "Comfy UI Online Loaders" + } + ], + "https://github.com/yolanother/DTAIComfyPromptAgent": [ + [ + "DTPromptAgent", + "DTPromptAgentString" + ], + { + "title_aux": "Comfy UI Prompt Agent" + } + ], + "https://github.com/yolanother/DTAIComfyQRCodes": [ + [ + "QRCode" + ], + { + "title_aux": "Comfy UI QR Codes" + } + ], + "https://github.com/yolanother/DTAIComfyVariables": [ + [ + "DTCLIPTextEncode", + "DTSingleLineStringVariable", + "DTSingleLineStringVariableNoClip", + "FloatVariable", + "IntVariable", + "StringFormat", + "StringFormatSingleLine", + "StringVariable" + ], + { + "title_aux": "Variables for Comfy UI" + } + ], + "https://github.com/yolanother/DTAIImageToTextNode": [ + [ + "DTAIImageToTextNode", + "DTAIImageUrlToTextNode" + ], + { + "title_aux": "Image to Text Node" + } + ], + "https://github.com/youyegit/tdxh_node_comfyui": [ + [ + "TdxhBoolNumber", + "TdxhClipVison", + "TdxhControlNetApply", + "TdxhControlNetProcessor", + "TdxhFloatInput", + "TdxhImageToSize", + "TdxhImageToSizeAdvanced", + "TdxhImg2ImgLatent", + "TdxhIntInput", + "TdxhLoraLoader", + "TdxhOnOrOff", + "TdxhReference", + "TdxhStringInput", + "TdxhStringInputTranslator" + ], + { + "title_aux": "tdxh_node_comfyui" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Depth-Anything-Tensorrt": [ + [ + "DepthAnythingTensorrt" + ], + { + "title_aux": "ComfyUI Depth Anything TensorRT" + } + ], + "https://github.com/yuvraj108c/ComfyUI-PiperTTS": [ + [ + "PiperTTS" + ], + { + "title_aux": "ComfyUI PiperTTS" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Pronodes": [ + [ + "LoadImageFromOutputDirectoryNode", + "LoadYoutubeVideoNode", + "PreviewVHSAudioNode", + "SaveAndOverwriteImageNode", + "VHSFilenamesToPathNode" + ], + { + "title_aux": "ComfyUI-Pronodes" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Upscaler-Tensorrt": [ + [ + "UpscalerTensorrt" + ], + { + "title_aux": "ComfyUI Upscaler TensorRT" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Vsgan": [ + [ + "DepthAnythingTrtNode", + "TTSCapcutNode", + "UpscaleVideoTrtNode" + ], + { + "title_aux": "ComfyUI-Vsgan" + } + ], + "https://github.com/yuvraj108c/ComfyUI-Whisper": [ + [ + "Add Subtitles To Background", + "Add Subtitles To Frames", + "Apply Whisper", + "Resize Cropped Subtitles" + ], + { + "title_aux": "ComfyUI Whisper" + } + ], + "https://github.com/yuvraj108c/ComfyUI-YoloNasPose-Tensorrt": [ + [ + "YoloNasPoseTensorrt" + ], + { + "title_aux": "ComfyUI YoloNasPose Tensorrt" + } + ], + "https://github.com/za-wa-n-go/ComfyUI_Zwng_Nodes": [ + [ + "ZwngLoadImagePathOrURL", + "ZwngPreviewImageAndMask", + "ZwngSimpleGoogleTranslater", + "ZwngSimplePhotoshopConnector" + ], + { + "title_aux": "ComfyUI_Zwng_Nodes" + } + ], + "https://github.com/zcfrank1st/Comfyui-Toolbox": [ + [ + "PreviewJson", + "PreviewVideo", + "SaveJson", + "TestJsonPreview" + ], + { + "title_aux": "Comfyui-Toolbox" + } + ], + "https://github.com/zcfrank1st/Comfyui-Yolov8": [ + [ + "Yolov8Detection", + "Yolov8Segmentation" + ], + { + "title_aux": "ComfyUI Yolov8" + } + ], + "https://github.com/zcfrank1st/comfyui_visual_anagrams": [ + [ + "VisualAnagramsAnimate", + "VisualAnagramsSample" + ], + { + "title_aux": "comfyui_visual_anagram" + } + ], + "https://github.com/zer0TF/cute-comfy": [ + [ + "Cute.Placeholder" + ], + { + "title_aux": "Cute Comfy" + } + ], + "https://github.com/zeroxoxo/ComfyUI-Fast-Style-Transfer": [ + [ + "FastStyleTransfer", + "TrainFastStyleTransfer" + ], + { + "title_aux": "ComfyUI-Fast-Style-Transfer" + } + ], + "https://github.com/zfkun/ComfyUI_zfkun": [ + [ + "ZFLoadImagePath", + "ZFPreviewText", + "ZFPreviewTextMultiline", + "ZFShareScreen", + "ZFTextTranslation" + ], + { + "title_aux": "ComfyUI_zfkun" + } + ], + "https://github.com/zhangp365/ComfyUI-utils-nodes": [ + [ + "CheckpointLoaderSimpleWithSwitch", + "ColorCorrectOfUtils", + "ConcatTextOfUtils", + "ImageBatchOneOrMore", + "ImageCompositeMaskedWithSwitch", + "ImageConcanateOfUtils", + "IntAndIntAddOffsetLiteral", + "IntMultipleAddLiteral", + "LoadImageMaskWithSwitch", + "LoadImageMaskWithoutListDir", + "LoadImageWithSwitch", + "LoadImageWithoutListDir", + "MaskAutoSelector", + "MaskFastGrow", + "ModifyTextGender", + "SplitMask" + ], + { + "title_aux": "zhangp365/Some Utils for ComfyUI" + } + ], + "https://github.com/zhongpei/ComfyUI-InstructIR": [ + [ + "InstructIRProcess", + "LoadInstructIRModel" + ], + { + "title_aux": "ComfyUI for InstructIR" + } + ], + "https://github.com/zhongpei/Comfyui_image2prompt": [ + [ + "CLIP AdvancedTextEncode|fofo", + "CLIP PromptConditioning|fofo", + "Image2Text", + "Image2TextWithTags", + "ImageBatchToList|fofo", + "ImageRewardScore|fofo", + "LoadImage2TextModel", + "LoadImageRewardScoreModel|fofo", + "LoadT5Model|fofo", + "LoadText2PromptModel", + "ShowText|fofo", + "T5QuantizationConfig|fofo", + "T5Text2Prompt|fofo", + "Text2GPTPrompt", + "Text2Prompt", + "TextBox|fofo", + "Translate2Chinese|fofo" + ], + { + "title_aux": "Comfyui_image2prompt" + } + ], + "https://github.com/zhuanqianfish/ComfyUI-EasyNode": [ + [ + "EasyCaptureNode", + "EasyVideoOutputNode", + "SendImageWebSocket" + ], + { + "title_aux": "EasyCaptureNode for ComfyUI" + } + ], + "https://github.com/zhulu111/ComfyUI_Bxb": [ + [ + "sdBxb", + "sdBxb_textInput" + ], + { + "title_aux": "ComfyUI_Bxb" + } + ], + "https://github.com/zohac/ComfyUI_ZC_DrawShape": [ + [ + "ZcDrawShape" + ], + { + "author": "Zohac", + "description": "nodes for artists, designers and animators.", + "nickname": "Zc DrawShape", + "title": "Zc DrawShape", + "title_aux": "ComfyUI_ZC_DrawShape" + } + ], + "https://github.com/zombieyang/sd-ppp": [ + [ + "Get Image From Photoshop Layer", + "Image Times Opacity", + "Mask Times Opacity", + "Send Images To Photoshop" + ], + { + "title_aux": "SD-PPP" + } + ], + "https://raw.githubusercontent.com/throttlekitty/SDXLCustomAspectRatio/main/SDXLAspectRatio.py": [ + [ + "SDXLAspectRatio" + ], + { + "title_aux": "SDXLCustomAspectRatio" + } + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/new/model-list.json b/custom_nodes/ComfyUI-Manager/node_db/new/model-list.json new file mode 100644 index 000000000..dee66b3c6 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/new/model-list.json @@ -0,0 +1,710 @@ +{ + "models": [ + { + "name": "xinsir/ControlNet++: All-in-one ControlNet", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-union-sdxl-1.0", + "description": "All-in-one ControlNet for image generations and editing!", + "reference": "https://huggingface.co/xinsir/controlnet-union-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-union-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + + { + "name": "InstantX/SD3-Controlnet-Canny", + "type": "controlnet", + "base": "SD3", + "save_path": "controlnet/SD3/InstantX-Controlnet-Canny", + "description": "Controlnet SD3 Canny model.", + "reference": "https://huggingface.co/InstantX/SD3-Controlnet-Canny", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/InstantX/SD3-Controlnet-Canny/resolve/main/diffusion_pytorch_model.safetensors", + "size": "1.19GB" + }, + { + "name": "InstantX/SD3-Controlnet-Pose", + "type": "controlnet", + "base": "SD3", + "save_path": "controlnet/SD3/InstantX-Controlnet-Pose", + "description": "Controlnet SD3 Pose model.", + "reference": "https://huggingface.co/InstantX/SD3-Controlnet-Pose", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/InstantX/SD3-Controlnet-Pose/resolve/main/diffusion_pytorch_model.safetensors", + "size": "1.19GB" + }, + { + "name": "InstantX/SD3-Controlnet-Tile", + "type": "controlnet", + "base": "SD3", + "save_path": "controlnet/SD3/InstantX-Controlnet-Tile", + "description": "Controlnet SD3 Tile model.", + "reference": "https://huggingface.co/InstantX/SD3-Controlnet-Tile", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/InstantX/SD3-Controlnet-Tile/resolve/main/diffusion_pytorch_model.safetensors", + "size": "1.19GB" + }, + + { + "name": "xinsir/ControlNet Depth SDXL, support zoe, midias", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-depth-sdxl-1.0", + "description": "Controlnet SDXL Depth model.", + "reference": "https://huggingface.co/xinsir/controlnet-depth-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-depth-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/ControlNet Tile SDXL", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-tile-sdxl-1.0", + "description": "Controlnet SDXL Tile model.", + "reference": "https://huggingface.co/xinsir/controlnet-tile-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-tile-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + + { + "name": "google-t5/t5-base", + "type": "clip", + "base": "t5-base", + "save_path": "clip/t5-base", + "description": "T5 Base: Text-To-Text Transfer Transformer. This model can be loaded via CLIPLoader for Stable Audio workflow.", + "reference": "https://huggingface.co/google-t5/t5-base", + "filename": "model.safetensors", + "url": "https://huggingface.co/google-t5/t5-base/resolve/main/model.safetensors", + "size": "892MB" + }, + + { + "name": "PixArt-Sigma-XL-2-1024-MS.pth", + "type": "checkpoint", + "base": "pixart-sigma", + "save_path": "checkpoints/PixArt-Sigma", + "description": "PixArt-Sigma Checkpoint model", + "reference": "https://huggingface.co/PixArt-alpha/PixArt-Sigma/tree/main", + "filename": "PixArt-Sigma-XL-2-1024-MS.pth", + "url": "https://huggingface.co/PixArt-alpha/PixArt-Sigma/resolve/main/PixArt-Sigma-XL-2-1024-MS.pth", + "size": "2.47GB" + }, + { + "name": "TAESD3 Decoder", + "type": "TAESD", + "base": "SDXL", + "save_path": "vae_approx", + "description": "(SD3 Verison) To view the preview in high quality while running samples in ComfyUI, you will need this model.", + "reference": "https://github.com/madebyollin/taesd", + "filename": "taesd3_decoder.pth", + "url": "https://github.com/madebyollin/taesd/raw/main/taesd3_decoder.pth", + "size": "4.94MB" + }, + { + "name": "TAESD3 Encoder", + "type": "TAESD", + "base": "SDXL", + "save_path": "vae_approx", + "description": "(SD3 Verison) To view the preview in high quality while running samples in ComfyUI, you will need this model.", + "reference": "https://github.com/madebyollin/taesd", + "filename": "taesd3_encoder.pth", + "url": "https://github.com/madebyollin/taesd/raw/main/taesd3_encoder.pth", + "size": "4.94MB" + }, + + { + "name": "TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic v2 (rank256)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "Controlnet SDXL Tile model realistic version.", + "reference": "https://huggingface.co/TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic", + "filename": "TTPLANET_Controlnet_Tile_realistic_v2_rank256.safetensors", + "url": "https://huggingface.co/TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic/resolve/main/TTPLANET_Controlnet_Tile_realistic_v2_rank256.safetensors", + "size": "774.4MB" + }, + + { + "name": "kijai/DepthAnythingV2 (vitb/fp16)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vitb_fp16.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vitb_fp16.safetensors", + "size": "195.0MB" + }, + { + "name": "kijai/DepthAnythingV2 (vitb/fp32)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vitb_fp32.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vitb_fp32.safetensors", + "size": "389.9MB" + }, + { + "name": "kijai/DepthAnythingV2 (vitl/fp16)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "[671MB] DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vitl_fp16.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vitl_fp16.safetensors", + "size": "670.7MB" + }, + { + "name": "kijai/DepthAnythingV2 (vitl/fp32)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "[195MB] DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vitl_fp32.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vitl_fp32.safetensors", + "size": "1.34GB" + }, + { + "name": "kijai/DepthAnythingV2 (vits/fp16)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "[49.6MB] DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vits_fp16.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vits_fp16.safetensors", + "size": "49.6MB" + }, + { + "name": "kijai/DepthAnythingV2 (vitb/fp32)", + "type": "depthanything", + "base": "depthanything", + "save_path": "depthanything", + "description": "[99.2MB] DepthAnythingV2 model", + "reference": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/tree/main", + "filename": "depth_anything_v2_vits_fp32.safetensors", + "url": "https://huggingface.co/Kijai/DepthAnythingV2-safetensors/resolve/main/depth_anything_v2_vits_fp32.safetensors", + "size": "99.2MB" + }, + + { + "name": "CN-anytest_v4-marged.safetensors", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[2.5GB] AnyTest Controlnet. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged.safetensors", + "size": "2.50GB" + }, + { + "name": "CN-anytest_v4-marged_am_dim256.safetensors (dim256/Animagine)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[774MB] AnyTest Controlnet Lora (dim256) for Animagine. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged_am_dim256.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged_am_dim256.safetensors", + "size": "774.4MB" + }, + { + "name": "CN-anytest_v4-marged_am_dim128.safetensors (dim128/Animagine)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[396MB] AnyTest Controlnet Lora (dim128) for Animagine. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged_am_dim128.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged_am_dim128.safetensors", + "size": "395.7MB" + }, + { + "name": "CN-anytest_v4-marged_pn_dim256.safetensors (dim256/Pony)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[774MB] AnyTest Controlnet Lora (dim256) for Pony. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged_pn_dim256.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged_pn_dim256.safetensors", + "size": "774.4MB" + }, + { + "name": "CN-anytest_v4-marged_pn_dim128.safetensors (dim128/Pony)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[396MB] AnyTest Controlnet Lora (dim128) for Pony. A model for style transfer.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v4-marged_pn_dim128.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v4-marged_pn_dim128.safetensors", + "size": "395.7MB" + }, + { + "name": "CN-anytest_v3-50000_fp16.safetensors (fp16)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[2.5GB] AnyTest Controlnet. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_fp16.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_fp16.safetensors", + "size": "2.50GB" + }, + { + "name": "CN-anytest_v3-50000_am_dim256.safetensors (dim256/Animagine)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[774MB] AnyTest Controlnet Lora (dim256) for Animagine. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_am_dim256.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_am_dim256.safetensors", + "size": "774.4MB" + }, + { + "name": "CN-anytest_v3-50000_am_dim128.safetensors (dim128/Animagine)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[396MB] AnyTest Controlnet Lora (dim128) for Animagine. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_am_dim128.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_am_dim128.safetensors", + "size": "395.7MB" + }, + { + "name": "CN-anytest_v3-50000_pn_dim256.safetensors (dim256/Pony)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[774MB] AnyTest Controlnet Lora (dim256) for Pony. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_pn_dim256.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_pn_dim256.safetensors", + "size": "774.4MB" + }, + { + "name": "CN-anytest_v3-50000_pn_dim128.safetensors (dim128/Pony)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[396MB] AnyTest Controlnet Lora (dim128) for Pony. A strict control model.", + "reference": "https://huggingface.co/2vXpSwA7/iroiro-lora/tree/main", + "filename": "CN-anytest_v3-50000_pn_dim128.safetensors", + "url": "https://huggingface.co/2vXpSwA7/iroiro-lora/resolve/main/test_controlnet2/CN-anytest_v3-50000_pn_dim128.safetensors", + "size": "395.7MB" + }, + + { + "name": "Kijai/ToonCrafter model checkpoint (interpolation fp16)", + "type": "checkpoint", + "base": "ToonCrafter", + "save_path": "checkpoints/ToonCrafter", + "description": "[5.25GB] ToonCrafter checkpoint model for ComfyUI-DynamiCrafterWrapper", + "reference": "https://huggingface.co/Kijai/DynamiCrafter_pruned", + "filename": "tooncrafter_512_interp-fp16.safetensors", + "url": "https://huggingface.co/Kijai/DynamiCrafter_pruned/resolve/main/tooncrafter_512_interp-fp16.safetensors", + "size": "5.25GB" + }, + + { + "name": "xinsir/Controlnet-Scribble-Sdxl-1.0", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-scribble-sdxl-1.0", + "description": "[2.5GB] Controlnet SDXL Scribble model.", + "reference": "https://huggingface.co/xinsir/controlnet-scribble-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-scribble-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/Controlnet-Canny-Sdxl-1.0 (V2)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-canny-sdxl-1.0", + "description": "[2.5GB] Controlnet SDXL Canny model.", + "reference": "https://huggingface.co/xinsir/controlnet-canny-sdxl-1.0", + "filename": "diffusion_pytorch_model_V2.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-canny-sdxl-1.0/resolve/main/diffusion_pytorch_model_V2.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/Controlnet-Openpose-Sdxl-1.0", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-openpose-sdxl-1.0", + "description": "[2.5GB] Controlnet SDXL Openpose model.", + "reference": "https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/Controlnet-Openpose-Sdxl-1.0 (Ver. twins)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-openpose-sdxl-1.0", + "description": "[2.5GB] Controlnet SDXL Openpose model. (Ver. twins)", + "reference": "https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0", + "filename": "diffusion_pytorch_model_twins.safetensors", + "url": "https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0/resolve/main/diffusion_pytorch_model_twins.safetensors", + "size": "2.50GB" + }, + { + "name": "xinsir/Controlnet-Scribble-Sdxl-1.0-Anime", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/controlnet-scribble-sdxl-1.0-anime", + "description": "[2.5GB] Controlnet SDXL Scribble model. (Ver. anime)", + "reference": "https://huggingface.co/xinsir/anime-painter", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/xinsir/anime-painter/resolve/main/diffusion_pytorch_model.safetensors", + "size": "2.50GB" + }, + + { + "name": "Doubiiu/ToonCrafter model checkpoint", + "type": "checkpoint", + "base": "ToonCrafter", + "save_path": "custom_nodes/ComfyUI-ToonCrafter/ToonCrafter/checkpoints/tooncrafter_512_interp_v1", + "description": "[10.5GB] ToonCrafter checkpoint model for ComfyUI-ToonCrafter", + "reference": "https://huggingface.co/Doubiiu/ToonCrafter/tree/main", + "filename": "model.ckpt", + "url": "https://huggingface.co/Doubiiu/ToonCrafter/resolve/main/model.ckpt", + "size": "10.5GB" + }, + + { + "name": "ViperYX/RGT_x2.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT", + "description": "[180MB] RGT x2 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_x2.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT/RGT_x2.pth", + "size": "179.8MB" + }, + { + "name": "ViperYX/RGT_x3.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT", + "description": "[180MB] RGT x3 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_x3.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT/RGT_x3.pth", + "size": "180.5MB" + }, + { + "name": "ViperYX/RGT_x4.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT", + "description": "[180MB] RGT_S x4 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_x4.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT/RGT_x4.pth", + "size": "180.4MB" + }, + { + "name": "ViperYX/RGT_S_x2.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT_S", + "description": "[135MB] RGT_S x2 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_S_x2.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT_S/RGT_S_x2.pth", + "size": "135.4MB" + }, + { + "name": "ViperYX/RGT_S_x3.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT_S", + "description": "[136MB] RGT_S x3 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_S_x3.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT_S/RGT_S_x3.pth", + "size": "136.1MB" + }, + { + "name": "ViperYX/RGT_S_x4.pth", + "type": "RGT", + "base": "RGT", + "save_path": "RGT/RGT_S", + "description": "[136MB] RGT_S x4 upscale model for ComfyUI-RGT", + "reference": "https://huggingface.co/ViperYX/RGT/tree/main", + "filename": "RGT_S_x4.pth", + "url": "https://huggingface.co/ViperYX/RGT/resolve/main/RGT_S/RGT_S_x4.pth", + "size": "136.0MB" + }, + + { + "name": "TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic v2 (fp16)", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL", + "description": "[2.5GB] Controlnet SDXL Tile model realistic version.", + "reference": "https://huggingface.co/TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic", + "filename": "TTPLANET_Controlnet_Tile_realistic_v2_fp16.safetensors", + "url": "https://huggingface.co/TTPlanet/TTPLanet_SDXL_Controlnet_Tile_Realistic/resolve/main/TTPLANET_Controlnet_Tile_realistic_v2_fp16.safetensors", + "size": "2.50GB" + }, + + { + "name": "TencentARC/CustomNet", + "type": "CustomNet", + "base": "CustomNet", + "save_path": "custom_nodes/ComfyUI_CustomNet/pretrain", + "description": "CustomNet pretrained model for ComfyUI_CustomNet", + "reference": "https://huggingface.co/TencentARC/CustomNet/tree/main", + "filename": "customnet_v1.pt", + "url": "https://huggingface.co/TencentARC/CustomNet/resolve/main/customnet_v1.pt", + "size": "5.71GB" + }, + + { + "name": "ID-Animator/animator.ckpt", + "type": "ID-Animator", + "base": "SD1.5", + "save_path": "custom_nodes/ComfyUI_ID_Animator/models", + "description": "ID-Animator checkpoint", + "reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator", + "filename": "animator.ckpt", + "url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/animator.ckpt", + "size": "247.3MB" + }, + { + "name": "ID-Animator/mm_sd_v15_v2.ckpt", + "type": "ID-Animator", + "base": "SD1.5", + "save_path": "custom_nodes/ComfyUI_ID_Animator/models/animatediff_models", + "description": "AnimateDiff checkpoint for ID-Animator", + "reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator", + "filename": "mm_sd_v15_v2.ckpt", + "url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/mm_sd_v15_v2.ckpt", + "size": "1.82GB" + }, + { + "name": "ID-Animator/image_encoder", + "type": "ID-Animator", + "base": "SD1.5", + "save_path": "custom_nodes/ComfyUI_ID_Animator/models/image_encoder", + "description": "CLIP Image encoder for ID-Animator", + "reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator", + "filename": "model.safetensors", + "url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/image_encoder/model.safetensors", + "size": "2.53GB" + }, + + { + "name": "IC-Light/fc", + "type": "IC-Light", + "base": "SD1.5", + "save_path": "unet/IC-Light", + "description": "The default relighting model, conditioned on text and foreground", + "reference": "https://huggingface.co/lllyasviel/ic-light", + "filename": "iclight_sd15_fc.safetensors", + "url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fc.safetensors", + "size": "1.72GB" + }, + { + "name": "IC-Light/fbc", + "type": "IC-Light", + "base": "SD1.5", + "save_path": "unet/IC-Light", + "description": "Relighting model conditioned with text, foreground, and background", + "reference": "https://huggingface.co/lllyasviel/ic-light", + "filename": "iclight_sd15_fbc.safetensors", + "url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fbc.safetensors", + "size": "1.72GB" + }, + { + "name": "IC-Light/fcon", + "type": "IC-Light", + "base": "SD1.5", + "save_path": "unet/IC-Light", + "description": "Same as iclight_sd15_fc.safetensors, but trained with offset noise", + "reference": "https://huggingface.co/lllyasviel/ic-light", + "filename": "iclight_sd15_fcon.safetensors", + "url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fcon.safetensors", + "size": "1.72GB" + }, + + { + "name": "MonsterMMORPG/insightface (for InstantID)", + "type": "insightface", + "base": "SDXL", + "save_path": "insightface/models", + "description": "MonsterMMORPG insightface model for cubiq/InstantID", + "reference": "https://huggingface.co/MonsterMMORPG/tools/tree/main", + "filename": "antelopev2.zip", + "url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/antelopev2.zip", + "size": "360.7MB" + }, + { + "name": "InstantID/ip-adapter", + "type": "instantid", + "base": "SDXL", + "save_path": "instantid/SDXL", + "description": "ip-adapter model for cubiq/InstantID", + "reference": "https://huggingface.co/InstantX/InstantID", + "filename": "ip-adapter.bin", + "url": "https://huggingface.co/InstantX/InstantID/resolve/main/ip-adapter.bin" + }, + { + "name": "InstantID/ControlNet", + "type": "controlnet", + "base": "SDXL", + "save_path": "controlnet/SDXL/instantid", + "description": "instantid controlnet model for cubiq/InstantID", + "reference": "https://huggingface.co/InstantX/InstantID", + "filename": "diffusion_pytorch_model.safetensors", + "url": "https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors" + }, + { + "name": "ip_plus_composition_sd15.safetensors", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/ostris/ip-composition-adapter", + "filename": "ip_plus_composition_sd15.safetensors", + "url": "https://huggingface.co/ostris/ip-composition-adapter/resolve/main/ip_plus_composition_sd15.safetensors" + }, + { + "name": "ip_plus_composition_sdxl.safetensors", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/ostris/ip-composition-adapter", + "filename": "ip_plus_composition_sdxl.safetensors", + "url": "https://huggingface.co/ostris/ip-composition-adapter/resolve/main/ip_plus_composition_sdxl.safetensors" + }, + { + "name": "ip-adapter-faceid-portrait-v11_sd15.bin", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Portrait V11 Model (SD1.5) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-portrait-v11_sd15.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait-v11_sd15.bin" + }, + { + "name": "ip-adapter-faceid-portrait_sdxl.bin", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Portrait Model (SDXL) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-portrait_sdxl.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sdxl.bin" + }, + { + "name": "ip-adapter-faceid-portrait_sdxl_unnorm.bin", + "type": "IP-Adapter", + "base": "SDXL", + "save_path": "ipadapter", + "description": "IP-Adapter-FaceID Portrait Model (SDXL/unnorm) [ipadapter]", + "reference": "https://huggingface.co/h94/IP-Adapter-FaceID", + "filename": "ip-adapter-faceid-portrait_sdxl_unnorm.bin", + "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sdxl_unnorm.bin" + }, + { + "name": "ip-adapter_sd15_light_v11.bin", + "type": "IP-Adapter", + "base": "SD1.5", + "save_path": "ipadapter", + "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", + "reference": "https://huggingface.co/h94/IP-Adapter", + "filename": "ip-adapter_sd15_light_v11.bin", + "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_light_v11.bin" + }, + + + { + "name": "Kijai/SUPIR-v0F_fp16.safetensors (pruned)", + "type": "checkpoints", + "base": "SUPIR", + "save_path": "checkpoints/SUPIR", + "description": "SUPIR checkpoint model", + "reference": "https://huggingface.co/Kijai/SUPIR_pruned/tree/main", + "filename": "SUPIR-v0F_fp16.safetensors", + "url": "https://huggingface.co/Kijai/SUPIR_pruned/resolve/main/SUPIR-v0F_fp16.safetensors" + }, + { + "name": "Kijai/SUPIR-v0Q_fp16.safetensors (pruned)", + "type": "checkpoints", + "base": "SUPIR", + "save_path": "checkpoints/SUPIR", + "description": "SUPIR checkpoint model", + "reference": "https://huggingface.co/Kijai/SUPIR_pruned/tree/main", + "filename": "SUPIR-v0Q_fp16.safetensors", + "url": "https://huggingface.co/Kijai/SUPIR_pruned/resolve/main/SUPIR-v0Q_fp16.safetensors" + }, + { + "name": "SUPIR-v0F.ckpt", + "type": "checkpoints", + "base": "SUPIR", + "save_path": "checkpoints/SUPIR", + "description": "SUPIR checkpoint model", + "reference": "https://huggingface.co/camenduru/SUPIR/tree/main", + "filename": "SUPIR-v0F.ckpt", + "url": "https://huggingface.co/camenduru/SUPIR/resolve/main/SUPIR-v0F.ckpt" + }, + { + "name": "SUPIR-v0Q.ckpt", + "type": "checkpoints", + "base": "SUPIR", + "save_path": "checkpoints/SUPIR", + "description": "SUPIR checkpoint model", + "reference": "https://huggingface.co/camenduru/SUPIR/tree/main", + "filename": "SUPIR-v0Q.ckpt", + "url": "https://huggingface.co/camenduru/SUPIR/resolve/main/SUPIR-v0Q.ckpt" + },{ + "name": "Depth-FM-v1 fp16 safetensors", + "type": "checkpoints", + "base": "Depth-FM", + "save_path": "checkpoints/depthfm", + "description": "Depth-FM monocular depth estimation model", + "reference": "https://huggingface.co/Kijai/depth-fm-pruned", + "filename": "depthfm-v1_fp16.safetensors", + "url": "https://huggingface.co/Kijai/depth-fm-pruned/resolve/main/depthfm-v1_fp16.safetensors" + }, + { + "name": "Depth-FM-v1 fp32 safetensors", + "type": "checkpoints", + "base": "Depth-FM", + "save_path": "checkpoints/depthfm", + "description": "Depth-FM monocular depth estimation model", + "reference": "https://huggingface.co/Kijai/depth-fm-pruned", + "filename": "depthfm-v1_fp32.safetensors", + "url": "https://huggingface.co/Kijai/depth-fm-pruned/resolve/main/depthfm-v1_fp32.safetensors" + }, + { + "name": "monster-labs - Controlnet QR Code Monster v1 For SDXL", + "type": "controlnet", + "base": "SDXL", + "save_path": "default", + "description": "monster-labs - Controlnet QR Code Monster v1 For SDXL", + "reference": "https://huggingface.co/monster-labs/control_v1p_sdxl_qrcode_monster", + "filename": "control_v1p_sdxl_qrcode_monster.safetensors", + "url": "https://huggingface.co/monster-labs/control_v1p_sdxl_qrcode_monster/resolve/main/diffusion_pytorch_model.safetensors" + } + ] +} diff --git a/custom_nodes/ComfyUI-Manager/node_db/tutorial/custom-node-list.json b/custom_nodes/ComfyUI-Manager/node_db/tutorial/custom-node-list.json new file mode 100644 index 000000000..c02d05d8e --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/tutorial/custom-node-list.json @@ -0,0 +1,244 @@ +{ + "custom_nodes": [ + { + "author": "Suzie1", + "title": "Guide To Making Custom Nodes in ComfyUI", + "reference": "https://github.com/Suzie1/ComfyUI_Guide_To_Making_Custom_Nodes", + "files": [ + "https://github.com/Suzie1/ComfyUI_Guide_To_Making_Custom_Nodes" + ], + "install_type": "git-clone", + "description": "There is a small node pack attached to this guide. This includes the init file and 3 nodes associated with the tutorials." + }, + { + "author": "bamboodia", + "title": "BAM Nodes", + "reference": "https://github.com/bamboodia/BAM_Nodes", + "files": [ + "https://github.com/bamboodia/BAM_Nodes" + ], + "install_type": "git-clone", + "description": "A collection of comfyui nodes that I have made for nothing more than educational purposes." + }, + { + "author": "BadCafeCode", + "title": "execution-inversion-demo-comfyui", + "reference": "https://github.com/BadCafeCode/execution-inversion-demo-comfyui", + "files": [ + "https://github.com/BadCafeCode/execution-inversion-demo-comfyui" + ], + "install_type": "git-clone", + "description": "These are demo nodes for [a/PR2666](https://github.com/comfyanonymous/ComfyUI/pull/2666)" + }, + { + "author": "ecjojo", + "title": "ecjojo_example_nodes", + "reference": "https://github.com/ecjojo/ecjojo-example-nodes", + "files": [ + "https://github.com/ecjojo/ecjojo-example-nodes" + ], + "install_type": "git-clone", + "description": "Welcome to ecjojo_example_nodes! This example is specifically designed for beginners who want to learn how to write a simple custom node.\nFeel free to modify this example and make it your own. Experiment with different features and functionalities to enhance your understanding of ComfyUI custom nodes. Don't be afraid to explore and customize the code to suit your needs.\nBy diving into this example and making it your own, you'll gain valuable hands-on experience in creating custom nodes in ComfyUI. Enjoy the process of learning and have fun with your custom node development journey!" + }, + { + "author": "dynamixar", + "title": "Atluris", + "reference": "https://github.com/dynamixar/Atluris", + "files": [ + "https://github.com/dynamixar/Atluris" + ], + "install_type": "git-clone", + "description": "Nodes:Random Line" + }, + { + "author": "et118", + "title": "ComfyUI-ElGogh-Nodes", + "reference": "https://github.com/et118/ComfyUI-ElGogh-Nodes", + "files": [ + "https://github.com/et118/ComfyUI-ElGogh-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:ElGogh Positive Prompt, ElGogh NEGATIVE Prompt, ElGogh Empty Latent Image, ElGogh Checkpoint Loader Simple" + }, + { + "author": "LarryJane491", + "title": "Custom-Node-Base", + "reference": "https://github.com/LarryJane491/Custom-Node-Base", + "files": [ + "https://github.com/LarryJane491/Custom-Node-Base" + ], + "install_type": "git-clone", + "description": "This project is an `empty` custom node that is already in its own folder. It serves as a base to build any custom node. Whenever you want to create a custom node, you can download that, put it in custom_nodes, then you just have to change the names and fill it with code!" + }, + { + "author": "foxtrot-roger", + "title": "comfyui-custom-nodes", + "reference": "https://github.com/foxtrot-roger/comfyui-custom-nodes", + "files": [ + "https://github.com/foxtrot-roger/comfyui-custom-nodes" + ], + "install_type": "git-clone", + "description": "Tutorial nodes" + }, + { + "author": "wailovet", + "title": "ComfyUI-WW", + "reference": "https://github.com/wailovet/ComfyUI-WW", + "files": [ + "https://github.com/wailovet/ComfyUI-WW" + ], + "install_type": "git-clone", + "description": "Nodes:WW_ImageResize" + }, + { + "author": "bmz55", + "title": "bmz nodes", + "reference": "https://github.com/bmz55/comfyui-bmz-nodes", + "files": [ + "https://github.com/bmz55/comfyui-bmz-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Load Images From Dir With Name (Inspire - BMZ), Count Images In Dir (BMZ), Get Level Text (BMZ), Get Level Float (BMZ)" + }, + { + "author": "azure-dragon-ai", + "title": "ComfyUI-HPSv2-Nodes", + "reference": "https://github.com/azure-dragon-ai/ComfyUI-HPSv2-Nodes", + "files": [ + "https://github.com/azure-dragon-ai/ComfyUI-HPSv2-Nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Loader, Image Processor, Text Processor, ImageScore" + }, + { + "author": "kappa54m", + "title": "ComfyUI-HPSv2-Nodes", + "reference": "https://github.com/kappa54m/ComfyUI_Usability", + "files": [ + "https://github.com/kappa54m/ComfyUI_Usability" + ], + "install_type": "git-clone", + "description": "Nodes:Load Image Dedup" + }, + { + "author": "IvanRybakov", + "title": "comfyui-node-int-to-string-convertor", + "reference": "https://github.com/IvanRybakov/comfyui-node-int-to-string-convertor", + "files": [ + "https://github.com/IvanRybakov/comfyui-node-int-to-string-convertor" + ], + "install_type": "git-clone", + "description": "Nodes:Int To String Convertor" + }, + { + "author": "yowipr", + "title": "ComfyUI-Manual", + "reference": "https://github.com/yowipr/ComfyUI-Manual", + "files": [ + "https://github.com/yowipr/ComfyUI-Manual" + ], + "install_type": "git-clone", + "description": "Nodes:M_Layer, M_Output" + }, + { + "author": "andrewharp", + "title": "ComfyUI Function Annotator", + "reference": "https://github.com/andrewharp/ComfyUI-Annotations", + "files": [ + "https://github.com/andrewharp/ComfyUI-Annotations" + ], + "install_type": "git-clone", + "description": "This module provides an annotation @ComfyFunc to streamline adding custom node types in ComfyUI. It processes your function's signature to create a wrapped function and custom node definition required for ComfyUI, eliminating all the boilerplate code. In most cases you can just add a @ComfyFunc(\"category\") annotation to your existing function." + }, + { + "author": "MokkaBoss1", + "title": "Woman_in_a_dress", + "reference": "https://github.com/MokkaBoss1/Woman_in_a_dress", + "files": [ + "https://github.com/MokkaBoss1/Woman_in_a_dress/raw/main/Woman_In_A_Dress.py" + ], + "install_type": "git-clone", + "description": "Nodes:Woman_in_a_dress" + }, + { + "author": "shinich39", + "title": "comfyui-concat-text-39", + "reference": "https://github.com/shinich39/comfyui-concat-text-39", + "files": [ + "https://github.com/shinich39/comfyui-concat-text-39" + ], + "install_type": "git-clone", + "description": "Nodes:Concatenate multiple text nodes." + }, + { + "author": "nilor-corp", + "title": "nilor-nodes", + "reference": "https://github.com/nilor-corp/nilor-nodes", + "files": [ + "https://github.com/nilor-corp/nilor-nodes" + ], + "install_type": "git-clone", + "description": "Nodes:Nilor Floats, Nilor Int To List Of Bools, Nilor Bool From List Of Bools, Nilor Int From List Of Ints, Nilor List of Ints, Nilor Count Images In Directory" + }, + { + "author": "OuticNZ", + "title": "ComfyUI-Simple-Of-Complex", + "reference": "https://github.com/OuticNZ/ComfyUI-Simple-Of-Complex", + "files": [ + "https://github.com/OuticNZ/ComfyUI-Simple-Of-Complex" + ], + "install_type": "git-clone", + "description": "Keeping it simple for starting. Single branch for now and will add development branch later." + }, + { + "author": "jtong", + "title": "comfyui-jtong-workflow", + "reference": "https://github.com/jtong/comfyui-jtong-workflow", + "files": [ + "https://github.com/jtong/comfyui-jtong-workflow" + ], + "install_type": "git-clone", + "description": "Nodes:jtong.Highway, Example" + }, + { + "author": "thinkthinking", + "title": "ComfyUI-Ye", + "reference": "https://github.com/thinkthinking/ComfyUI-Ye", + "files": [ + "https://github.com/thinkthinking/ComfyUI-Ye" + ], + "install_type": "git-clone", + "description": "Nodes:Signature|Ye, CheckpointLoader|Ye, PrintHelloWorld|Ye." + }, + { + "author": "BoosterCore", + "title": "ComfyUI-BC-Experimental", + "reference": "https://github.com/BoosterCore/ComfyUI-BC-Experimental", + "files": [ + "https://github.com/BoosterCore/ComfyUI-BC-Experimental" + ], + "install_type": "git-clone", + "description": "Nodes:ClipTextEncodeBC, SaveAnyText, SimpleText" + }, + { + "author": "sonyeon-sj", + "title": "ComfyUI-easy_ImageSize_Selecter", + "reference": "https://github.com/sonyeon-sj/ComfyUI-easy_ImageSize_Selecter", + "files": [ + "https://github.com/sonyeon-sj/ComfyUI-easy_ImageSize_Selecter" + ], + "install_type": "git-clone", + "description": "Custom node for ComfyUI Select the image size from the preset and select Vertical and Horizontal to output Width and Height." + }, + { + "author": "boricuapab", + "title": "ComfyUI_BoricuapabWFNodePack", + "reference": "https://github.com/boricuapab/ComfyUI_BoricuapabWFNodePack", + "files": [ + "https://github.com/boricuapab/ComfyUI_BoricuapabWFNodePack" + ], + "install_type": "git-clone", + "description": "Learning how to make my own comfy ui custom nodes" + } + ] +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/tutorial/extension-node-map.json b/custom_nodes/ComfyUI-Manager/node_db/tutorial/extension-node-map.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/tutorial/extension-node-map.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/node_db/tutorial/model-list.json b/custom_nodes/ComfyUI-Manager/node_db/tutorial/model-list.json new file mode 100644 index 000000000..8e3e1dc48 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/tutorial/model-list.json @@ -0,0 +1,3 @@ +{ + "models": [] +} diff --git a/custom_nodes/ComfyUI-Manager/node_db/tutorial/scan.sh b/custom_nodes/ComfyUI-Manager/node_db/tutorial/scan.sh new file mode 100644 index 000000000..5d8d8c48b --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/node_db/tutorial/scan.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source ../../../../venv/bin/activate +rm .tmp/*.py > /dev/null +python ../../scanner.py diff --git a/custom_nodes/ComfyUI-Manager/notebooks/comfyui_colab_with_manager.ipynb b/custom_nodes/ComfyUI-Manager/notebooks/comfyui_colab_with_manager.ipynb new file mode 100644 index 000000000..d8b863889 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/notebooks/comfyui_colab_with_manager.ipynb @@ -0,0 +1,372 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "aaaaaaaaaa" + }, + "source": [ + "Git clone the repo and install the requirements. (ignore the pip errors about protobuf)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "bbbbbbbbbb" + }, + "outputs": [], + "source": [ + "# #@title Environment Setup\n", + "\n", + "from pathlib import Path\n", + "\n", + "OPTIONS = {}\n", + "\n", + "USE_GOOGLE_DRIVE = True #@param {type:\"boolean\"}\n", + "UPDATE_COMFY_UI = True #@param {type:\"boolean\"}\n", + "USE_COMFYUI_MANAGER = True #@param {type:\"boolean\"}\n", + "INSTALL_CUSTOM_NODES_DEPENDENCIES = True #@param {type:\"boolean\"}\n", + "OPTIONS['USE_GOOGLE_DRIVE'] = USE_GOOGLE_DRIVE\n", + "OPTIONS['UPDATE_COMFY_UI'] = UPDATE_COMFY_UI\n", + "OPTIONS['USE_COMFYUI_MANAGER'] = USE_COMFYUI_MANAGER\n", + "OPTIONS['INSTALL_CUSTOM_NODES_DEPENDENCIES'] = INSTALL_CUSTOM_NODES_DEPENDENCIES\n", + "\n", + "current_dir = !pwd\n", + "WORKSPACE = f\"{current_dir[0]}/ComfyUI\"\n", + "\n", + "if OPTIONS['USE_GOOGLE_DRIVE']:\n", + " !echo \"Mounting Google Drive...\"\n", + " %cd /\n", + "\n", + " from google.colab import drive\n", + " drive.mount('/content/drive')\n", + "\n", + " WORKSPACE = \"/content/drive/MyDrive/ComfyUI\"\n", + " %cd /content/drive/MyDrive\n", + "\n", + "![ ! -d $WORKSPACE ] && echo -= Initial setup ComfyUI =- && git clone https://github.com/comfyanonymous/ComfyUI\n", + "%cd $WORKSPACE\n", + "\n", + "if OPTIONS['UPDATE_COMFY_UI']:\n", + " !echo -= Updating ComfyUI =-\n", + "\n", + " # Correction of the issue of permissions being deleted on Google Drive.\n", + " ![ -f \".ci/nightly/update_windows/update_comfyui_and_python_dependencies.bat\" ] && chmod 755 .ci/nightly/update_windows/update_comfyui_and_python_dependencies.bat\n", + " ![ -f \".ci/nightly/windows_base_files/run_nvidia_gpu.bat\" ] && chmod 755 .ci/nightly/windows_base_files/run_nvidia_gpu.bat\n", + " ![ -f \".ci/update_windows/update_comfyui_and_python_dependencies.bat\" ] && chmod 755 .ci/update_windows/update_comfyui_and_python_dependencies.bat\n", + " ![ -f \".ci/update_windows_cu118/update_comfyui_and_python_dependencies.bat\" ] && chmod 755 .ci/update_windows_cu118/update_comfyui_and_python_dependencies.bat\n", + " ![ -f \".ci/update_windows/update.py\" ] && chmod 755 .ci/update_windows/update.py\n", + " ![ -f \".ci/update_windows/update_comfyui.bat\" ] && chmod 755 .ci/update_windows/update_comfyui.bat\n", + " ![ -f \".ci/update_windows/README_VERY_IMPORTANT.txt\" ] && chmod 755 .ci/update_windows/README_VERY_IMPORTANT.txt\n", + " ![ -f \".ci/update_windows/run_cpu.bat\" ] && chmod 755 .ci/update_windows/run_cpu.bat\n", + " ![ -f \".ci/update_windows/run_nvidia_gpu.bat\" ] && chmod 755 .ci/update_windows/run_nvidia_gpu.bat\n", + "\n", + " !git pull\n", + "\n", + "!echo -= Install dependencies =-\n", + "!pip3 install accelerate\n", + "!pip3 install einops transformers>=4.25.1 safetensors>=0.3.0 aiohttp pyyaml Pillow scipy tqdm psutil\n", + "!pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121\n", + "!pip3 install torchsde\n", + "!pip3 install kornia>=0.7.1 spandrel\n", + "\n", + "if OPTIONS['USE_COMFYUI_MANAGER']:\n", + " %cd custom_nodes\n", + "\n", + " # Correction of the issue of permissions being deleted on Google Drive.\n", + " ![ -f \"ComfyUI-Manager/check.sh\" ] && chmod 755 ComfyUI-Manager/check.sh\n", + " ![ -f \"ComfyUI-Manager/scan.sh\" ] && chmod 755 ComfyUI-Manager/scan.sh\n", + " ![ -f \"ComfyUI-Manager/node_db/dev/scan.sh\" ] && chmod 755 ComfyUI-Manager/node_db/dev/scan.sh\n", + " ![ -f \"ComfyUI-Manager/scripts/install-comfyui-venv-linux.sh\" ] && chmod 755 ComfyUI-Manager/scripts/install-comfyui-venv-linux.sh\n", + " ![ -f \"ComfyUI-Manager/scripts/install-comfyui-venv-win.bat\" ] && chmod 755 ComfyUI-Manager/scripts/install-comfyui-venv-win.bat\n", + "\n", + " ![ ! -d ComfyUI-Manager ] && echo -= Initial setup ComfyUI-Manager =- && git clone https://github.com/ltdrdata/ComfyUI-Manager\n", + " %cd ComfyUI-Manager\n", + " !git pull\n", + "\n", + "%cd $WORKSPACE\n", + "\n", + "if OPTIONS['INSTALL_CUSTOM_NODES_DEPENDENCIES']:\n", + " !echo -= Install custom nodes dependencies =-\n", + " !pip install GitPython\n", + " !python custom_nodes/ComfyUI-Manager/cm-cli.py restore-dependencies\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "cccccccccc" + }, + "source": [ + "Download some models/checkpoints/vae or custom comfyui nodes (uncomment the commands for the ones you want)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "dddddddddd" + }, + "outputs": [], + "source": [ + "# Checkpoints\n", + "\n", + "### SDXL\n", + "### I recommend these workflow examples: https://comfyanonymous.github.io/ComfyUI_examples/sdxl/\n", + "\n", + "#!wget -c https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0.safetensors -P ./models/checkpoints/\n", + "#!wget -c https://huggingface.co/stabilityai/stable-diffusion-xl-refiner-1.0/resolve/main/sd_xl_refiner_1.0.safetensors -P ./models/checkpoints/\n", + "\n", + "# SDXL ReVision\n", + "#!wget -c https://huggingface.co/comfyanonymous/clip_vision_g/resolve/main/clip_vision_g.safetensors -P ./models/clip_vision/\n", + "\n", + "# SD1.5\n", + "!wget -c https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.ckpt -P ./models/checkpoints/\n", + "\n", + "# SD2\n", + "#!wget -c https://huggingface.co/stabilityai/stable-diffusion-2-1-base/resolve/main/v2-1_512-ema-pruned.safetensors -P ./models/checkpoints/\n", + "#!wget -c https://huggingface.co/stabilityai/stable-diffusion-2-1/resolve/main/v2-1_768-ema-pruned.safetensors -P ./models/checkpoints/\n", + "\n", + "# Some SD1.5 anime style\n", + "#!wget -c https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix2/AbyssOrangeMix2_hard.safetensors -P ./models/checkpoints/\n", + "#!wget -c https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix3/AOM3A1_orangemixs.safetensors -P ./models/checkpoints/\n", + "#!wget -c https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix3/AOM3A3_orangemixs.safetensors -P ./models/checkpoints/\n", + "#!wget -c https://huggingface.co/Linaqruf/anything-v3.0/resolve/main/anything-v3-fp16-pruned.safetensors -P ./models/checkpoints/\n", + "\n", + "# Waifu Diffusion 1.5 (anime style SD2.x 768-v)\n", + "#!wget -c https://huggingface.co/waifu-diffusion/wd-1-5-beta3/resolve/main/wd-illusion-fp16.safetensors -P ./models/checkpoints/\n", + "\n", + "\n", + "# unCLIP models\n", + "#!wget -c https://huggingface.co/comfyanonymous/illuminatiDiffusionV1_v11_unCLIP/resolve/main/illuminatiDiffusionV1_v11-unclip-h-fp16.safetensors -P ./models/checkpoints/\n", + "#!wget -c https://huggingface.co/comfyanonymous/wd-1.5-beta2_unCLIP/resolve/main/wd-1-5-beta2-aesthetic-unclip-h-fp16.safetensors -P ./models/checkpoints/\n", + "\n", + "\n", + "# VAE\n", + "!wget -c https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.safetensors -P ./models/vae/\n", + "#!wget -c https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt -P ./models/vae/\n", + "#!wget -c https://huggingface.co/hakurei/waifu-diffusion-v1-4/resolve/main/vae/kl-f8-anime2.ckpt -P ./models/vae/\n", + "\n", + "\n", + "# Loras\n", + "#!wget -c https://civitai.com/api/download/models/10350 -O ./models/loras/theovercomer8sContrastFix_sd21768.safetensors #theovercomer8sContrastFix SD2.x 768-v\n", + "#!wget -c https://civitai.com/api/download/models/10638 -O ./models/loras/theovercomer8sContrastFix_sd15.safetensors #theovercomer8sContrastFix SD1.x\n", + "#!wget -c https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_offset_example-lora_1.0.safetensors -P ./models/loras/ #SDXL offset noise lora\n", + "\n", + "\n", + "# T2I-Adapter\n", + "#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_depth_sd14v1.pth -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_seg_sd14v1.pth -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_sketch_sd14v1.pth -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_keypose_sd14v1.pth -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_openpose_sd14v1.pth -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_color_sd14v1.pth -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_canny_sd14v1.pth -P ./models/controlnet/\n", + "\n", + "# T2I Styles Model\n", + "#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_style_sd14v1.pth -P ./models/style_models/\n", + "\n", + "# CLIPVision model (needed for styles model)\n", + "#!wget -c https://huggingface.co/openai/clip-vit-large-patch14/resolve/main/pytorch_model.bin -O ./models/clip_vision/clip_vit14.bin\n", + "\n", + "\n", + "# ControlNet\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_ip2p_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_canny_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1p_sd15_depth_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_inpaint_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_lineart_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_mlsd_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_normalbae_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_openpose_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_scribble_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_seg_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_softedge_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15s2_lineart_anime_fp16.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11u_sd15_tile_fp16.safetensors -P ./models/controlnet/\n", + "\n", + "# ControlNet SDXL\n", + "#!wget -c https://huggingface.co/stabilityai/control-lora/resolve/main/control-LoRAs-rank256/control-lora-canny-rank256.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/stabilityai/control-lora/resolve/main/control-LoRAs-rank256/control-lora-depth-rank256.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/stabilityai/control-lora/resolve/main/control-LoRAs-rank256/control-lora-recolor-rank256.safetensors -P ./models/controlnet/\n", + "#!wget -c https://huggingface.co/stabilityai/control-lora/resolve/main/control-LoRAs-rank256/control-lora-sketch-rank256.safetensors -P ./models/controlnet/\n", + "\n", + "# Controlnet Preprocessor nodes by Fannovel16\n", + "#!cd custom_nodes && git clone https://github.com/Fannovel16/comfy_controlnet_preprocessors; cd comfy_controlnet_preprocessors && python install.py\n", + "\n", + "\n", + "# GLIGEN\n", + "#!wget -c https://huggingface.co/comfyanonymous/GLIGEN_pruned_safetensors/resolve/main/gligen_sd14_textbox_pruned_fp16.safetensors -P ./models/gligen/\n", + "\n", + "\n", + "# ESRGAN upscale model\n", + "#!wget -c https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P ./models/upscale_models/\n", + "#!wget -c https://huggingface.co/sberbank-ai/Real-ESRGAN/resolve/main/RealESRGAN_x2.pth -P ./models/upscale_models/\n", + "#!wget -c https://huggingface.co/sberbank-ai/Real-ESRGAN/resolve/main/RealESRGAN_x4.pth -P ./models/upscale_models/\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kkkkkkkkkkkkkkk" + }, + "source": [ + "### Run ComfyUI with cloudflared (Recommended Way)\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "jjjjjjjjjjjjjj" + }, + "outputs": [], + "source": [ + "!wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb\n", + "!dpkg -i cloudflared-linux-amd64.deb\n", + "\n", + "import subprocess\n", + "import threading\n", + "import time\n", + "import socket\n", + "import urllib.request\n", + "\n", + "def iframe_thread(port):\n", + " while True:\n", + " time.sleep(0.5)\n", + " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", + " result = sock.connect_ex(('127.0.0.1', port))\n", + " if result == 0:\n", + " break\n", + " sock.close()\n", + " print(\"\\nComfyUI finished loading, trying to launch cloudflared (if it gets stuck here cloudflared is having issues)\\n\")\n", + "\n", + " p = subprocess.Popen([\"cloudflared\", \"tunnel\", \"--url\", \"http://127.0.0.1:{}\".format(port)], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n", + " for line in p.stderr:\n", + " l = line.decode()\n", + " if \"trycloudflare.com \" in l:\n", + " print(\"This is the URL to access ComfyUI:\", l[l.find(\"http\"):], end='')\n", + " #print(l, end='')\n", + "\n", + "\n", + "threading.Thread(target=iframe_thread, daemon=True, args=(8188,)).start()\n", + "\n", + "!python main.py --dont-print-server" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kkkkkkkkkkkkkk" + }, + "source": [ + "### Run ComfyUI with localtunnel\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "jjjjjjjjjjjjj" + }, + "outputs": [], + "source": [ + "!npm install -g localtunnel\n", + "\n", + "import subprocess\n", + "import threading\n", + "import time\n", + "import socket\n", + "import urllib.request\n", + "\n", + "def iframe_thread(port):\n", + " while True:\n", + " time.sleep(0.5)\n", + " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", + " result = sock.connect_ex(('127.0.0.1', port))\n", + " if result == 0:\n", + " break\n", + " sock.close()\n", + " print(\"\\nComfyUI finished loading, trying to launch localtunnel (if it gets stuck here localtunnel is having issues)\\n\")\n", + "\n", + " print(\"The password/enpoint ip for localtunnel is:\", urllib.request.urlopen('https://ipv4.icanhazip.com').read().decode('utf8').strip(\"\\n\"))\n", + " p = subprocess.Popen([\"lt\", \"--port\", \"{}\".format(port)], stdout=subprocess.PIPE)\n", + " for line in p.stdout:\n", + " print(line.decode(), end='')\n", + "\n", + "\n", + "threading.Thread(target=iframe_thread, daemon=True, args=(8188,)).start()\n", + "\n", + "!python main.py --dont-print-server" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "gggggggggg" + }, + "source": [ + "### Run ComfyUI with colab iframe (use only in case the previous way with localtunnel doesn't work)\n", + "\n", + "You should see the ui appear in an iframe. If you get a 403 error, it's your firefox settings or an extension that's messing things up.\n", + "\n", + "If you want to open it in another window use the link.\n", + "\n", + "Note that some UI features like live image previews won't work because the colab iframe blocks websockets." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "hhhhhhhhhh" + }, + "outputs": [], + "source": [ + "import threading\n", + "import time\n", + "import socket\n", + "def iframe_thread(port):\n", + " while True:\n", + " time.sleep(0.5)\n", + " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", + " result = sock.connect_ex(('127.0.0.1', port))\n", + " if result == 0:\n", + " break\n", + " sock.close()\n", + " from google.colab import output\n", + " output.serve_kernel_port_as_iframe(port, height=1024)\n", + " print(\"to open it in a window you can open this link here:\")\n", + " output.serve_kernel_port_as_window(port)\n", + "\n", + "threading.Thread(target=iframe_thread, daemon=True, args=(8188,)).start()\n", + "\n", + "!python main.py --dont-print-server" + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "provenance": [] + }, + "gpuClass": "standard", + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/pip_overrides.json.template b/custom_nodes/ComfyUI-Manager/pip_overrides.json.template new file mode 100644 index 000000000..a6b1f2629 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/pip_overrides.json.template @@ -0,0 +1,21 @@ +{ + "imageio-ffmpeg": "imageio", + "imageio[ffmpeg]": "imageio", + "imageio_ffmpeg": "imageio", + "diffusers~=0.21.4": "diffusers", + "huggingface_hub": "huggingface-hub", + "numpy<1.24>=1.18": "numpy", + "numpy>=1.18.5, <1.25.0": "numpy", + "opencv-contrib-python": "opencv-contrib-python-headless", + "opencv-python": "opencv-contrib-python-headless", + "opencv-python-headless": "opencv-contrib-python-headless", + "opencv-python-headless[ffmpeg]<=4.7.0.72": "opencv-contrib-python-headless", + "opencv-python>=4.7.0.72": "opencv-contrib-python-headless", + "pandas<=1.5.1": "pandas", + "scikit-image==0.20.0": "scikit-image", + "scipy>=1.11.4": "scipy", + "segment_anything": "segment-anything", + "timm==0.6.5": "timm", + "timm>=0.4.12": "timm", + "transformers==4.26.1": "transformers" +} \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/prestartup_script.py b/custom_nodes/ComfyUI-Manager/prestartup_script.py new file mode 100644 index 000000000..163a9880c --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/prestartup_script.py @@ -0,0 +1,665 @@ +import datetime +import os +import subprocess +import sys +import atexit +import threading +import re +import locale +import platform +import json +import ast +import logging + +glob_path = os.path.join(os.path.dirname(__file__), "glob") +sys.path.append(glob_path) + +import security_check +from manager_util import * +import cm_global + +security_check.security_check() + +cm_global.pip_downgrade_blacklist = ['torch', 'torchsde', 'torchvision', 'transformers', 'safetensors', 'kornia'] + + +def skip_pip_spam(x): + return ('Requirement already satisfied:' in x) or ("DEPRECATION: Loading egg at" in x) + + +message_collapses = [skip_pip_spam] +import_failed_extensions = set() +cm_global.variables['cm.on_revision_detected_handler'] = [] +enable_file_logging = True + + +def register_message_collapse(f): + global message_collapses + message_collapses.append(f) + + +def is_import_failed_extension(name): + global import_failed_extensions + return name in import_failed_extensions + + +def check_file_logging(): + global enable_file_logging + try: + import configparser + config_path = os.path.join(os.path.dirname(__file__), "config.ini") + config = configparser.ConfigParser() + config.read(config_path) + default_conf = config['default'] + + if 'file_logging' in default_conf and default_conf['file_logging'].lower() == 'false': + enable_file_logging = False + except Exception: + pass + + +check_file_logging() + +comfy_path = os.environ.get('COMFYUI_PATH') +if comfy_path is None: + comfy_path = os.path.abspath(os.path.dirname(sys.modules['__main__'].__file__)) + +sys.__comfyui_manager_register_message_collapse = register_message_collapse +sys.__comfyui_manager_is_import_failed_extension = is_import_failed_extension +cm_global.register_api('cm.register_message_collapse', register_message_collapse) +cm_global.register_api('cm.is_import_failed_extension', is_import_failed_extension) + + +comfyui_manager_path = os.path.dirname(__file__) +custom_nodes_path = os.path.abspath(os.path.join(comfyui_manager_path, "..")) +startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts") +restore_snapshot_path = os.path.join(startup_script_path, "restore-snapshot.json") +git_script_path = os.path.join(comfyui_manager_path, "git_helper.py") +pip_overrides_path = os.path.join(comfyui_manager_path, "pip_overrides.json") + + +cm_global.pip_overrides = {} +if os.path.exists(pip_overrides_path): + with open(pip_overrides_path, 'r', encoding="UTF-8", errors="ignore") as json_file: + cm_global.pip_overrides = json.load(json_file) + + +def remap_pip_package(pkg): + if pkg in cm_global.pip_overrides: + res = cm_global.pip_overrides[pkg] + print(f"[ComfyUI-Manager] '{pkg}' is remapped to '{res}'") + return res + else: + return pkg + + +std_log_lock = threading.Lock() + + +class TerminalHook: + def __init__(self): + self.hooks = {} + + def add_hook(self, k, v): + self.hooks[k] = v + + def remove_hook(self, k): + if k in self.hooks: + del self.hooks[k] + + def write_stderr(self, msg): + for v in self.hooks.values(): + try: + v.write_stderr(msg) + except Exception: + pass + + def write_stdout(self, msg): + for v in self.hooks.values(): + try: + v.write_stdout(msg) + except Exception: + pass + + +terminal_hook = TerminalHook() +sys.__comfyui_manager_terminal_hook = terminal_hook + + +def handle_stream(stream, prefix): + stream.reconfigure(encoding=locale.getpreferredencoding(), errors='replace') + for msg in stream: + if prefix == '[!]' and ('it/s]' in msg or 's/it]' in msg) and ('%|' in msg or 'it [' in msg): + if msg.startswith('100%'): + print('\r' + msg, end="", file=sys.stderr), + else: + print('\r' + msg[:-1], end="", file=sys.stderr), + else: + if prefix == '[!]': + print(prefix, msg, end="", file=sys.stderr) + else: + print(prefix, msg, end="") + + +def process_wrap(cmd_str, cwd_path, handler=None, env=None): + process = subprocess.Popen(cmd_str, cwd=cwd_path, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=1) + + if handler is None: + handler = handle_stream + + stdout_thread = threading.Thread(target=handler, args=(process.stdout, "")) + stderr_thread = threading.Thread(target=handler, args=(process.stderr, "[!]")) + + stdout_thread.start() + stderr_thread.start() + + stdout_thread.join() + stderr_thread.join() + + return process.wait() + + +try: + if '--port' in sys.argv: + port_index = sys.argv.index('--port') + if port_index + 1 < len(sys.argv): + port = int(sys.argv[port_index + 1]) + postfix = f"_{port}" + else: + postfix = "" + else: + postfix = "" + + # Logger setup + if enable_file_logging: + if os.path.exists(f"comfyui{postfix}.log"): + if os.path.exists(f"comfyui{postfix}.prev.log"): + if os.path.exists(f"comfyui{postfix}.prev2.log"): + os.remove(f"comfyui{postfix}.prev2.log") + os.rename(f"comfyui{postfix}.prev.log", f"comfyui{postfix}.prev2.log") + os.rename(f"comfyui{postfix}.log", f"comfyui{postfix}.prev.log") + + log_file = open(f"comfyui{postfix}.log", "w", encoding="utf-8", errors="ignore") + + log_lock = threading.Lock() + + original_stdout = sys.stdout + original_stderr = sys.stderr + + if original_stdout.encoding.lower() == 'utf-8': + write_stdout = original_stdout.write + write_stderr = original_stderr.write + else: + def wrapper_stdout(msg): + original_stdout.write(msg.encode('utf-8').decode(original_stdout.encoding, errors="ignore")) + + def wrapper_stderr(msg): + original_stderr.write(msg.encode('utf-8').decode(original_stderr.encoding, errors="ignore")) + + write_stdout = wrapper_stdout + write_stderr = wrapper_stderr + + pat_tqdm = r'\d+%.*\[(.*?)\]' + pat_import_fail = r'seconds \(IMPORT FAILED\):.*[/\\]custom_nodes[/\\](.*)$' + + is_start_mode = True + + + class ComfyUIManagerLogger: + def __init__(self, is_stdout): + self.is_stdout = is_stdout + self.encoding = "utf-8" + self.last_char = '' + + def fileno(self): + try: + if self.is_stdout: + return original_stdout.fileno() + else: + return original_stderr.fileno() + except AttributeError: + # Handle error + raise ValueError("The object does not have a fileno method") + + def isatty(self): + return False + + def write(self, message): + global is_start_mode + + if any(f(message) for f in message_collapses): + return + + if is_start_mode: + match = re.search(pat_import_fail, message) + if match: + import_failed_extensions.add(match.group(1)) + + if 'Starting server' in message: + is_start_mode = False + + if not self.is_stdout: + match = re.search(pat_tqdm, message) + if match: + message = re.sub(r'([#|])\d', r'\1▌', message) + message = re.sub('#', '█', message) + if '100%' in message: + self.sync_write(message) + else: + write_stderr(message) + original_stderr.flush() + else: + self.sync_write(message) + else: + self.sync_write(message) + + def sync_write(self, message, file_only=False): + with log_lock: + timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')[:-3] + if self.last_char != '\n': + log_file.write(message) + else: + log_file.write(f"[{timestamp}] {message}") + log_file.flush() + self.last_char = message if message == '' else message[-1] + + if not file_only: + with std_log_lock: + if self.is_stdout: + write_stdout(message) + original_stdout.flush() + terminal_hook.write_stderr(message) + else: + write_stderr(message) + original_stderr.flush() + terminal_hook.write_stdout(message) + + def flush(self): + log_file.flush() + + with std_log_lock: + if self.is_stdout: + original_stdout.flush() + else: + original_stderr.flush() + + def close(self): + self.flush() + + def reconfigure(self, *args, **kwargs): + pass + + # You can close through sys.stderr.close_log() + def close_log(self): + sys.stderr = original_stderr + sys.stdout = original_stdout + log_file.close() + + def close_log(): + sys.stderr = original_stderr + sys.stdout = original_stdout + log_file.close() + + + if enable_file_logging: + sys.stdout = ComfyUIManagerLogger(True) + stderr_wrapper = ComfyUIManagerLogger(False) + sys.stderr = stderr_wrapper + + atexit.register(close_log) + else: + sys.stdout.close_log = lambda: None + stderr_wrapper = None + + + class LoggingHandler(logging.Handler): + def emit(self, record): + global is_start_mode + + message = record.getMessage() + + if is_start_mode: + match = re.search(pat_import_fail, message) + if match: + import_failed_extensions.add(match.group(1)) + + if 'Starting server' in message: + is_start_mode = False + + if stderr_wrapper: + stderr_wrapper.sync_write(message+'\n', file_only=True) + + + logging.getLogger().addHandler(LoggingHandler()) + + +except Exception as e: + print(f"[ComfyUI-Manager] Logging failed: {e}") + + +try: + import git +except ModuleNotFoundError: + my_path = os.path.dirname(__file__) + requirements_path = os.path.join(my_path, "requirements.txt") + + print(f"## ComfyUI-Manager: installing dependencies. (GitPython)") + try: + result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '-r', requirements_path]) + except subprocess.CalledProcessError as e: + print(f"## [ERROR] ComfyUI-Manager: Attempting to reinstall dependencies using an alternative method.") + try: + result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '--user', '-r', requirements_path]) + except subprocess.CalledProcessError as e: + print(f"## [ERROR] ComfyUI-Manager: Failed to install the GitPython package in the correct Python environment. Please install it manually in the appropriate environment. (You can seek help at https://app.element.io/#/room/%23comfyui_space%3Amatrix.org)") + +try: + import git + print(f"## ComfyUI-Manager: installing dependencies done.") +except: + # maybe we should sys.exit() here? there is at least two screens worth of error messages still being pumped after our error messages + print(f"## [ERROR] ComfyUI-Manager: GitPython package seems to be installed, but failed to load somehow. Make sure you have a working git client installed") + + +print("** ComfyUI startup time:", datetime.datetime.now()) +print("** Platform:", platform.system()) +print("** Python version:", sys.version) +print("** Python executable:", sys.executable) +print("** ComfyUI Path:", comfy_path) + +if enable_file_logging: + print("** Log path:", os.path.abspath('comfyui.log')) +else: + print("** Log path: file logging is disabled") + + +def read_downgrade_blacklist(): + try: + import configparser + config_path = os.path.join(os.path.dirname(__file__), "config.ini") + config = configparser.ConfigParser() + config.read(config_path) + default_conf = config['default'] + + if 'downgrade_blacklist' in default_conf: + items = default_conf['downgrade_blacklist'].split(',') + items = [x.strip() for x in items if x != ''] + cm_global.pip_downgrade_blacklist += items + cm_global.pip_downgrade_blacklist = list(set(cm_global.pip_downgrade_blacklist)) + except: + pass + + +read_downgrade_blacklist() + + +def check_bypass_ssl(): + try: + import configparser + import ssl + config_path = os.path.join(os.path.dirname(__file__), "config.ini") + config = configparser.ConfigParser() + config.read(config_path) + default_conf = config['default'] + + if 'bypass_ssl' in default_conf and default_conf['bypass_ssl'].lower() == 'true': + print(f"[ComfyUI-Manager] WARN: Unsafe - SSL verification bypass option is Enabled. (see ComfyUI-Manager/config.ini)") + ssl._create_default_https_context = ssl._create_unverified_context # SSL certificate error fix. + except Exception: + pass + + +check_bypass_ssl() + + +# Perform install +processed_install = set() +script_list_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "startup-scripts", "install-scripts.txt") +pip_map = None + + +def get_installed_packages(): + global pip_map + + if pip_map is None: + try: + result = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], universal_newlines=True) + + pip_map = {} + for line in result.split('\n'): + x = line.strip() + if x: + y = line.split() + if y[0] == 'Package' or y[0].startswith('-'): + continue + + pip_map[y[0]] = y[1] + except subprocess.CalledProcessError as e: + print(f"[ComfyUI-Manager] Failed to retrieve the information of installed pip packages.") + return set() + + return pip_map + + +def is_installed(name): + name = name.strip() + + if name.startswith('#'): + return True + + pattern = r'([^<>!=]+)([<>!=]=?)(.*)' + match = re.search(pattern, name) + + if match: + name = match.group(1) + + if name in cm_global.pip_downgrade_blacklist: + pips = get_installed_packages() + + if match is None: + if name in pips: + return True + elif match.group(2) in ['<=', '==', '<']: + if name in pips: + if StrictVersion(pips[name]) >= StrictVersion(match.group(3)): + print(f"[ComfyUI-Manager] skip black listed pip installation: '{name}'") + return True + + pkg = get_installed_packages().get(name.lower()) + if pkg is None: + return False # update if not installed + + if match is None: + return True # don't update if version is not specified + + if match.group(2) in ['>', '>=']: + if StrictVersion(pkg) < StrictVersion(match.group(3)): + return False + elif StrictVersion(pkg) > StrictVersion(match.group(3)): + print(f"[SKIP] Downgrading pip package isn't allowed: {name.lower()} (cur={pkg})") + + return True # prevent downgrade + + +if os.path.exists(restore_snapshot_path): + try: + cloned_repos = [] + + def msg_capture(stream, prefix): + stream.reconfigure(encoding=locale.getpreferredencoding(), errors='replace') + for msg in stream: + if msg.startswith("CLONE: "): + cloned_repos.append(msg[7:]) + if prefix == '[!]': + print(prefix, msg, end="", file=sys.stderr) + else: + print(prefix, msg, end="") + + elif prefix == '[!]' and ('it/s]' in msg or 's/it]' in msg) and ('%|' in msg or 'it [' in msg): + if msg.startswith('100%'): + print('\r' + msg, end="", file=sys.stderr), + else: + print('\r'+msg[:-1], end="", file=sys.stderr), + else: + if prefix == '[!]': + print(prefix, msg, end="", file=sys.stderr) + else: + print(prefix, msg, end="") + + print(f"[ComfyUI-Manager] Restore snapshot.") + cmd_str = [sys.executable, git_script_path, '--apply-snapshot', restore_snapshot_path] + + new_env = os.environ.copy() + new_env["COMFYUI_PATH"] = comfy_path + exit_code = process_wrap(cmd_str, custom_nodes_path, handler=msg_capture, env=new_env) + + repository_name = '' + for url in cloned_repos: + try: + repository_name = url.split("/")[-1].strip() + repo_path = os.path.join(custom_nodes_path, repository_name) + repo_path = os.path.abspath(repo_path) + + requirements_path = os.path.join(repo_path, 'requirements.txt') + install_script_path = os.path.join(repo_path, 'install.py') + + this_exit_code = 0 + + if os.path.exists(requirements_path): + with open(requirements_path, 'r', encoding="UTF-8", errors="ignore") as file: + for line in file: + package_name = remap_pip_package(line.strip()) + if package_name and not is_installed(package_name): + if not package_name.startswith('#'): + install_cmd = [sys.executable, "-m", "pip", "install", package_name] + this_exit_code += process_wrap(install_cmd, repo_path) + + if os.path.exists(install_script_path) and f'{repo_path}/install.py' not in processed_install: + processed_install.add(f'{repo_path}/install.py') + install_cmd = [sys.executable, install_script_path] + print(f">>> {install_cmd} / {repo_path}") + + new_env = os.environ.copy() + new_env["COMFYUI_PATH"] = comfy_path + this_exit_code += process_wrap(install_cmd, repo_path, env=new_env) + + if this_exit_code != 0: + print(f"[ComfyUI-Manager] Restoring '{repository_name}' is failed.") + + except Exception as e: + print(e) + print(f"[ComfyUI-Manager] Restoring '{repository_name}' is failed.") + + if exit_code != 0: + print(f"[ComfyUI-Manager] Restore snapshot failed.") + else: + print(f"[ComfyUI-Manager] Restore snapshot done.") + + except Exception as e: + print(e) + print(f"[ComfyUI-Manager] Restore snapshot failed.") + + os.remove(restore_snapshot_path) + + +def execute_lazy_install_script(repo_path, executable): + global processed_install + + install_script_path = os.path.join(repo_path, "install.py") + requirements_path = os.path.join(repo_path, "requirements.txt") + + if os.path.exists(requirements_path): + print(f"Install: pip packages for '{repo_path}'") + with open(requirements_path, "r") as requirements_file: + for line in requirements_file: + package_name = remap_pip_package(line.strip()) + if package_name and not is_installed(package_name): + install_cmd = [executable, "-m", "pip", "install", package_name] + process_wrap(install_cmd, repo_path) + + if os.path.exists(install_script_path) and f'{repo_path}/install.py' not in processed_install: + processed_install.add(f'{repo_path}/install.py') + print(f"Install: install script for '{repo_path}'") + install_cmd = [executable, "install.py"] + + new_env = os.environ.copy() + new_env["COMFYUI_PATH"] = comfy_path + process_wrap(install_cmd, repo_path, env=new_env) + + +# Check if script_list_path exists +if os.path.exists(script_list_path): + print("\n#######################################################################") + print("[ComfyUI-Manager] Starting dependency installation/(de)activation for the extension\n") + + executed = set() + # Read each line from the file and convert it to a list using eval + with open(script_list_path, 'r', encoding="UTF-8", errors="ignore") as file: + for line in file: + if line in executed: + continue + + executed.add(line) + + try: + script = ast.literal_eval(line) + + if script[1].startswith('#') and script[1] != '#FORCE': + if script[1] == "#LAZY-INSTALL-SCRIPT": + execute_lazy_install_script(script[0], script[2]) + + elif os.path.exists(script[0]): + if script[1] == "#FORCE": + del script[1] + else: + if 'pip' in script[1:] and 'install' in script[1:] and is_installed(script[-1]): + continue + + print(f"\n## ComfyUI-Manager: EXECUTE => {script[1:]}") + print(f"\n## Execute install/(de)activation script for '{script[0]}'") + + new_env = os.environ.copy() + new_env["COMFYUI_PATH"] = comfy_path + exit_code = process_wrap(script[1:], script[0], env=new_env) + + if exit_code != 0: + print(f"install/(de)activation script failed: {script[0]}") + else: + print(f"\n## ComfyUI-Manager: CANCELED => {script[1:]}") + + except Exception as e: + print(f"[ERROR] Failed to execute install/(de)activation script: {line} / {e}") + + # Remove the script_list_path file + if os.path.exists(script_list_path): + os.remove(script_list_path) + + print("\n[ComfyUI-Manager] Startup script completed.") + print("#######################################################################\n") + +del processed_install +del pip_map + + +def check_windows_event_loop_policy(): + try: + import configparser + config_path = os.path.join(os.path.dirname(__file__), "config.ini") + config = configparser.ConfigParser() + config.read(config_path) + default_conf = config['default'] + + if 'windows_selector_event_loop_policy' in default_conf and default_conf['windows_selector_event_loop_policy'].lower() == 'true': + try: + import asyncio + import asyncio.windows_events + asyncio.set_event_loop_policy(asyncio.windows_events.WindowsSelectorEventLoopPolicy()) + print(f"[ComfyUI-Manager] Windows event loop policy mode enabled") + except Exception as e: + print(f"[ComfyUI-Manager] WARN: Windows initialization fail: {e}") + except Exception: + pass + + +if platform.system() == 'Windows': + check_windows_event_loop_policy() diff --git a/custom_nodes/ComfyUI-Manager/pyproject.toml b/custom_nodes/ComfyUI-Manager/pyproject.toml new file mode 100644 index 000000000..fbb0be02f --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/pyproject.toml @@ -0,0 +1,15 @@ +[project] +name = "comfyui-manager" +description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI." +version = "2.46.2" +license = "LICENSE" +dependencies = ["GitPython", "PyGithub", "matrix-client==0.4.0", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions"] + +[project.urls] +Repository = "https://github.com/ltdrdata/ComfyUI-Manager" +# Used by Comfy Registry https://comfyregistry.org + +[tool.comfy] +PublisherId = "drltdata" +DisplayName = "ComfyUI-Manager" +Icon = "" diff --git a/custom_nodes/ComfyUI-Manager/requirements.txt b/custom_nodes/ComfyUI-Manager/requirements.txt new file mode 100644 index 000000000..89f93b417 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/requirements.txt @@ -0,0 +1,8 @@ +GitPython +PyGithub +matrix-client==0.4.0 +transformers +huggingface-hub>0.20 +typer +rich +typing-extensions \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/scan.sh b/custom_nodes/ComfyUI-Manager/scan.sh new file mode 100644 index 000000000..f1f088ecc --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/scan.sh @@ -0,0 +1,7 @@ +#!/bin/bash +rm ~/.tmp/default/*.py > /dev/null 2>&1 +python scanner.py ~/.tmp/default $* +cp extension-node-map.json node_db/new/. + +echo Integrity check +./check.sh diff --git a/custom_nodes/ComfyUI-Manager/scanner.py b/custom_nodes/ComfyUI-Manager/scanner.py new file mode 100644 index 000000000..0118768fd --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/scanner.py @@ -0,0 +1,527 @@ +import ast +import re +import os +import json +from git import Repo +import concurrent +import datetime +import concurrent.futures +import requests + +builtin_nodes = set() + +import sys + +from urllib.parse import urlparse +from github import Github + + +def download_url(url, dest_folder, filename=None): + # Ensure the destination folder exists + if not os.path.exists(dest_folder): + os.makedirs(dest_folder) + + # Extract filename from URL if not provided + if filename is None: + filename = os.path.basename(url) + + # Full path to save the file + dest_path = os.path.join(dest_folder, filename) + + # Download the file + response = requests.get(url, stream=True) + if response.status_code == 200: + with open(dest_path, 'wb') as file: + for chunk in response.iter_content(chunk_size=1024): + if chunk: + file.write(chunk) + else: + raise Exception(f"Failed to download file from {url}") + + +# prepare temp dir +if len(sys.argv) > 1: + temp_dir = sys.argv[1] +else: + temp_dir = os.path.join(os.getcwd(), ".tmp") + +if not os.path.exists(temp_dir): + os.makedirs(temp_dir) + + +skip_update = '--skip-update' in sys.argv or '--skip-all' in sys.argv +skip_stat_update = '--skip-stat-update' in sys.argv or '--skip-all' in sys.argv + +if not skip_stat_update: + g = Github(os.environ.get('GITHUB_TOKEN')) +else: + g = None + + +print(f"TEMP DIR: {temp_dir}") + + +parse_cnt = 0 + + +def extract_nodes(code_text): + global parse_cnt + + try: + if parse_cnt % 100 == 0: + print(f".", end="", flush=True) + parse_cnt += 1 + + code_text = re.sub(r'\\[^"\']', '', code_text) + parsed_code = ast.parse(code_text) + + assignments = (node for node in parsed_code.body if isinstance(node, ast.Assign)) + + for assignment in assignments: + if isinstance(assignment.targets[0], ast.Name) and assignment.targets[0].id in ['NODE_CONFIG', 'NODE_CLASS_MAPPINGS']: + node_class_mappings = assignment.value + break + else: + node_class_mappings = None + + if node_class_mappings: + s = set() + + for key in node_class_mappings.keys: + if key is not None and isinstance(key.value, str): + s.add(key.value.strip()) + + return s + else: + return set() + except: + return set() + + +# scan +def scan_in_file(filename, is_builtin=False): + global builtin_nodes + + try: + with open(filename, encoding='utf-8') as file: + code = file.read() + except UnicodeDecodeError: + with open(filename, encoding='cp949') as file: + code = file.read() + + pattern = r"_CLASS_MAPPINGS\s*=\s*{([^}]*)}" + regex = re.compile(pattern, re.MULTILINE | re.DOTALL) + + nodes = set() + class_dict = {} + + nodes |= extract_nodes(code) + code = re.sub(r'^#.*?$', '', code, flags=re.MULTILINE) + + def extract_keys(pattern, code): + keys = re.findall(pattern, code) + return {key.strip() for key in keys} + + def update_nodes(nodes, new_keys): + nodes |= new_keys + + patterns = [ + r'^[^=]*_CLASS_MAPPINGS\["(.*?)"\]', + r'^[^=]*_CLASS_MAPPINGS\[\'(.*?)\'\]', + r'@register_node\("(.+)",\s*\".+"\)', + r'"(\w+)"\s*:\s*{"class":\s*\w+\s*' + ] + + with concurrent.futures.ThreadPoolExecutor() as executor: + futures = {executor.submit(extract_keys, pattern, code): pattern for pattern in patterns} + for future in concurrent.futures.as_completed(futures): + update_nodes(nodes, future.result()) + + matches = regex.findall(code) + for match in matches: + dict_text = match + + key_value_pairs = re.findall(r"\"([^\"]*)\"\s*:\s*([^,\n]*)", dict_text) + for key, value in key_value_pairs: + class_dict[key.strip()] = value.strip() + + key_value_pairs = re.findall(r"'([^']*)'\s*:\s*([^,\n]*)", dict_text) + for key, value in key_value_pairs: + class_dict[key.strip()] = value.strip() + + for key, value in class_dict.items(): + nodes.add(key.strip()) + + update_pattern = r"_CLASS_MAPPINGS.update\s*\({([^}]*)}\)" + update_match = re.search(update_pattern, code) + if update_match: + update_dict_text = update_match.group(1) + update_key_value_pairs = re.findall(r"\"([^\"]*)\"\s*:\s*([^,\n]*)", update_dict_text) + for key, value in update_key_value_pairs: + class_dict[key.strip()] = value.strip() + nodes.add(key.strip()) + + metadata = {} + lines = code.strip().split('\n') + for line in lines: + if line.startswith('@'): + if line.startswith("@author:") or line.startswith("@title:") or line.startswith("@nickname:") or line.startswith("@description:"): + key, value = line[1:].strip().split(':', 1) + metadata[key.strip()] = value.strip() + + if is_builtin: + builtin_nodes += set(nodes) + else: + for x in builtin_nodes: + if x in nodes: + nodes.remove(x) + + return nodes, metadata + + +def get_py_file_paths(dirname): + file_paths = [] + + for root, dirs, files in os.walk(dirname): + if ".git" in root or "__pycache__" in root: + continue + + for file in files: + if file.endswith(".py"): + file_path = os.path.join(root, file) + file_paths.append(file_path) + + return file_paths + + +def get_nodes(target_dir): + py_files = [] + directories = [] + + for item in os.listdir(target_dir): + if ".git" in item or "__pycache__" in item: + continue + + path = os.path.abspath(os.path.join(target_dir, item)) + + if os.path.isfile(path) and item.endswith(".py"): + py_files.append(path) + elif os.path.isdir(path): + directories.append(path) + + return py_files, directories + + +def get_git_urls_from_json(json_file): + with open(json_file, encoding='utf-8') as file: + data = json.load(file) + + custom_nodes = data.get('custom_nodes', []) + git_clone_files = [] + for node in custom_nodes: + if node.get('install_type') == 'git-clone': + files = node.get('files', []) + if files: + git_clone_files.append((files[0], node.get('title'), node.get('preemptions'), node.get('nodename_pattern'))) + + git_clone_files.append(("https://github.com/comfyanonymous/ComfyUI", "ComfyUI", None, None)) + + return git_clone_files + + +def get_py_urls_from_json(json_file): + with open(json_file, encoding='utf-8') as file: + data = json.load(file) + + custom_nodes = data.get('custom_nodes', []) + py_files = [] + for node in custom_nodes: + if node.get('install_type') == 'copy': + files = node.get('files', []) + if files: + py_files.append((files[0], node.get('title'), node.get('preemptions'), node.get('nodename_pattern'))) + + return py_files + + +def clone_or_pull_git_repository(git_url): + repo_name = git_url.split("/")[-1].split(".")[0] + repo_dir = os.path.join(temp_dir, repo_name) + + if os.path.exists(repo_dir): + try: + repo = Repo(repo_dir) + origin = repo.remote(name="origin") + origin.pull() + repo.git.submodule('update', '--init', '--recursive') + print(f"Pulling {repo_name}...") + except Exception as e: + print(f"Pulling {repo_name} failed: {e}") + else: + try: + Repo.clone_from(git_url, repo_dir, recursive=True) + print(f"Cloning {repo_name}...") + except Exception as e: + print(f"Cloning {repo_name} failed: {e}") + + +def update_custom_nodes(): + if not os.path.exists(temp_dir): + os.makedirs(temp_dir) + + node_info = {} + + git_url_titles_preemptions = get_git_urls_from_json('custom-node-list.json') + + def process_git_url_title(url, title, preemptions, node_pattern): + name = os.path.basename(url) + if name.endswith(".git"): + name = name[:-4] + + node_info[name] = (url, title, preemptions, node_pattern) + if not skip_update: + clone_or_pull_git_repository(url) + + def process_git_stats(git_url_titles_preemptions): + GITHUB_STATS_CACHE_FILENAME = 'github-stats-cache.json' + GITHUB_STATS_FILENAME = 'github-stats.json' + + github_stats = {} + try: + with open(GITHUB_STATS_CACHE_FILENAME, 'r', encoding='utf-8') as file: + github_stats = json.load(file) + except FileNotFoundError: + pass + + def is_rate_limit_exceeded(): + return g.rate_limiting[0] == 0 + + if is_rate_limit_exceeded(): + print(f"GitHub API Rate Limit Exceeded: remained - {(g.rate_limiting_resettime - datetime.datetime.now().timestamp())/60:.2f} min") + else: + def renew_stat(url): + if is_rate_limit_exceeded(): + return + + if 'github.com' not in url: + return None + + print('.', end="") + sys.stdout.flush() + try: + # Parsing the URL + parsed_url = urlparse(url) + domain = parsed_url.netloc + path = parsed_url.path + path_parts = path.strip("/").split("/") + if len(path_parts) >= 2 and domain == "github.com": + owner_repo = "/".join(path_parts[-2:]) + repo = g.get_repo(owner_repo) + owner = repo.owner + now = datetime.datetime.now(datetime.timezone.utc) + author_time_diff = now - owner.created_at + + last_update = repo.pushed_at.strftime("%Y-%m-%d %H:%M:%S") if repo.pushed_at else 'N/A' + item = { + "stars": repo.stargazers_count, + "last_update": last_update, + "cached_time": now.timestamp(), + "author_account_age_days": author_time_diff.days, + } + return url, item + else: + print(f"\nInvalid URL format for GitHub repository: {url}\n") + except Exception as e: + print(f"\nERROR on {url}\n{e}") + + return None + + # resolve unresolved urls + with concurrent.futures.ThreadPoolExecutor(11) as executor: + futures = [] + for url, title, preemptions, node_pattern in git_url_titles_preemptions: + if url not in github_stats: + futures.append(executor.submit(renew_stat, url)) + + for future in concurrent.futures.as_completed(futures): + url_item = future.result() + if url_item is not None: + url, item = url_item + github_stats[url] = item + + # renew outdated cache + outdated_urls = [] + for k, v in github_stats.items(): + elapsed = (datetime.datetime.now().timestamp() - v['cached_time']) + if elapsed > 60*60*12: # 12 hours + outdated_urls.append(k) + + with concurrent.futures.ThreadPoolExecutor(11) as executor: + for url in outdated_urls: + futures.append(executor.submit(renew_stat, url)) + + for future in concurrent.futures.as_completed(futures): + url_item = future.result() + if url_item is not None: + url, item = url_item + github_stats[url] = item + + with open('github-stats-cache.json', 'w', encoding='utf-8') as file: + json.dump(github_stats, file, ensure_ascii=False, indent=4) + + with open(GITHUB_STATS_FILENAME, 'w', encoding='utf-8') as file: + for v in github_stats.values(): + if "cached_time" in v: + del v["cached_time"] + + github_stats = dict(sorted(github_stats.items())) + + json.dump(github_stats, file, ensure_ascii=False, indent=4) + + print(f"Successfully written to {GITHUB_STATS_FILENAME}.") + + if not skip_stat_update: + process_git_stats(git_url_titles_preemptions) + + with concurrent.futures.ThreadPoolExecutor(11) as executor: + for url, title, preemptions, node_pattern in git_url_titles_preemptions: + executor.submit(process_git_url_title, url, title, preemptions, node_pattern) + + py_url_titles_and_pattern = get_py_urls_from_json('custom-node-list.json') + + def download_and_store_info(url_title_preemptions_and_pattern): + url, title, preemptions, node_pattern = url_title_preemptions_and_pattern + name = os.path.basename(url) + if name.endswith(".py"): + node_info[name] = (url, title, preemptions, node_pattern) + + try: + download_url(url, temp_dir) + except: + print(f"[ERROR] Cannot download '{url}'") + + with concurrent.futures.ThreadPoolExecutor(10) as executor: + executor.map(download_and_store_info, py_url_titles_and_pattern) + + return node_info + + +def gen_json(node_info): + # scan from .py file + node_files, node_dirs = get_nodes(temp_dir) + + comfyui_path = os.path.abspath(os.path.join(temp_dir, "ComfyUI")) + node_dirs.remove(comfyui_path) + node_dirs = [comfyui_path] + node_dirs + + data = {} + for dirname in node_dirs: + py_files = get_py_file_paths(dirname) + metadata = {} + + nodes = set() + for py in py_files: + nodes_in_file, metadata_in_file = scan_in_file(py, dirname == "ComfyUI") + nodes.update(nodes_in_file) + metadata.update(metadata_in_file) + + dirname = os.path.basename(dirname) + + if 'Jovimetrix' in dirname: + pass + + if len(nodes) > 0 or (dirname in node_info and node_info[dirname][3] is not None): + nodes = list(nodes) + nodes.sort() + + if dirname in node_info: + git_url, title, preemptions, node_pattern = node_info[dirname] + + metadata['title_aux'] = title + + if preemptions is not None: + metadata['preemptions'] = preemptions + + if node_pattern is not None: + metadata['nodename_pattern'] = node_pattern + + data[git_url] = (nodes, metadata) + else: + print(f"WARN: {dirname} is removed from custom-node-list.json") + + for file in node_files: + nodes, metadata = scan_in_file(file) + + if len(nodes) > 0 or (dirname in node_info and node_info[dirname][3] is not None): + nodes = list(nodes) + nodes.sort() + + file = os.path.basename(file) + + if file in node_info: + url, title, preemptions, node_pattern = node_info[file] + metadata['title_aux'] = title + + if preemptions is not None: + metadata['preemptions'] = preemptions + + if node_pattern is not None: + metadata['nodename_pattern'] = node_pattern + + data[url] = (nodes, metadata) + else: + print(f"Missing info: {file}") + + # scan from node_list.json file + extensions = [name for name in os.listdir(temp_dir) if os.path.isdir(os.path.join(temp_dir, name))] + + for extension in extensions: + node_list_json_path = os.path.join(temp_dir, extension, 'node_list.json') + if os.path.exists(node_list_json_path): + git_url, title, preemptions, node_pattern = node_info[extension] + + with open(node_list_json_path, 'r', encoding='utf-8') as f: + try: + node_list_json = json.load(f) + except Exception as e: + print(f"\nERROR: Invalid json format '{node_list_json_path}'") + print("------------------------------------------------------") + print(e) + print("------------------------------------------------------") + + metadata_in_url = {} + if git_url not in data: + nodes = set() + else: + nodes_in_url, metadata_in_url = data[git_url] + nodes = set(nodes_in_url) + + for x, desc in node_list_json.items(): + nodes.add(x.strip()) + + metadata_in_url['title_aux'] = title + + if preemptions is not None: + metadata['preemptions'] = preemptions + + if node_pattern is not None: + metadata_in_url['nodename_pattern'] = node_pattern + + nodes = list(nodes) + nodes.sort() + data[git_url] = (nodes, metadata_in_url) + + json_path = f"extension-node-map.json" + with open(json_path, "w", encoding='utf-8') as file: + json.dump(data, file, indent=4, sort_keys=True) + + +print("### ComfyUI Manager Node Scanner ###") + +print("\n# Updating extensions\n") +updated_node_info = update_custom_nodes() + +print("\n# 'extension-node-map.json' file is generated.\n") +gen_json(updated_node_info) + +print("\nDONE.\n") \ No newline at end of file diff --git a/custom_nodes/ComfyUI-Manager/scripts/colab-dependencies.py b/custom_nodes/ComfyUI-Manager/scripts/colab-dependencies.py new file mode 100644 index 000000000..d5a70ed6d --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/scripts/colab-dependencies.py @@ -0,0 +1,39 @@ +import os +import subprocess + + +def get_enabled_subdirectories_with_files(base_directory): + subdirs_with_files = [] + for subdir in os.listdir(base_directory): + try: + full_path = os.path.join(base_directory, subdir) + if os.path.isdir(full_path) and not subdir.endswith(".disabled") and not subdir.startswith('.') and subdir != '__pycache__': + print(f"## Install dependencies for '{subdir}'") + requirements_file = os.path.join(full_path, "requirements.txt") + install_script = os.path.join(full_path, "install.py") + + if os.path.exists(requirements_file) or os.path.exists(install_script): + subdirs_with_files.append((full_path, requirements_file, install_script)) + except Exception as e: + print(f"EXCEPTION During Dependencies INSTALL on '{subdir}':\n{e}") + + return subdirs_with_files + + +def install_requirements(requirements_file_path): + if os.path.exists(requirements_file_path): + subprocess.run(["pip", "install", "-r", requirements_file_path]) + + +def run_install_script(install_script_path): + if os.path.exists(install_script_path): + subprocess.run(["python", install_script_path]) + + +custom_nodes_directory = "custom_nodes" +subdirs_with_files = get_enabled_subdirectories_with_files(custom_nodes_directory) + + +for subdir, requirements_file, install_script in subdirs_with_files: + install_requirements(requirements_file) + run_install_script(install_script) diff --git a/custom_nodes/ComfyUI-Manager/scripts/install-comfyui-venv-linux.sh b/custom_nodes/ComfyUI-Manager/scripts/install-comfyui-venv-linux.sh new file mode 100644 index 000000000..fecf3d5bc --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/scripts/install-comfyui-venv-linux.sh @@ -0,0 +1,21 @@ +git clone https://github.com/comfyanonymous/ComfyUI +cd ComfyUI/custom_nodes +git clone https://github.com/ltdrdata/ComfyUI-Manager +cd .. +python -m venv venv +source venv/bin/activate +python -m pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu121 +python -m pip install -r requirements.txt +python -m pip install -r custom_nodes/ComfyUI-Manager/requirements.txt +cd .. +echo "#!/bin/bash" > run_gpu.sh +echo "cd ComfyUI" >> run_gpu.sh +echo "source venv/bin/activate" >> run_gpu.sh +echo "python main.py --preview-method auto" >> run_gpu.sh +chmod +x run_gpu.sh + +echo "#!/bin/bash" > run_cpu.sh +echo "cd ComfyUI" >> run_cpu.sh +echo "source venv/bin/activate" >> run_cpu.sh +echo "python main.py --preview-method auto --cpu" >> run_cpu.sh +chmod +x run_cpu.sh diff --git a/custom_nodes/ComfyUI-Manager/scripts/install-comfyui-venv-win.bat b/custom_nodes/ComfyUI-Manager/scripts/install-comfyui-venv-win.bat new file mode 100644 index 000000000..2789ef6db --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/scripts/install-comfyui-venv-win.bat @@ -0,0 +1,17 @@ +git clone https://github.com/comfyanonymous/ComfyUI +cd ComfyUI/custom_nodes +git clone https://github.com/ltdrdata/ComfyUI-Manager +cd .. +python -m venv venv +call venv/Scripts/activate +python -m pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu121 +python -m pip install -r requirements.txt +python -m pip install -r custom_nodes/ComfyUI-Manager/requirements.txt +cd .. +echo "cd ComfyUI" >> run_gpu.bat +echo "call venv/Scripts/activate" >> run_gpu.bat +echo "python main.py" >> run_gpu.bat + +echo "cd ComfyUI" >> run_cpu.bat +echo "call venv/Scripts/activate" >> run_cpu.bat +echo "python main.py --cpu" >> run_cpu.bat diff --git a/custom_nodes/ComfyUI-Manager/scripts/install-manager-for-portable-version.bat b/custom_nodes/ComfyUI-Manager/scripts/install-manager-for-portable-version.bat new file mode 100644 index 000000000..7b067dfd7 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/scripts/install-manager-for-portable-version.bat @@ -0,0 +1,2 @@ +.\python_embeded\python.exe -s -m pip install gitpython +.\python_embeded\python.exe -c "import git; git.Repo.clone_from('https://github.com/ltdrdata/ComfyUI-Manager', './ComfyUI/custom_nodes/ComfyUI-Manager')" diff --git a/custom_nodes/ComfyUI-Manager/scripts/update-fix.py b/custom_nodes/ComfyUI-Manager/scripts/update-fix.py new file mode 100644 index 000000000..d2ac10074 --- /dev/null +++ b/custom_nodes/ComfyUI-Manager/scripts/update-fix.py @@ -0,0 +1,12 @@ +import git + +commit_hash = "a361cc1" + +repo = git.Repo('.') + +if repo.is_dirty(): + repo.git.stash() + +repo.git.update_ref("refs/remotes/origin/main", commit_hash) +repo.remotes.origin.fetch() +repo.git.pull("origin", "main") diff --git a/custom_nodes/ComfyUI-Manager/snapshots/the_snapshot_files_are_located_here b/custom_nodes/ComfyUI-Manager/snapshots/the_snapshot_files_are_located_here new file mode 100644 index 000000000..e69de29bb