feat: unify and improve tooltip documentation across CLI and ComfyUI nodes

- Standardize tooltip format with multi-line descriptions and bullet points
- Add comprehensive output tooltips for all nodes (DiT, VAE, torch.compile, upscaler)
- Enhance node descriptions with detailed capability summaries
- Simplify CLI tile size arguments to single integers (converted internally to tuples)
- Remove OneOrTwoValues argparse class for cleaner implementation
- Fix encode_tiled tooltip (was incorrectly referencing decoding)
- Clarify color correction purpose (corrects upscaling color shifts)
- Add multi-GPU offloading information to all offload_device tooltips
- Improve torch.compile parameter descriptions with use cases
- Ensure CLI and ComfyUI tooltips are consistent in terminology and structure
This commit is contained in:
Adrien Toupet
2025-11-05 15:35:22 -05:00
parent 326489d94c
commit 806bb94df0
6 changed files with 263 additions and 137 deletions
+34 -76
View File
@@ -703,11 +703,11 @@ def _process_frames_core(
'offload_device': dit_offload,
},
encode_tiled=args.vae_encode_tiling_enabled,
encode_tile_size=args.vae_encode_tile_size,
encode_tile_overlap=args.vae_encode_tile_overlap,
encode_tile_size=(args.vae_encode_tile_size, args.vae_encode_tile_size),
encode_tile_overlap=(args.vae_encode_tile_overlap, args.vae_encode_tile_overlap),
decode_tiled=args.vae_decode_tiling_enabled,
decode_tile_size=args.vae_decode_tile_size,
decode_tile_overlap=args.vae_decode_tile_overlap,
decode_tile_size=(args.vae_decode_tile_size, args.vae_decode_tile_size),
decode_tile_overlap=(args.vae_decode_tile_overlap, args.vae_decode_tile_overlap),
tile_debug=args.tile_debug.lower() if args.tile_debug else "false",
attention_mode=args.attention_mode,
torch_compile_args_dit=torch_compile_args_dit,
@@ -980,53 +980,12 @@ def _gpu_processing(
# Argument Parsing
# =============================================================================
class OneOrTwoValues(argparse.Action):
"""
Custom argparse action for tile size arguments accepting 1 or 2 integers.
Allows flexible input formats:
- Single integer: --tile_size 1024 → (1024, 1024)
- Two integers: --tile_size 1024 768 → (1024, 768)
- Comma-separated: --tile_size 1024,768 → (1024, 768)
Used for VAE tiling parameters where height and width can be specified
separately or as a single value applied to both dimensions.
"""
def __call__(
self,
parser: argparse.ArgumentParser,
namespace: argparse.Namespace,
values: List[str],
option_string: Optional[str] = None
) -> None:
"""Parse and validate tile size arguments."""
if len(values) not in [1, 2]:
parser.error(f"{option_string} requires 1 or 2 arguments")
if len(values) == 1:
values = values[0]
if ',' in values:
values = [v.strip() for v in values.split(',') if v.strip()]
else:
values = values.split()
try:
result = tuple(int(v) for v in values)
if len(result) == 1:
result = (result[0], result[0]) # Convert single value to (h, w)
setattr(namespace, self.dest, result)
except ValueError:
parser.error(f"{option_string} arguments must be integers")
def parse_arguments() -> argparse.Namespace:
"""
Parse and validate command-line arguments for SeedVR2 CLI.
Configures all available options including model selection, processing parameters,
memory optimization settings, and output configuration. Uses custom action classes
for complex argument types (e.g., OneOrTwoValues for tile sizes).
memory optimization settings, and output configuration.
Returns:
Parsed arguments namespace with all CLI parameters
@@ -1034,7 +993,6 @@ def parse_arguments() -> argparse.Namespace:
Note:
- cuda_device argument only available on non-macOS systems
- Default model directory resolves to "models/SEEDVR2" if not specified
- Tile size/overlap arguments use OneOrTwoValues for flexible input
"""
# Multi-line usage examples for --help
@@ -1107,13 +1065,13 @@ Examples:
quality_group = parser.add_argument_group('Quality control')
quality_group.add_argument("--color_correction", type=str, default="lab",
choices=["lab", "wavelet", "wavelet_adaptive", "hsv", "adain", "none"],
help="Color correction: 'lab' (best, perceptual matching), 'wavelet' (natural, preserves detail), "
"'wavelet_adaptive' (adaptive saturation), 'hsv' (hue-conditional), 'adain' (style transfer), "
"'none' (no correction). Default: lab")
help="Color correction method: 'lab' (perceptual color matching, recommended), 'wavelet' (frequency-based), "
"'wavelet_adaptive' (wavelet + saturation correction), 'hsv' (hue-conditional), 'adain' (statistical transfer), "
"'none' (disabled) (default: lab)")
quality_group.add_argument("--input_noise_scale", type=float, default=0.0,
help="Input noise (0.0-1.0) to add variation to input (default: 0.0)")
help="Input noise injection scale (0.0-1.0). Adds variation to input images (default: 0.0)")
quality_group.add_argument("--latent_noise_scale", type=float, default=0.0,
help="Latent noise (0.0-1.0) during diffusion. Can soften details (default: 0.0)")
help="Latent noise injection scale (0.0-1.0). Adds variation to latent space (default: 0.0)")
# Device Management
device_group = parser.add_argument_group('Device management')
@@ -1140,16 +1098,16 @@ Examples:
vae_group = parser.add_argument_group('VAE tiling (for high resolution upscale)')
vae_group.add_argument("--vae_encode_tiling_enabled", action="store_true",
help="Enable VAE encode tiling to reduce VRAM during encoding")
vae_group.add_argument("--vae_encode_tile_size", action=OneOrTwoValues, nargs='+', default=(1024, 1024),
help="Encode tile size in pixels (height width or single value). Default: 1024")
vae_group.add_argument("--vae_encode_tile_overlap", action=OneOrTwoValues, nargs='+', default=(128, 128),
help="Encode tile overlap in pixels. Higher = better blending. Default: 128")
vae_group.add_argument("--vae_encode_tile_size", type=int, default=1024,
help="VAE encode tile size in pixels (default: 1024). Applied to both height and width. Only used if --vae_encode_tiling_enabled is set")
vae_group.add_argument("--vae_encode_tile_overlap", type=int, default=128,
help="VAE encode tile overlap in pixels (default: 128). Reduces visible seams between tiles. Only used if --vae_encode_tiling_enabled is set")
vae_group.add_argument("--vae_decode_tiling_enabled", action="store_true",
help="Enable VAE decode tiling to reduce VRAM during decoding (recommended for 4K+)")
vae_group.add_argument("--vae_decode_tile_size", action=OneOrTwoValues, nargs='+', default=(1024, 1024),
help="Decode tile size in pixels (height width or single value). Default: 1024")
vae_group.add_argument("--vae_decode_tile_overlap", action=OneOrTwoValues, nargs='+', default=(128, 128),
help="Decode tile overlap in pixels. Higher = better blending. Default: 128")
help="Enable VAE decode tiling to reduce VRAM during decoding")
vae_group.add_argument("--vae_decode_tile_size", type=int, default=1024,
help="VAE decode tile size in pixels (default: 1024). Applied to both height and width. Only used if --vae_decode_tiling_enabled is set")
vae_group.add_argument("--vae_decode_tile_overlap", type=int, default=128,
help="VAE decode tile overlap in pixels (default: 128). Reduces visible seams between tiles. Only used if --vae_decode_tiling_enabled is set")
vae_group.add_argument("--tile_debug", type=str, default="false", choices=["false", "encode", "decode"],
help="Visualize tiles: 'false' (default), 'encode', or 'decode'")
@@ -1158,23 +1116,23 @@ Examples:
perf_group.add_argument("--attention_mode", type=str, default="sdpa",
choices=["sdpa", "flash_attn"],
help="Attention backend: 'sdpa' (default, always available) or 'flash_attn' (faster, requires package)")
perf_group.add_argument("--compile_dit", action="store_true",
help="Enable torch.compile for DiT (20-40%% speedup, slower first run)")
perf_group.add_argument("--compile_dit", action="store_true",
help="Enable torch.compile for DiT model (20-40%% speedup, requires PyTorch 2.0+ and Triton)")
perf_group.add_argument("--compile_vae", action="store_true",
help="Enable torch.compile for VAE (15-25%% speedup, slower first run)")
help="Enable torch.compile for VAE model (15-25%% speedup, requires PyTorch 2.0+ and Triton)")
perf_group.add_argument("--compile_backend", type=str, default="inductor", choices=["inductor", "cudagraphs"],
help="Compile backend (default: inductor)")
perf_group.add_argument("--compile_mode", type=str, default="default",
choices=["default", "reduce-overhead", "max-autotune", "max-autotune-no-cudagraphs"],
help="Compile mode (default: default)")
help="Compilation backend: 'inductor' (full optimization with Triton) or 'cudagraphs' (lightweight, no kernel optimization) (default: inductor)")
perf_group.add_argument("--compile_mode", type=str, default="default", choices=["default", "reduce-overhead", "max-autotune", "max-autotune-no-cudagraphs"],
help="Optimization level: 'default' (fast compilation), 'reduce-overhead' (lower overhead), 'max-autotune' (best runtime, slow compilation), "
"'max-autotune-no-cudagraphs' (like max-autotune without cudagraphs) (default: default)")
perf_group.add_argument("--compile_fullgraph", action="store_true",
help="Force single graph compilation (max optimization, may fail)")
help="Compile entire model as single graph (faster but less flexible). May fail with dynamic shapes (default: False)")
perf_group.add_argument("--compile_dynamic", action="store_true",
help="Handle dynamic input shapes (slower but more flexible)")
help="Handle varying input shapes without recompilation. Useful for different resolutions/batch sizes (default: False)")
perf_group.add_argument("--compile_dynamo_cache_size_limit", type=int, default=64,
help="Max compiled versions cached per function (default: 64)")
help="Max cached compiled versions per function. Increase when using many different input shapes. Higher uses more memory (default: 64)")
perf_group.add_argument("--compile_dynamo_recompile_limit", type=int, default=128,
help="Max recompile attempts before fallback (default: 128)")
help="Max recompilation attempts before fallback to eager mode. Safety limit to prevent compilation loops (default: 128)")
# Model Caching (for batch processing)
cache_group = parser.add_argument_group('Model caching (batch processing)')
@@ -1232,12 +1190,12 @@ def main() -> None:
for key, value in vars(args).items():
debug.log(f"{key}: {value}", category="none", indent_level=1)
if args.vae_encode_tiling_enabled and (args.vae_encode_tile_overlap[0] >= args.vae_encode_tile_size[0] or args.vae_encode_tile_overlap[1] >= args.vae_encode_tile_size[1]):
debug.log(f"VAE encode tile overlap {args.vae_encode_tile_overlap} must be smaller than tile size {args.vae_encode_tile_size}", level="ERROR", category="vae", force=True)
if args.vae_encode_tiling_enabled and args.vae_encode_tile_overlap >= args.vae_encode_tile_size:
debug.log(f"VAE encode tile overlap ({args.vae_encode_tile_overlap}) must be smaller than tile size ({args.vae_encode_tile_size})", level="ERROR", category="vae", force=True)
sys.exit(1)
if args.vae_decode_tiling_enabled and (args.vae_decode_tile_overlap[0] >= args.vae_decode_tile_size[0] or args.vae_decode_tile_overlap[1] >= args.vae_decode_tile_size[1]):
debug.log(f"VAE decode tile overlap {args.vae_decode_tile_overlap} must be smaller than tile size {args.vae_decode_tile_size}", level="ERROR", category="vae", force=True)
if args.vae_decode_tiling_enabled and args.vae_decode_tile_overlap >= args.vae_decode_tile_size:
debug.log(f"VAE decode tile overlap ({args.vae_decode_tile_overlap}) must be smaller than tile size ({args.vae_decode_tile_size})", level="ERROR", category="vae", force=True)
sys.exit(1)
# Validate BlockSwap configuration - either blocks_to_swap or swap_io_components requires dit_offload_device
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "seedvr2_videoupscaler"
description = "SeedVR2 official ComfyUI integration: ByteDance-Seed's one-step diffusion-based video/image upscaling with memory-efficient inference"
version = "3.0.0"
version = "2.5.0"
authors = [
{name = "numz"},
{name = "adrientoupet"}
+46 -14
View File
@@ -34,19 +34,25 @@ class SeedVR2LoadDiTModel(io.ComfyNode):
display_name="SeedVR2 (Down)Load DiT Model",
category="SEEDVR2",
description=(
"Configure DiT model for SeedVR2 upscaling. Supports BlockSwap for limited VRAM, "
"model caching, and torch.compile optimization. Connect output to SeedVR2 Video Upscaler."
"Load and configure SeedVR2 DiT (Diffusion Transformer) model for video upscaling. "
"Supports BlockSwap memory optimization for low VRAM systems, model caching for batch processing, "
"multi-GPU offloading, and torch.compile acceleration. \n\n"
"Connect to Video Upscaler node."
),
inputs=[
io.Combo.Input("model",
options=dit_models,
default=DEFAULT_DIT,
tooltip="DiT model for upscaling. Models will automatically download on first use. Additional models can be added to the ComfyUI models folder."
tooltip=(
"DiT (Diffusion Transformer) model for video upscaling.\n"
"Models automatically download on first use.\n"
"Additional models can be added to the ComfyUI models folder."
)
),
io.Combo.Input("device",
options=devices,
default=devices[0],
tooltip="Device for DiT inference (upscaling)"
tooltip="GPU/CPU device for DiT model inference (upscaling phase)"
),
io.Int.Input("blocks_to_swap",
default=0,
@@ -54,23 +60,44 @@ class SeedVR2LoadDiTModel(io.ComfyNode):
max=36,
step=1,
optional=True,
tooltip="Number of transformer blocks to swap. Requires offload_device to be set and different from device. 0=disabled. 3B model: 0-32 blocks, 7B model: 0-36 blocks."
tooltip=(
"Number of transformer blocks to swap between devices for VRAM optimization.\n"
"• 0: Disabled (default)\n"
"• 3B model: 0-32 blocks\n"
"• 7B model: 0-36 blocks\n"
"\n"
"Requires offload_device to be set and different from device."
)
),
io.Boolean.Input("swap_io_components",
default=False,
optional=True,
tooltip="Offload input/output embeddings and norm layers. Requires offload_device to be set and different from device."
tooltip=(
"Offload input/output embeddings and normalization layers to reduce VRAM.\n"
"Requires offload_device to be set and different from device."
)
),
io.Combo.Input("offload_device",
options=get_device_list(include_none=True, include_cpu=True),
default="none",
optional=True,
tooltip="Device to offload DiT model to when not in use. Select 'none' to keep on inference device, or 'cpu' for CPU offload (slower but reduces VRAM usage). Required for BlockSwap."
tooltip=(
"Device to offload DiT model when not actively processing.\n"
"• 'none': Keep model on inference device (default, fastest)\n"
"• 'cpu': Offload to system RAM (reduces VRAM usage)\n"
"• 'cuda:X': Offload to another GPU (good balance if available)\n"
"\n"
"Required for BlockSwap (blocks_to_swap or swap_io_components)."
)
),
io.Boolean.Input("cache_model",
default=False,
optional=True,
tooltip="Keep DiT model loaded on offload_device between workflow runs. Useful for batch processing."
tooltip=(
"Keep DiT model loaded on offload_device between workflow runs.\n"
"Useful for batch processing to avoid repeated loading.\n"
"Requires offload_device to be set."
)
),
io.Combo.Input("attention_mode",
options=["sdpa", "flash_attn"],
@@ -78,20 +105,25 @@ class SeedVR2LoadDiTModel(io.ComfyNode):
optional=True,
tooltip=(
"Attention computation backend:\n"
"• sdpa: PyTorch scaled_dot_product_attention (default, always available)\n"
"• flash_attn: Flash Attention 2 (faster, requires flash-attn package)\n"
"• sdpa: PyTorch scaled_dot_product_attention (default, stable, always available)\n"
"• flash_attn: Flash Attention 2 (faster on supported hardware, requires flash-attn package)\n"
"\n"
"SDPA is recommended as the default - it's stable and works everywhere.\n"
"Flash Attention provides speedup on some hardware through optimized CUDA kernels."
"SDPA is recommended - stable and works everywhere.\n"
"Flash Attention provides speedup through optimized CUDA kernels on compatible GPUs."
)
),
io.Custom("TORCH_COMPILE_ARGS").Input("torch_compile_args",
optional=True,
tooltip="Optional torch.compile settings from SeedVR2 Torch Compile Settings node for speedup"
tooltip=(
"Optional torch.compile optimization settings from SeedVR2 Torch Compile Settings node.\n"
"Provides 20-40% speedup with compatible PyTorch 2.0+ and Triton installation."
)
),
],
outputs=[
io.Custom("SEEDVR2_DIT").Output()
io.Custom("SEEDVR2_DIT").Output(
tooltip="DiT model configuration containing model path, device settings, BlockSwap parameters, and compilation options. Connect to Video Upscaler node."
)
]
)
+38 -14
View File
@@ -17,8 +17,9 @@ class SeedVR2TorchCompileSettings(io.ComfyNode):
display_name="SeedVR2 Torch Compile Settings",
category="SEEDVR2",
description=(
"Configure torch.compile optimization for DiT and VAE speedup. "
"Connect to DiT and/or VAE model loader. Requires PyTorch 2.0+ and Triton."
"Configure SeedVR2 torch.compile optimization for 20-40% DiT speedup and 15-25% VAE speedup. "
"Trades longer first-run compilation time for faster inference.\n\n"
"Connect to DiT and/or VAE model loaders. Requires PyTorch 2.0+ and Triton for inductor backend."
),
inputs=[
io.Combo.Input("backend",
@@ -26,46 +27,69 @@ class SeedVR2TorchCompileSettings(io.ComfyNode):
default="inductor",
tooltip=(
"Compilation backend:\n"
"• inductor: Full optimization with Triton kernel generation and fusion\n"
"• cudagraphs: Lightweight, only wraps model with CUDA graphs, no kernel optimization"
"• inductor: Full optimization with Triton kernel generation and fusion (recommended)\n"
"• cudagraphs: Lightweight wrapper using CUDA graphs, no kernel optimization"
)
),
io.Combo.Input("mode",
options=["default", "reduce-overhead", "max-autotune", "max-autotune-no-cudagraphs"],
default="default",
tooltip=(
"Optimization level (compilation time vs runtime speed):\n"
"• default: Fast compilation, good speedup\n"
"• reduce-overhead: Lower overhead, better for smaller models\n"
"• max-autotune: Slowest compilation, best runtime (recommended for production)\n"
"• max-autotune-no-cudagraphs: Like max-autotune but without cudagraphs"
"Optimization level (compilation time vs runtime performance):\n"
"• default: Fast compilation with good speedup (recommended for development)\n"
"• reduce-overhead: Lower overhead, optimized for smaller models\n"
"• max-autotune: Slowest compilation, best runtime performance (recommended for production)\n"
"• max-autotune-no-cudagraphs: Like max-autotune but without CUDA graphs"
)
),
io.Boolean.Input("fullgraph",
default=False,
tooltip="Compile entire model as single graph (faster but less flexible). May fail with dynamic shapes."
tooltip=(
"Compile entire model as single graph without breaks.\n"
"• False: Allow graph breaks for better compatibility (default)\n"
"• True: Enforce no breaks for maximum optimization (may fail with dynamic shapes)"
)
),
io.Boolean.Input("dynamic",
default=False,
tooltip="Handle varying input shapes without recompilation. Useful for different resolutions/batch sizes."
tooltip=(
"Handle varying input shapes without recompilation.\n"
"• False: Specialize for exact input shapes (default)\n"
"• True: Create dynamic kernels that adapt to shape variations\n"
"\n"
"Enable when processing different resolutions or batch sizes."
)
),
io.Int.Input("dynamo_cache_size_limit",
default=64,
min=0,
max=1024,
step=1,
tooltip="Maximum cached compiled versions per function. Increase if using many different input shapes."
tooltip=(
"Maximum cached compiled versions per function (default: 64).\n"
"Controls how many shape variations to compile before stopping.\n"
"\n"
"• Increase: When processing many different input shapes (more memory usage)\n"
"• Decrease: When recompilation cost outweighs benefits (faster fallback to eager)"
)
),
io.Int.Input("dynamo_recompile_limit",
default=128,
min=0,
max=1024,
step=1,
tooltip="Maximum recompilation attempts before fallback to eager mode. Only increase if you see recompile_limit warnings"
tooltip=(
"Maximum recompilation attempts before fallback to eager mode (default: 128).\n"
"Safety limit to prevent infinite compilation loops.\n"
"\n"
"Only increase if you see 'hit config.recompile_limit' warnings and have bounded shape variations."
)
),
],
outputs=[
io.Custom("TORCH_COMPILE_ARGS").Output()
io.Custom("TORCH_COMPILE_ARGS").Output(
tooltip="torch.compile optimization settings including backend, mode, and Dynamo configuration. Connect to DiT and/or VAE model loader nodes."
)
]
)
+62 -15
View File
@@ -35,82 +35,129 @@ class SeedVR2LoadVAEModel(io.ComfyNode):
display_name="SeedVR2 (Down)Load VAE Model",
category="SEEDVR2",
description=(
"Configure VAE model for SeedVR2 encoding/decoding. Supports tiled processing for VRAM reduction, "
"model caching, and torch.compile optimization. Connect output to SeedVR2 Video Upscaler."
"Load and configure SeedVR2 VAE (Variational Autoencoder) for encoding/decoding video frames to/from latent space. "
"Supports tiled processing to handle high resolutions on limited VRAM, model caching, "
"multi-GPU offloading, and torch.compile acceleration. \n\n"
"Connect to Video Upscaler node."
),
inputs=[
io.Combo.Input("model",
options=vae_models,
default=DEFAULT_VAE,
tooltip="VAE model for encoding/decoding. Models will automatically download on first use. Additional models can be added to the ComfyUI models folder."
tooltip=(
"VAE (Variational Autoencoder) model for encoding/decoding.\n"
"Models automatically download on first use.\n"
"Additional models can be added to the ComfyUI models folder."
)
),
io.Combo.Input("device",
options=devices,
default=devices[0],
tooltip="Device for VAE inference (encoding/decoding)"
tooltip="GPU/CPU device for VAE model inference (encoding/decoding phases)"
),
io.Boolean.Input("encode_tiled",
default=False,
optional=True,
tooltip="Enable tiled decoding to reduce VRAM during decoding"
tooltip="Enable tiled encoding to reduce VRAM usage during the encoding phase"
),
io.Int.Input("encode_tile_size",
default=1024,
min=64,
step=32,
optional=True,
tooltip="Encoding tile size in pixels (default: 1024). Adjust based on available VRAM."
tooltip=(
"Encoding tile size in pixels (default: 1024).\n"
"Applied to both height and width.\n"
"Lower values reduce VRAM usage but may increase processing time.\n"
"Only used when encode_tiled is enabled."
)
),
io.Int.Input("encode_tile_overlap",
default=128,
min=0,
step=32,
optional=True,
tooltip="Pixel overlap between encoding tiles to reduce visible seams (default: 128). Higher values improve blending at the cost of slower processing."
tooltip=(
"Pixel overlap between encoding tiles (default: 128).\n"
"Reduces visible seams between tiles through blending.\n"
"Higher values improve quality but slow processing.\n"
"Only used when encode_tiled is enabled."
)
),
io.Boolean.Input("decode_tiled",
default=False,
optional=True,
tooltip="Enable tiled decoding to reduce VRAM during decoding"
tooltip="Enable tiled decoding to reduce VRAM usage during the decoding phase"
),
io.Int.Input("decode_tile_size",
default=1024,
min=64,
step=32,
optional=True,
tooltip="Decoding tile size in pixels (default: 1024). Adjust based on available VRAM."
tooltip=(
"Decoding tile size in pixels (default: 1024).\n"
"Applied to both height and width.\n"
"Lower values reduce VRAM usage but may increase processing time.\n"
"Only used when decode_tiled is enabled."
)
),
io.Int.Input("decode_tile_overlap",
default=128,
min=0,
step=32,
optional=True,
tooltip="Pixel overlap between decoding tiles to reduce visible seams (default: 128). Higher values improve blending at the cost of slower processing."
tooltip=(
"Pixel overlap between decoding tiles (default: 128).\n"
"Reduces visible seams between tiles through blending.\n"
"Higher values improve quality but slow processing.\n"
"Only used when decode_tiled is enabled."
)
),
io.Combo.Input("tile_debug",
options=["false", "encode", "decode"],
default="false",
optional=True,
tooltip="Enable tile debug visualization: 'false' (no overlay), 'encode' (show encode tiles), 'decode' (show decode tiles). Only works when respective tiling is enabled."
tooltip=(
"Tile debug visualization mode:\n"
"• 'false': No visualization overlay (default)\n"
"• 'encode': Show encoding tile boundaries\n"
"• 'decode': Show decoding tile boundaries\n"
"\n"
"Only works when respective tiling is enabled."
)
),
io.Combo.Input("offload_device",
options=get_device_list(include_none=True, include_cpu=True),
default="none",
optional=True,
tooltip="Device to offload VAE model to when not in use. Select 'none' to keep on inference device, or 'cpu' for CPU offload (slower but reduces VRAM usage). Required for BlockSwap."
tooltip=(
"Device to offload VAE model when not actively processing.\n"
"• 'none': Keep model on inference device (default, fastest)\n"
"• 'cpu': Offload to system RAM (reduces VRAM usage)\n"
"• 'cuda:X': Offload to another GPU (good balance if available)"
)
),
io.Boolean.Input("cache_model",
default=False,
optional=True,
tooltip="Keep VAE model loaded on offload_device between workflow runs. Useful for batch processing."
tooltip=(
"Keep VAE model loaded on offload_device between workflow runs.\n"
"Useful for batch processing to avoid repeated loading.\n"
"Requires offload_device to be set."
)
),
io.Custom("TORCH_COMPILE_ARGS").Input("torch_compile_args",
optional=True,
tooltip="Optional torch.compile settings from SeedVR2 Torch Compile Settings node for speedup"
tooltip=(
"Optional torch.compile optimization settings from SeedVR2 Torch Compile Settings node.\n"
"Provides 15-25% speedup with compatible PyTorch 2.0+ and Triton installation."
)
),
],
outputs=[
io.Custom("SEEDVR2_VAE").Output()
io.Custom("SEEDVR2_VAE").Output(
tooltip="VAE model configuration containing model path, device settings, tiling parameters, and compilation options. Connect to Video Upscaler node."
)
]
)
+82 -17
View File
@@ -53,46 +53,72 @@ class SeedVR2VideoUpscaler(io.ComfyNode):
display_name="SeedVR2 Video Upscaler",
category="SEEDVR2",
description=(
"High-quality video upscaling using diffusion models. "
"Supports RGB and RGBA formats, temporal consistency, and adaptive VRAM management."
"SeedVR2 main upscaling node: processes video frames using DiT and VAE models with diffusion-based enhancement. "
"Handles RGB/RGBA formats, maintains temporal consistency across frames, applies color correction, "
"and manages VRAM through intelligent tensor offloading. \n\n"
"Requires DiT and VAE model configurations."
),
inputs=[
io.Image.Input("image",
tooltip="Input video frames. Accepts both RGB (3-channel) and RGBA (4-channel) images. Output will match input format."
tooltip=(
"Input video frames as image batch.\n"
"Accepts both RGB (3-channel) and RGBA (4-channel) formats.\n"
"Output format will match input format."
)
),
io.Custom("SEEDVR2_DIT").Input("dit",
tooltip="DiT model configuration from SeedVR2 Load DiT Model node"
tooltip="DiT model configuration from SeedVR2 (Down)Load DiT Model node"
),
io.Custom("SEEDVR2_VAE").Input("vae",
tooltip="VAE model configuration from SeedVR2 Load VAE Model node"
tooltip="VAE model configuration from SeedVR2 (Down)Load VAE Model node"
),
io.Int.Input("seed",
default=42,
min=0,
max=2**32 - 1,
step=1,
tooltip="Random seed for generation. Same seed = same output."
tooltip=(
"Random seed for reproducible generation (default: 42).\n"
"Same seed with same inputs produces identical output."
)
),
io.Int.Input("new_resolution",
default=1080,
min=16,
max=16384,
step=2,
tooltip="Target resolution for the shortest edge. Maintains aspect ratio."
tooltip=(
"Target resolution for the shortest edge in pixels (default: 1080).\n"
"Automatically maintains aspect ratio of input.\n"
"Even values required for optimal processing."
)
),
io.Int.Input("max_resolution",
default=0,
min=0,
max=16384,
step=2,
tooltip="Maximum resolution for any edge. If any dimension exceeds this after new_resolution is applied, both dimensions are scaled down proportionally. 0 = no limit (default)."
tooltip=(
"Maximum resolution limit for any dimension (default: 0, no limit).\n"
"If any edge exceeds this after applying new_resolution,\n"
"both dimensions are scaled down proportionally.\n"
"Useful to prevent excessive VRAM usage on extreme aspect ratios."
)
),
io.Int.Input("batch_size",
default=5,
min=1,
max=16384,
step=4,
tooltip="Frames per batch (4n+1: 1,5,9,13,17,21,...). Ideally match shot length. Higher = better temporal consistency + speed but more VRAM."
tooltip=(
"Number of frames processed together per batch (default: 5).\n"
"Must follow pattern 4n+1: 1, 5, 9, 13, 17, 21, ...\n"
"\n"
"• Higher values: Better temporal consistency and faster processing\n"
"• Lower values: Reduced VRAM usage\n"
"\n"
"Ideally match to shot length for best quality."
)
),
io.Int.Input("temporal_overlap",
default=0,
@@ -100,7 +126,11 @@ class SeedVR2VideoUpscaler(io.ComfyNode):
max=16,
step=1,
optional=True,
tooltip="Overlapping frames between batches for smoother transitions. 0 = disabled. Values 1-4 work well for temporal consistency."
tooltip=(
"Overlapping frames between consecutive batches (default: 0, disabled).\n"
"Improves temporal consistency across batch boundaries through blending.\n"
"Values 1-4 work well for most content."
)
),
io.Int.Input("prepend_frames",
default=0,
@@ -108,12 +138,26 @@ class SeedVR2VideoUpscaler(io.ComfyNode):
max=32,
step=1,
optional=True,
tooltip="Number of frames to prepend to the video (reversed from start). This can help with artifacts at the start of the video and are automatically removed after processing."
tooltip=(
"Number of frames to prepend (reversed from start) before processing (default: 0).\n"
"Helps reduce artifacts at video beginning.\n"
"Prepended frames are automatically removed from final output."
)
),
io.Combo.Input("color_correction",
options=["lab", "wavelet", "wavelet_adaptive", "hsv", "adain", "none"],
default="lab",
tooltip="Color correction method: 'lab' (full perceptual color matching with detail preservation, recommended), 'wavelet' (frequency-based natural colors, preserves details), 'wavelet_adaptive' (wavelet base + targeted saturation correction), 'hsv' (hue-conditional saturation matching), 'adain' (statistical style transfer), 'none' (no correction)"
tooltip=(
"Corrects color shifts in upscaled output to match original input (default: lab).\n"
"The upscaling process may alter colors; this applies color grading to restore them.\n"
"\n"
"• lab: Perceptual color matching with detail preservation (recommended)\n"
"• wavelet: Frequency-based natural colors, preserves fine details\n"
"• wavelet_adaptive: Wavelet base with targeted saturation correction\n"
"• hsv: Hue-conditional saturation matching\n"
"• adain: Statistical style transfer approach\n"
"• none: No color correction applied"
)
),
io.Float.Input("input_noise_scale",
default=0.0,
@@ -121,7 +165,12 @@ class SeedVR2VideoUpscaler(io.ComfyNode):
max=1.0,
step=0.001,
optional=True,
tooltip="Input noise injection scale [0.0-1.0]. Adds variation to input. 0.0 = disabled."
tooltip=(
"Input noise injection scale (default: 0.0, disabled).\n"
"Adds controlled variation to input images before encoding.\n"
"Range: 0.0 (no noise) to 1.0 (maximum noise).\n"
"Can help with certain types of artifacts."
)
),
io.Float.Input("latent_noise_scale",
default=0.0,
@@ -129,22 +178,38 @@ class SeedVR2VideoUpscaler(io.ComfyNode):
max=1.0,
step=0.001,
optional=True,
tooltip="Latent noise injection scale [0.0-1.0]. Adds variation to latent space. 0.0 = disabled."
tooltip=(
"Latent space noise injection scale (default: 0.0, disabled).\n"
"Adds controlled variation during the diffusion process.\n"
"Range: 0.0 (no noise) to 1.0 (maximum noise).\n"
"Can soften details if input_noise_scale doesn't help."
)
),
io.Combo.Input("offload_device",
options=get_device_list(include_none=True, include_cpu=True),
default="cpu",
optional=True,
tooltip="Device to offload intermediate tensors. 'cpu' prevents VRAM accumulation for long videos. 'none' keeps all tensors on inference device (faster but increases VRAM usage)."
tooltip=(
"Device for storing intermediate tensors between processing phases (default: cpu).\n"
"• 'none': Keep all tensors on inference device (fastest but highest VRAM usage)\n"
"• 'cpu': Offload to system RAM (recommended for long videos, slower transfers)\n"
"• 'cuda:X': Offload to another GPU (good balance if available, faster than CPU)"
)
),
io.Boolean.Input("enable_debug",
default=False,
optional=True,
tooltip="Show detailed memory usage and timing information during generation, useful for troubleshooting."
tooltip=(
"Enable detailed debug logging (default: False).\n"
"Shows memory usage, timing information, and processing details.\n"
"Useful for troubleshooting errors and performance issues."
)
),
],
outputs=[
io.Image.Output()
io.Image.Output(
tooltip="Upscaled video frames with color correction applied. Format (RGB/RGBA) matches input. Range [0, 1] normalized for ComfyUI compatibility."
)
]
)