2023-09-21 22:23:01 -04:00
import comfy . utils
2024-10-16 14:58:30 -04:00
import comfy_extras . nodes_post_processing
2023-11-20 03:55:51 -05:00
import torch
2025-08-28 16:38:28 -07:00
import nodes
2025-10-09 09:14:00 +03:00
from typing_extensions import override
from comfy_api . latest import ComfyExtension , io
2025-12-06 05:20:22 +02:00
import logging
2025-12-18 19:21:40 -08:00
import math
2025-01-22 06:37:46 -05:00
def reshape_latent_to ( target_shape , latent , repeat_batch = True ) :
2023-09-21 22:23:01 -04:00
if latent . shape [ 1 : ] != target_shape [ 1 : ] :
2025-01-22 06:37:46 -05:00
latent = comfy . utils . common_upscale ( latent , target_shape [ - 1 ] , target_shape [ - 2 ] , " bilinear " , " center " )
if repeat_batch :
return comfy . utils . repeat_to_batch_size ( latent , target_shape [ 0 ] )
else :
return latent
2023-09-21 22:23:01 -04:00
2025-10-09 09:14:00 +03:00
class LatentAdd ( io . ComfyNode ) :
2023-09-21 22:23:01 -04:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentAdd " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " combine latents " , " sum latents " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced " ,
2025-10-09 09:14:00 +03:00
inputs = [
io . Latent . Input ( " samples1 " ) ,
io . Latent . Input ( " samples2 " ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
2023-09-21 22:23:01 -04:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , samples1 , samples2 ) - > io . NodeOutput :
2023-09-21 22:23:01 -04:00
samples_out = samples1 . copy ( )
s1 = samples1 [ " samples " ]
s2 = samples2 [ " samples " ]
s2 = reshape_latent_to ( s1 . shape , s2 )
samples_out [ " samples " ] = s1 + s2
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( samples_out )
2023-09-21 22:23:01 -04:00
2025-10-09 09:14:00 +03:00
class LatentSubtract ( io . ComfyNode ) :
2023-09-21 22:23:01 -04:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentSubtract " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " difference latent " , " remove features " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced " ,
2025-10-09 09:14:00 +03:00
inputs = [
io . Latent . Input ( " samples1 " ) ,
io . Latent . Input ( " samples2 " ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
2023-09-21 22:23:01 -04:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , samples1 , samples2 ) - > io . NodeOutput :
2023-09-21 22:23:01 -04:00
samples_out = samples1 . copy ( )
s1 = samples1 [ " samples " ]
s2 = samples2 [ " samples " ]
s2 = reshape_latent_to ( s1 . shape , s2 )
samples_out [ " samples " ] = s1 - s2
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( samples_out )
2023-09-21 22:23:01 -04:00
2025-10-09 09:14:00 +03:00
class LatentMultiply ( io . ComfyNode ) :
2023-09-21 22:23:01 -04:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentMultiply " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " scale latent " , " amplify latent " , " latent gain " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced " ,
2025-10-09 09:14:00 +03:00
inputs = [
io . Latent . Input ( " samples " ) ,
io . Float . Input ( " multiplier " , default = 1.0 , min = - 10.0 , max = 10.0 , step = 0.01 ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
2023-09-21 22:23:01 -04:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , samples , multiplier ) - > io . NodeOutput :
2023-09-21 22:23:01 -04:00
samples_out = samples . copy ( )
s1 = samples [ " samples " ]
samples_out [ " samples " ] = s1 * multiplier
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( samples_out )
2023-09-21 22:23:01 -04:00
2025-10-09 09:14:00 +03:00
class LatentInterpolate ( io . ComfyNode ) :
2023-11-20 03:55:51 -05:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentInterpolate " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " blend latent " , " mix latent " , " lerp latent " , " transition " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced " ,
2025-10-09 09:14:00 +03:00
inputs = [
io . Latent . Input ( " samples1 " ) ,
io . Latent . Input ( " samples2 " ) ,
io . Float . Input ( " ratio " , default = 1.0 , min = 0.0 , max = 1.0 , step = 0.01 ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
2023-11-20 03:55:51 -05:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , samples1 , samples2 , ratio ) - > io . NodeOutput :
2023-11-20 03:55:51 -05:00
samples_out = samples1 . copy ( )
s1 = samples1 [ " samples " ]
s2 = samples2 [ " samples " ]
s2 = reshape_latent_to ( s1 . shape , s2 )
m1 = torch . linalg . vector_norm ( s1 , dim = ( 1 ) )
m2 = torch . linalg . vector_norm ( s2 , dim = ( 1 ) )
s1 = torch . nan_to_num ( s1 / m1 )
s2 = torch . nan_to_num ( s2 / m2 )
t = ( s1 * ratio + s2 * ( 1.0 - ratio ) )
mt = torch . linalg . vector_norm ( t , dim = ( 1 ) )
st = torch . nan_to_num ( t / mt )
samples_out [ " samples " ] = st * ( m1 * ratio + m2 * ( 1.0 - ratio ) )
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( samples_out )
2023-11-20 03:55:51 -05:00
2025-10-09 09:14:00 +03:00
class LatentConcat ( io . ComfyNode ) :
2025-08-27 19:28:10 -07:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentConcat " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " join latents " , " stitch latents " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced " ,
2025-10-09 09:14:00 +03:00
inputs = [
io . Latent . Input ( " samples1 " ) ,
io . Latent . Input ( " samples2 " ) ,
io . Combo . Input ( " dim " , options = [ " x " , " -x " , " y " , " -y " , " t " , " -t " ] ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
2025-08-27 19:28:10 -07:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , samples1 , samples2 , dim ) - > io . NodeOutput :
2025-08-27 19:28:10 -07:00
samples_out = samples1 . copy ( )
s1 = samples1 [ " samples " ]
s2 = samples2 [ " samples " ]
s2 = comfy . utils . repeat_to_batch_size ( s2 , s1 . shape [ 0 ] )
if " - " in dim :
c = ( s2 , s1 )
else :
c = ( s1 , s2 )
if " x " in dim :
dim = - 1
elif " y " in dim :
dim = - 2
elif " t " in dim :
dim = - 3
samples_out [ " samples " ] = torch . cat ( c , dim = dim )
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( samples_out )
2025-08-27 19:28:10 -07:00
2025-10-09 09:14:00 +03:00
class LatentCut ( io . ComfyNode ) :
2025-08-28 16:38:28 -07:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentCut " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " crop latent " , " slice latent " , " extract region " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced " ,
2025-10-09 09:14:00 +03:00
inputs = [
io . Latent . Input ( " samples " ) ,
io . Combo . Input ( " dim " , options = [ " x " , " y " , " t " ] ) ,
io . Int . Input ( " index " , default = 0 , min = - nodes . MAX_RESOLUTION , max = nodes . MAX_RESOLUTION , step = 1 ) ,
io . Int . Input ( " amount " , default = 1 , min = 1 , max = nodes . MAX_RESOLUTION , step = 1 ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
2025-08-28 16:38:28 -07:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , samples , dim , index , amount ) - > io . NodeOutput :
2025-08-28 16:38:28 -07:00
samples_out = samples . copy ( )
s1 = samples [ " samples " ]
if " x " in dim :
dim = s1 . ndim - 1
elif " y " in dim :
dim = s1 . ndim - 2
elif " t " in dim :
dim = s1 . ndim - 3
if index > = 0 :
index = min ( index , s1 . shape [ dim ] - 1 )
amount = min ( s1 . shape [ dim ] - index , amount )
else :
index = max ( index , - s1 . shape [ dim ] )
amount = min ( - index , amount )
samples_out [ " samples " ] = torch . narrow ( s1 , dim , index , amount )
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( samples_out )
2025-08-28 16:38:28 -07:00
2025-12-18 19:21:40 -08:00
class LatentCutToBatch ( io . ComfyNode ) :
@classmethod
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentCutToBatch " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " slice to batch " , " split latent " , " tile latent " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced " ,
2025-12-18 19:21:40 -08:00
inputs = [
io . Latent . Input ( " samples " ) ,
io . Combo . Input ( " dim " , options = [ " t " , " x " , " y " ] ) ,
io . Int . Input ( " slice_size " , default = 1 , min = 1 , max = nodes . MAX_RESOLUTION , step = 1 ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
@classmethod
def execute ( cls , samples , dim , slice_size ) - > io . NodeOutput :
samples_out = samples . copy ( )
s1 = samples [ " samples " ]
if " x " in dim :
dim = s1 . ndim - 1
elif " y " in dim :
dim = s1 . ndim - 2
elif " t " in dim :
dim = s1 . ndim - 3
if dim < 2 :
return io . NodeOutput ( samples )
s = s1 . movedim ( dim , 1 )
if s . shape [ 1 ] < slice_size :
slice_size = s . shape [ 1 ]
elif s . shape [ 1 ] % slice_size != 0 :
s = s [ : , : math . floor ( s . shape [ 1 ] / slice_size ) * slice_size ]
new_shape = [ - 1 , slice_size ] + list ( s . shape [ 2 : ] )
samples_out [ " samples " ] = s . reshape ( new_shape ) . movedim ( 1 , dim )
return io . NodeOutput ( samples_out )
2025-10-09 09:14:00 +03:00
class LatentBatch ( io . ComfyNode ) :
2023-12-16 01:21:00 -05:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentBatch " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " combine latents " , " merge latents " , " join latents " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/batch " ,
V3 Improvements + DynamicCombo + Autogrow exposed in public API (#11345)
* Support Combo outputs in a more sane way
* Remove test validate_inputs function on test node
* Make curr_prefix be a list of strings instead of string for easier parsing as keys get added to dynamic types
* Start to account for id prefixes from frontend, need to fix bug with nested dynamics
* Ensure inputs/outputs/hidden are lists in schema finalize function, remove no longer needed 'is not None' checks
* Add raw_link and extra_dict to all relevant Inputs
* Make nested DynamicCombos work properly with prefixed keys on latest frontend; breaks old Autogrow, but is pretty much ready for upcoming Autogrow keys
* Replace ... usage with a MISSING sentinel for clarity in nodes_logic.py
* Added CustomCombo node in backend to reflect frontend node
* Prepare Autogrow's expand_schema_for_dynamic to work with upcoming frontend changes
* Prepare for look up table for dynamic input stuff
* More progress towards dynamic input lookup function stuff
* Finished converting _expand_schema_for_dynamic to be done via lookup instead of OOP to guarantee working with process isolation, did refactoring to remove old implementation + cleaning INPUT_TYPES definition including v3 hidden definition
* Change order of functions
* Removed some unneeded functions after dynamic refactor
* Make MatchType's output default displayname "MATCHTYPE"
* Fix DynamicSlot get_all
* Removed redundant code - dynamic stuff no longer happens in OOP way
* Natively support AnyType (*) without __ne__ hacks
* Remove stray code that made it in
* Remove expand_schema_for_dynamic left over on DynamicInput class
* get_dynamic() on DynamicInput/Output was not doing anything anymore, so removed it
* Make validate_inputs validate combo input correctly
* Temporarily comment out conversion to 'new' (9 month old) COMBO format in get_input_info
* Remove refrences to resources feature scrapped from V3
* Expose DynamicCombo in public API
* satisfy ruff after some code got commented out
* Make missing input error prettier for dynamic types
* Created a Switch2 node as a side-by-side test, will likely go with Switch2 as the initial switch node
* Figured out Switch situation
* Pass in v3_data in IsChangedCache.get function's fingerprint_inputs, add a from_v3_data helper method to HiddenHolder
* Switch order of Switch and Soft Switch nodes in file
* Temp test node for MatchType
* Fix missing v3_data for v1 nodes in validation
* For now, remove chacking duplicate id's for dynamic types
* Add Resize Image/Mask node that thanks to MatchType+DynamicCombo is 16-nodes-in-1
* Made DynamicCombo references in DCTestNode use public interface
* Add an AnyTypeTestNode
* Make lazy status for specific inputs on DynamicInputs work by having the values of the dictionary for check_lazy_status be a tuple, where the second element is the key of the input that can be returned
* Comment out test logic nodes
* Make primitive float's step make more sense
* Add (and leave commented out) some potential logic nodes
* Change default crop option to "center" on Resize Image/Mask node
* Changed copy.copy(d) to d.copy()
* Autogrow is available in stable frontend, so exposing it in public API
* Use outputs id as display_name if no display_name present, remove v3 outputs id restriction that made them have to have unique IDs from the inputs
* Enable Custom Combo node as stable frontend now supports it
* Make id properly act like display_name on outputs
* Add Batch Images/Masks/Latents node
* Comment out Batch Images/Masks/Latents node for now, as Autogrow has a bug with MatchType where top connection is disconnected upon refresh
* Removed code for a couple test nodes in nodes_logic.py
* Add Batch Images, Batch Masks, and Batch Latents nodes with Autogrow, deprecate old Batch Images + LatentBatch nodes
2025-12-30 20:09:55 -08:00
is_deprecated = True ,
2025-10-09 09:14:00 +03:00
inputs = [
io . Latent . Input ( " samples1 " ) ,
io . Latent . Input ( " samples2 " ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
2023-12-16 01:21:00 -05:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , samples1 , samples2 ) - > io . NodeOutput :
2023-12-16 01:21:00 -05:00
samples_out = samples1 . copy ( )
s1 = samples1 [ " samples " ]
s2 = samples2 [ " samples " ]
2025-01-22 06:37:46 -05:00
s2 = reshape_latent_to ( s1 . shape , s2 , repeat_batch = False )
2023-12-16 01:21:00 -05:00
s = torch . cat ( ( s1 , s2 ) , dim = 0 )
samples_out [ " samples " ] = s
samples_out [ " batch_index " ] = samples1 . get ( " batch_index " , [ x for x in range ( 0 , s1 . shape [ 0 ] ) ] ) + samples2 . get ( " batch_index " , [ x for x in range ( 0 , s2 . shape [ 0 ] ) ] )
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( samples_out )
2023-12-16 01:21:00 -05:00
2025-10-09 09:14:00 +03:00
class LatentBatchSeedBehavior ( io . ComfyNode ) :
2024-01-26 23:13:02 -05:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentBatchSeedBehavior " ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced " ,
2025-10-09 09:14:00 +03:00
inputs = [
io . Latent . Input ( " samples " ) ,
io . Combo . Input ( " seed_behavior " , options = [ " random " , " fixed " ] , default = " fixed " ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
2024-01-26 23:13:02 -05:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , samples , seed_behavior ) - > io . NodeOutput :
2024-01-26 23:13:02 -05:00
samples_out = samples . copy ( )
latent = samples [ " samples " ]
if seed_behavior == " random " :
if ' batch_index ' in samples_out :
samples_out . pop ( ' batch_index ' )
elif seed_behavior == " fixed " :
batch_number = samples_out . get ( " batch_index " , [ 0 ] ) [ 0 ]
samples_out [ " batch_index " ] = [ batch_number ] * latent . shape [ 0 ]
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( samples_out )
2024-01-26 23:13:02 -05:00
2025-10-09 09:14:00 +03:00
class LatentApplyOperation ( io . ComfyNode ) :
2024-10-15 15:00:36 -04:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentApplyOperation " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " transform latent " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced/operations " ,
2025-10-09 09:14:00 +03:00
is_experimental = True ,
inputs = [
io . Latent . Input ( " samples " ) ,
io . LatentOperation . Input ( " operation " ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
2024-10-15 15:00:36 -04:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , samples , operation ) - > io . NodeOutput :
2024-10-15 15:00:36 -04:00
samples_out = samples . copy ( )
s1 = samples [ " samples " ]
samples_out [ " samples " ] = operation ( latent = s1 )
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( samples_out )
2024-10-15 15:00:36 -04:00
2025-10-09 09:14:00 +03:00
class LatentApplyOperationCFG ( io . ComfyNode ) :
2024-10-15 15:00:36 -04:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentApplyOperationCFG " ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced/operations " ,
2025-10-09 09:14:00 +03:00
is_experimental = True ,
inputs = [
io . Model . Input ( " model " ) ,
io . LatentOperation . Input ( " operation " ) ,
] ,
outputs = [
io . Model . Output ( ) ,
] ,
)
2024-10-15 15:00:36 -04:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , model , operation ) - > io . NodeOutput :
2024-10-15 15:00:36 -04:00
m = model . clone ( )
def pre_cfg_function ( args ) :
conds_out = args [ " conds_out " ]
if len ( conds_out ) == 2 :
conds_out [ 0 ] = operation ( latent = ( conds_out [ 0 ] - conds_out [ 1 ] ) ) + conds_out [ 1 ]
else :
conds_out [ 0 ] = operation ( latent = conds_out [ 0 ] )
return conds_out
m . set_model_sampler_pre_cfg_function ( pre_cfg_function )
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( m )
2024-10-15 15:00:36 -04:00
2025-10-09 09:14:00 +03:00
class LatentOperationTonemapReinhard ( io . ComfyNode ) :
2024-10-15 15:00:36 -04:00
@classmethod
2025-10-09 09:14:00 +03:00
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentOperationTonemapReinhard " ,
add search aliases to all nodes (#12035)
* feat: Add search_aliases field to node schema
Adds `search_aliases` field to improve node discoverability. Users can define alternative search terms for nodes (e.g., "text concat" → StringConcatenate).
Changes:
- Add `search_aliases: list[str]` to V3 Schema
- Add `SEARCH_ALIASES` support for V1 nodes
- Include field in `/object_info` response
- Add aliases to high-priority core nodes
V1 usage:
```python
class MyNode:
SEARCH_ALIASES = ["alt name", "synonym"]
```
V3 usage:
```python
io.Schema(
node_id="MyNode",
search_aliases=["alt name", "synonym"],
...
)
```
## Related PRs
- Frontend: Comfy-Org/ComfyUI_frontend#XXXX (draft - merge after this)
- Docs: Comfy-Org/docs#XXXX (draft - merge after stable)
* Propagate search_aliases through V3 Schema.get_v1_info to NodeInfoV1
* feat: add SEARCH_ALIASES for core nodes (#12016)
Add search aliases to 22 core nodes in nodes.py to improve node discoverability:
- Checkpoint/model loaders: CheckpointLoader, DiffusersLoader
- Conditioning nodes: ConditioningAverage, ConditioningSetArea, ConditioningSetMask, ConditioningZeroOut
- Style nodes: StyleModelApply
- Image nodes: LoadImageMask, LoadImageOutput, ImageBatch, ImageInvert, ImagePadForOutpaint
- Latent nodes: LoadLatent, SaveLatent, LatentBlend, LatentComposite, LatentCrop, LatentFlip, LatentFromBatch, LatentUpscale, LatentUpscaleBy, RepeatLatentBatch
* feat: add SEARCH_ALIASES for image, mask, and string nodes (#12017)
Add search aliases to nodes in comfy_extras for better discoverability:
- nodes_mask.py: mask manipulation nodes
- nodes_images.py: image processing nodes
- nodes_post_processing.py: post-processing effect nodes
- nodes_string.py: string manipulation nodes
- nodes_compositing.py: compositing nodes
- nodes_morphology.py: morphological operation nodes
- nodes_latent.py: latent space nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for audio and video nodes (#12018)
Add search aliases to audio and video nodes for better discoverability:
- nodes_audio.py: audio loading, saving, and processing nodes
- nodes_video.py: video loading and processing nodes
- nodes_wan.py: WAN model nodes
Uses search_aliases parameter in io.Schema() for v3 nodes.
* feat: add SEARCH_ALIASES for model and misc nodes (#12019)
Add search aliases to model-related and miscellaneous nodes:
- Model nodes: nodes_model_merging.py, nodes_model_advanced.py, nodes_lora_extract.py
- Sampler nodes: nodes_custom_sampler.py, nodes_align_your_steps.py
- Control nodes: nodes_controlnet.py, nodes_attention_multiply.py, nodes_hooks.py
- Training nodes: nodes_train.py, nodes_dataset.py
- Utility nodes: nodes_logic.py, nodes_canny.py, nodes_differential_diffusion.py
- Architecture-specific: nodes_sd3.py, nodes_pixart.py, nodes_lumina2.py, nodes_kandinsky5.py, nodes_hidream.py, nodes_fresca.py, nodes_hunyuan3d.py
- Media nodes: nodes_load_3d.py, nodes_webcam.py, nodes_preview_any.py, nodes_wanmove.py
Uses search_aliases parameter in io.Schema() for v3 nodes, SEARCH_ALIASES class attribute for legacy nodes.
2026-01-22 18:36:58 -08:00
search_aliases = [ " hdr latent " ] ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced/operations " ,
2025-10-09 09:14:00 +03:00
is_experimental = True ,
inputs = [
io . Float . Input ( " multiplier " , default = 1.0 , min = 0.0 , max = 100.0 , step = 0.01 ) ,
] ,
outputs = [
io . LatentOperation . Output ( ) ,
] ,
)
2024-10-15 15:00:36 -04:00
2025-10-09 09:14:00 +03:00
@classmethod
def execute ( cls , multiplier ) - > io . NodeOutput :
2024-10-15 15:00:36 -04:00
def tonemap_reinhard ( latent , * * kwargs ) :
latent_vector_magnitude = ( torch . linalg . vector_norm ( latent , dim = ( 1 ) ) + 0.0000000001 ) [ : , None ]
normalized_latent = latent / latent_vector_magnitude
2026-02-08 18:16:40 -08:00
dims = list ( range ( 1 , latent_vector_magnitude . ndim ) )
mean = torch . mean ( latent_vector_magnitude , dim = dims , keepdim = True )
std = torch . std ( latent_vector_magnitude , dim = dims , keepdim = True )
2024-10-15 15:00:36 -04:00
top = ( std * 5 + mean ) * multiplier
#reinhard
latent_vector_magnitude * = ( 1.0 / top )
new_magnitude = latent_vector_magnitude / ( latent_vector_magnitude + 1.0 )
new_magnitude * = top
return normalized_latent * new_magnitude
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( tonemap_reinhard )
class LatentOperationSharpen ( io . ComfyNode ) :
@classmethod
def define_schema ( cls ) :
return io . Schema (
node_id = " LatentOperationSharpen " ,
2026-05-27 17:43:33 -07:00
category = " model/latent/advanced/operations " ,
2025-10-09 09:14:00 +03:00
is_experimental = True ,
inputs = [
feat: mark 429 widgets as advanced for collapsible UI (#12197)
* feat: mark 429 widgets as advanced for collapsible UI
Mark widgets as advanced across core, comfy_extras, and comfy_api_nodes
to support the new collapsible advanced inputs section in the frontend.
Changes:
- 267 advanced markers in comfy_extras/
- 162 advanced markers in comfy_api_nodes/
- All files pass python3 -m py_compile verification
Widgets marked advanced (hidden by default):
- Scheduler internals: sigma_max, sigma_min, rho, mu, beta, alpha
- Sampler internals: eta, s_noise, order, rtol, atol, h_init, pcoeff, etc.
- Memory optimization: tile_size, overlap, temporal_size, temporal_overlap
- Pipeline controls: add_noise, start_at_step, end_at_step
- Timing controls: start_percent, end_percent
- Layer selection: stop_at_clip_layer, layers, block_number
- Video encoding: codec, crf, format
- Device/dtype: device, noise_device, dtype, weight_dtype
Widgets kept basic (always visible):
- Core params: strength, steps, cfg, denoise, seed, width, height
- Model selectors: ckpt_name, lora_name, vae_name, sampler_name
- Common controls: upscale_method, crop, batch_size, fps, opacity
Related: frontend PR #11939
Amp-Thread-ID: https://ampcode.com/threads/T-019c1734-6b61-702e-b333-f02c399963fc
* fix: remove advanced=True from DynamicCombo.Input (unsupported)
Amp-Thread-ID: https://ampcode.com/threads/T-019c1734-6b61-702e-b333-f02c399963fc
* fix: address review - un-mark model merge, video, image, and training node widgets as advanced
Per comfyanonymous review:
- Model merge arguments should not be advanced (all 14 model-specific merge classes)
- SaveAnimatedWEBP lossless/quality/method should not be advanced
- SaveWEBM/SaveVideo codec/crf/format should not be advanced
- TrainLoraNode options should not be advanced (7 inputs)
Amp-Thread-ID: https://ampcode.com/threads/T-019c322b-a3a8-71b7-9962-d44573ca6352
* fix: un-mark batch_size and webcam width/height as advanced (should stay basic)
Amp-Thread-ID: https://ampcode.com/threads/T-019c3236-1417-74aa-82a3-bcb365fbe9d1
---------
Co-authored-by: Jedrzej Kosinski <kosinkadink1@gmail.com>
2026-02-19 19:20:02 -08:00
io . Int . Input ( " sharpen_radius " , default = 9 , min = 1 , max = 31 , step = 1 , advanced = True ) ,
io . Float . Input ( " sigma " , default = 1.0 , min = 0.1 , max = 10.0 , step = 0.1 , advanced = True ) ,
io . Float . Input ( " alpha " , default = 0.1 , min = 0.0 , max = 5.0 , step = 0.01 , advanced = True ) ,
2025-10-09 09:14:00 +03:00
] ,
outputs = [
io . LatentOperation . Output ( ) ,
] ,
)
2024-10-15 15:00:36 -04:00
2024-10-16 05:25:31 -04:00
@classmethod
2025-10-09 09:14:00 +03:00
def execute ( cls , sharpen_radius , sigma , alpha ) - > io . NodeOutput :
2024-10-16 05:25:31 -04:00
def sharpen ( latent , * * kwargs ) :
luminance = ( torch . linalg . vector_norm ( latent , dim = ( 1 ) ) + 1e-6 ) [ : , None ]
normalized_latent = latent / luminance
channels = latent . shape [ 1 ]
kernel_size = sharpen_radius * 2 + 1
kernel = comfy_extras . nodes_post_processing . gaussian_kernel ( kernel_size , sigma , device = luminance . device )
center = kernel_size / / 2
kernel * = alpha * - 10
kernel [ center , center ] = kernel [ center , center ] - kernel . sum ( ) + 1.0
padded_image = torch . nn . functional . pad ( normalized_latent , ( sharpen_radius , sharpen_radius , sharpen_radius , sharpen_radius ) , ' reflect ' )
sharpened = torch . nn . functional . conv2d ( padded_image , kernel . repeat ( channels , 1 , 1 ) . unsqueeze ( 1 ) , padding = kernel_size / / 2 , groups = channels ) [ : , : , sharpen_radius : - sharpen_radius , sharpen_radius : - sharpen_radius ]
return luminance * sharpened
2025-10-09 09:14:00 +03:00
return io . NodeOutput ( sharpen )
2025-12-06 05:20:22 +02:00
class ReplaceVideoLatentFrames ( io . ComfyNode ) :
@classmethod
def define_schema ( cls ) :
return io . Schema (
node_id = " ReplaceVideoLatentFrames " ,
2026-05-27 17:43:33 -07:00
category = " model/latent/batch " ,
2025-12-06 05:20:22 +02:00
inputs = [
io . Latent . Input ( " destination " , tooltip = " The destination latent where frames will be replaced. " ) ,
io . Latent . Input ( " source " , optional = True , tooltip = " The source latent providing frames to insert into the destination latent. If not provided, the destination latent is returned unchanged. " ) ,
io . Int . Input ( " index " , default = 0 , min = - nodes . MAX_RESOLUTION , max = nodes . MAX_RESOLUTION , step = 1 , tooltip = " The starting latent frame index in the destination latent where the source latent frames will be placed. Negative values count from the end. " ) ,
] ,
outputs = [
io . Latent . Output ( ) ,
] ,
)
@classmethod
def execute ( cls , destination , index , source = None ) - > io . NodeOutput :
if source is None :
return io . NodeOutput ( destination )
dest_frames = destination [ " samples " ] . shape [ 2 ]
source_frames = source [ " samples " ] . shape [ 2 ]
if index < 0 :
index = dest_frames + index
if index > dest_frames :
logging . warning ( f " ReplaceVideoLatentFrames: Index { index } is out of bounds for destination latent frames { dest_frames } . " )
return io . NodeOutput ( destination )
if index + source_frames > dest_frames :
logging . warning ( f " ReplaceVideoLatentFrames: Source latent frames { source_frames } do not fit within destination latent frames { dest_frames } at the specified index { index } . " )
return io . NodeOutput ( destination )
s = source . copy ( )
s_source = source [ " samples " ]
s_destination = destination [ " samples " ] . clone ( )
s_destination [ : , : , index : index + s_source . shape [ 2 ] ] = s_source
s [ " samples " ] = s_destination
return io . NodeOutput ( s )
2025-10-09 09:14:00 +03:00
class LatentExtension ( ComfyExtension ) :
@override
async def get_node_list ( self ) - > list [ type [ io . ComfyNode ] ] :
return [
LatentAdd ,
LatentSubtract ,
LatentMultiply ,
LatentInterpolate ,
LatentConcat ,
LatentCut ,
2025-12-18 19:21:40 -08:00
LatentCutToBatch ,
2025-10-09 09:14:00 +03:00
LatentBatch ,
LatentBatchSeedBehavior ,
LatentApplyOperation ,
LatentApplyOperationCFG ,
LatentOperationTonemapReinhard ,
LatentOperationSharpen ,
2025-12-06 05:20:22 +02:00
ReplaceVideoLatentFrames
2025-10-09 09:14:00 +03:00
]
async def comfy_entrypoint ( ) - > LatentExtension :
return LatentExtension ( )