ComfyUI/docs/custom-nodes.md

8.4 KiB

Custom Nodes Guide

This document provides detailed information for developers who want to create custom nodes for ComfyUI.

Table of Contents

Introduction

ComfyUI's power comes from its extensibility through custom nodes. Custom nodes allow you to:

  • Add new functionality not available in the core application
  • Optimize existing workflows
  • Create specialized interfaces for specific tasks
  • Integrate with external tools and services

This guide will walk you through creating, testing, and distributing custom nodes.

Setting Up the Development Environment

Prerequisites

  • Python 3.9+ (3.11 recommended)
  • ComfyUI installed (source installation recommended for development)
  • Basic knowledge of Python
  • Understanding of ComfyUI's node system

Development Environment Setup

  1. Install ComfyUI from source:

    git clone https://github.com/comfyanonymous/ComfyUI.git
    cd ComfyUI
    
    # Set up development environment
    uv venv .venv
    source .venv/bin/activate  # Linux/macOS
    # or
    .venv\Scripts\activate     # Windows
    
    # Install dependencies
    uv pip install -e ".[dev]"
    
  2. Create a custom nodes directory:

    mkdir -p custom_nodes/my_custom_node
    cd custom_nodes/my_custom_node
    

Custom Node Structure

A typical custom node package has the following structure:

my_custom_node/
├── __init__.py           # Entry point for your node
├── nodes.py              # Node implementation
├── requirements.txt      # Dependencies
├── README.md             # Documentation
└── web/                  # [Optional] Frontend components
    ├── js/
    │   └── my_node.js    # Custom UI components
    └── style.css         # Custom styling

Creating Your First Node

Basic Node Template

Create a file called nodes.py with the following content:

# nodes.py
import torch
import numpy as np
from PIL import Image

class MyCustomNode:
    """
    A simple custom node that applies a filter to an image.
    """
    
    # Define the input and output types for the node
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "image": ("IMAGE",),
                "intensity": ("FLOAT", {
                    "default": 1.0,
                    "min": 0.0,
                    "max": 2.0,
                    "step": 0.01
                }),
            },
        }
    
    # Define the return types
    RETURN_TYPES = ("IMAGE",)
    # Optional: Define output names (defaults to return types)
    RETURN_NAMES = ("filtered_image",)
    # Define the node category for UI organization
    CATEGORY = "image/filters"
    # Optional: Add a description
    DESCRIPTION = "Applies a custom filter to the input image"
    
    def __init__(self):
        pass
    
    def execute(self, image, intensity):
        # Convert from tensor format to numpy for processing
        # Assuming image is [B, H, W, C] format
        img_np = image.numpy()
        
        # Apply a simple brightness adjustment as an example
        adjusted = np.clip(img_np * intensity, 0, 1)
        
        # Convert back to tensor
        result = torch.from_numpy(adjusted)
        
        return (result,)

Register Your Node

Create an __init__.py file to register your node:

# __init__.py
from .nodes import MyCustomNode

NODE_CLASS_MAPPINGS = {
    "MyCustomNode": MyCustomNode
}

NODE_DISPLAY_NAME_MAPPINGS = {
    "MyCustomNode": "My Custom Filter"
}

Node Inputs and Outputs

Input Types

ComfyUI supports several input types:

  • INT: Integer values
  • FLOAT: Floating point values
  • STRING: Text strings
  • BOOLEAN: True/False values
  • IMAGE: Image data
  • Custom enum types: A list of string options

Input Configuration

For numeric inputs, you can provide additional configuration:

"parameter_name": ("FLOAT", {
    "default": 1.0,
    "min": 0.0,
    "max": 10.0,
    "step": 0.1,
    "display": "slider"  # or "number" for a numeric input field
})

For dropdown selectors:

"mode": (["option1", "option2", "option3"],)

Output Types

Common output types include:

  • IMAGE: Processed image data
  • MASK: Image mask data
  • LATENT: Latent space representation
  • CONDITIONING: Conditioning data for samplers
  • MODEL: Model data

Multi-Output Nodes

For nodes with multiple outputs:

RETURN_TYPES = ("IMAGE", "MASK")
RETURN_NAMES = ("output_image", "image_mask")

Advanced Node Development

Handling Batches of Images

To process batches efficiently:

def execute(self, image, intensity):
    # image has shape [B, H, W, C]
    batch_size = image.shape[0]
    result = []
    
    for i in range(batch_size):
        # Process each image in the batch
        img = image[i]
        # Apply processing
        processed = self.process_single_image(img, intensity)
        result.append(processed)
    
    # Stack results back into a batch
    return (torch.stack(result),)

Integrating External Libraries

For nodes that use external libraries:

  1. Add requirements to requirements.txt:

    opencv-python>=4.5.0
    scikit-image>=0.19.0
    
  2. Import and use in your node:

    import cv2
    from skimage import filters
    
    class ImageProcessingNode:
        # ...
        def execute(self, image, params):
            # Convert to format for OpenCV
            img_np = (image.numpy() * 255).astype(np.uint8)
            # Process with CV2
            processed = cv2.someFunction(img_np, params)
            # Convert back
            return (torch.from_numpy(processed / 255.0),)
    

Custom UI Components

For advanced UI elements, create a JavaScript file in web/js/:

// web/js/my_component.js
import { app } from "../../scripts/app.js";

app.registerExtension({
    name: "MyCustomComponent",
    async setup(app) {
        // Register a custom widget
        app.registerNodeDef("MyCustomNode", {
            color: "#5588AA",
            uiFields: {
                "customParameter": (node, inputName) => {
                    // Create custom UI element
                    const widget = document.createElement("div");
                    widget.innerHTML = `<div class="custom-control">...</div>`;
                    return { element: widget };
                }
            }
        });
    }
});

Distributing Custom Nodes

Packaging

  1. Create a README.md with installation and usage instructions
  2. Include a requirements.txt with dependencies
  3. Add example workflows in your documentation
  4. Include screenshots of the node in action

Installation Instructions

Provide clear installation instructions:

## Installation

1. Navigate to your ComfyUI custom_nodes directory
2. Clone this repository:

git clone https://github.com/username/my-custom-node.git

3. Install requirements:

cd my-custom-node pip install -r requirements.txt

4. Restart ComfyUI

Publishing

  1. Publish your code to GitHub
  2. Add your node to the ComfyUI Custom Nodes List
  3. Share in the ComfyUI Discord community

Best Practices

Performance

  • Optimize tensor operations for speed
  • Use batch processing where possible
  • Consider adding a "preview" mode for complex operations
  • Clean up resources in __del__ if needed

Compatibility

  • Test with different ComfyUI versions
  • Document minimum requirements
  • Provide fallbacks for optional dependencies
  • Handle different image formats and dimensions

User Experience

  • Use clear, descriptive names for nodes and parameters
  • Add tooltips with DESCRIPTION and input descriptions
  • Include examples in your documentation
  • Add visual feedback for long-running operations

Error Handling

  • Validate inputs before processing
  • Provide clear error messages
  • Handle edge cases gracefully
  • Add debug logging for troubleshooting

Version Management

  • Use semantic versioning
  • Keep a changelog
  • Test thoroughly before releasing updates
  • Document breaking changes