From 09fa33cd1c70623ba8ff0b441e4e4187fd75e815 Mon Sep 17 00:00:00 2001 From: malkuthro <166633396+malkuthro@users.noreply.github.com> Date: Sat, 16 May 2026 21:06:02 +0200 Subject: [PATCH] fix(video): reach VHS_VideoCombine via nodes.NODE_CLASS_MAPPINGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous `from videohelpersuite.nodes import VideoCombine` fails inside ComfyUI's loader context because VHS uses relative imports throughout (`from .logger ...`, `from .utils ...`) that only resolve when VHS is loaded through ComfyUI's importlib spec — not through a plain absolute import path. The error surfaced as No module named 'utils.install_util'; 'utils' is not a package at Koolook load time, which caused the node to self-skip with an empty NODE_CLASS_MAPPINGS — invisible in ComfyUI's search palette. Fix: look up VHS_VideoCombine through `nodes.NODE_CLASS_MAPPINGS`, which is the documented cross-pack interface. ComfyUI's loader (custom_nodes/.../__init__.py exec_module → merge into global) runs to completion for each pack before moving to the next, and VHS sorts before Koolook alphabetically in every layout we've seen, so by the time Koolook's __init__.py runs the global registry already has VHS_VideoCombine in it. Verified against ComfyUI's nodes.py load_custom_node() at load_custom_node() lines 2196 (exec_module) and 2225-2228 (merge), which guarantee this ordering. Co-Authored-By: Claude Opus 4.7 (1M context) --- k_video_combine.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/k_video_combine.py b/k_video_combine.py index c2d0b23..78fa039 100644 --- a/k_video_combine.py +++ b/k_video_combine.py @@ -34,12 +34,34 @@ from typing import Optional, Tuple try: import folder_paths # ComfyUI core; always present at runtime. - from videohelpersuite.nodes import VideoCombine as _VHS_VideoCombine + # Reach the VHS VideoCombine class through ComfyUI's global node + # registry rather than `from videohelpersuite.nodes import ...`. + # VHS uses relative imports internally (`from .logger import ...`, + # `from .utils import ...`) which only resolve correctly when VHS + # is loaded through ComfyUI's custom-node loader, not through a + # plain absolute import. The global registry is the documented + # cross-pack interface — ComfyUI populates it as each pack loads, + # and Koolook loads after VHS in every install we've seen because + # `comfyui-videohelpersuite` sorts before `koolook` (and even an + # uppercase `ComfyUI-VideoHelperSuite` sorts before + # `ComfyUI-Koolook` if both are present). If for some reason VHS + # isn't loaded yet, the lookup returns None and we self-skip with + # a clear message. + import nodes as _comfy_nodes_module + _VHS_VideoCombine = _comfy_nodes_module.NODE_CLASS_MAPPINGS.get("VHS_VideoCombine") + if _VHS_VideoCombine is None: + raise RuntimeError( + "VHS_VideoCombine not present in ComfyUI's NODE_CLASS_MAPPINGS " + "at Koolook load time. Either ComfyUI-VideoHelperSuite isn't " + "installed, or it loaded after Koolook (unexpected — check " + "custom_nodes folder names)." + ) _VHS_AVAILABLE = True _VHS_IMPORT_ERROR: Optional[BaseException] = None -except ImportError as _exc: +except (ImportError, RuntimeError) as _exc: _VHS_AVAILABLE = False _VHS_IMPORT_ERROR = _exc + _VHS_VideoCombine = None # type: ignore[assignment] def _resolve_abs_target(