mirror of
https://git.datalinker.icu/comfyanonymous/ComfyUI
synced 2026-09-06 13:27:08 +08:00
docs: add comprehensive guide for creating custom nodes in ComfyUI
This commit is contained in:
parent
ce337af026
commit
5e9da4d2ca
347
docs/custom-nodes.md
Normal file
347
docs/custom-nodes.md
Normal file
@ -0,0 +1,347 @@
|
||||
# Custom Nodes Guide
|
||||
|
||||
This document provides detailed information for developers who want to create custom nodes for ComfyUI.
|
||||
|
||||
## Table of Contents
|
||||
- [Introduction](#introduction)
|
||||
- [Setting Up the Development Environment](#setting-up-the-development-environment)
|
||||
- [Custom Node Structure](#custom-node-structure)
|
||||
- [Creating Your First Node](#creating-your-first-node)
|
||||
- [Node Inputs and Outputs](#node-inputs-and-outputs)
|
||||
- [Advanced Node Development](#advanced-node-development)
|
||||
- [Distributing Custom Nodes](#distributing-custom-nodes)
|
||||
- [Best Practices](#best-practices)
|
||||
|
||||
## 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:
|
||||
```bash
|
||||
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:
|
||||
```bash
|
||||
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:
|
||||
|
||||
```python
|
||||
# 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:
|
||||
|
||||
```python
|
||||
# __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:
|
||||
|
||||
```python
|
||||
"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:
|
||||
|
||||
```python
|
||||
"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:
|
||||
|
||||
```python
|
||||
RETURN_TYPES = ("IMAGE", "MASK")
|
||||
RETURN_NAMES = ("output_image", "image_mask")
|
||||
```
|
||||
|
||||
## Advanced Node Development
|
||||
|
||||
### Handling Batches of Images
|
||||
|
||||
To process batches efficiently:
|
||||
|
||||
```python
|
||||
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:
|
||||
```python
|
||||
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/`:
|
||||
|
||||
```javascript
|
||||
// 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:
|
||||
|
||||
```markdown
|
||||
## 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](https://github.com/comfyanonymous/ComfyUI-Custom-Nodes)
|
||||
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
|
||||
Loading…
x
Reference in New Issue
Block a user