This commit is contained in:
noembryo
2026-09-03 22:18:09 +03:00
parent 85853bd754
commit b2191d6680
6 changed files with 125 additions and 9 deletions
+20
View File
@@ -1,8 +1,11 @@
# noEmbryo Nodes
A diverse set of nodes for ComfyUI.
- [Json Prompt Loader](#json-prompt-loader)
- [Load Image (from path)](#load-image-from-path)
- [Resolution Scale](#resolution-scale)
- [Regex Text Chopper](#regex-text-chopper)
- [H3 Motion Context Clip Stitcher](#h3-motion-context-clip-stitcher)
- [H3 Motion Context Clip Purge](#h3-motion-context-clip-purge)
- [Auto Save Workflow](#auto-save-workflow)
- [PromptTermList (1-6)](#prompttermlist-1-6)
@@ -142,6 +145,23 @@ No quality loss, like when trying to concatenate encoded videos.
- **frame_count**: The total number of frames
- **report**: Logging of some of the node's actions
---
## H3 Motion Context Clip Purge
![H3MotionContextClipPurge.png](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/refs/heads/master/stuff/H3MotionContextClipPurge.png)
Deletes the numbered `h3_motion_context_av_v1` clip archive files at the root of a folder (default: `h3_context`)
Only files matching the pattern are removed; sub-folders and everything inside them are left untouched.
- **Controls**
- **mode**: Purge (Enabled): delete the matching files.
Preview (dry run, Disabled): delete nothing; the report just lists the files that would be deleted.
- **folder** is the folder whose root-level clip archives will be deleted.
Absolute paths and paths relative to ComfyUI/output are accepted.
- **pattern** is the filename glob. Only root-level FILES matching this pattern are deleted.
Sub-folders are never touched.
- **Outputs**
- **report**: Shows the actions of the node.
---
## Auto Save Workflow
+6 -2
View File
@@ -19,12 +19,14 @@ from server import PromptServer
def _is_url(s) -> bool:
"""Return True if s looks like an HTTP(S) URL."""
""" Return True if s looks like an HTTP(S) URL.
"""
# noinspection HttpUrlsUsage
return isinstance(s, str) and (s.startswith("http://") or s.startswith("https://"))
def _fetch_url_bytes(url: str, timeout: float = 30.0) -> bytes:
"""Download the bytes of a URL. Raises on any network/HTTP problem.
""" Download the bytes of a URL. Raises on any network/HTTP problem.
Embedded Python distributions (StabilityMatrix, ComfyUI portable, ...) often
ship with a missing or outdated CA bundle, causing CERTIFICATE_VERIFY_FAILED
@@ -46,6 +48,7 @@ def _fetch_url_bytes(url: str, timeout: float = 30.0) -> bytes:
# Strategy 2: use certifi's CA bundle if it's installed.
try:
# noinspection PyUnresolvedReferences
import certifi
ctx = ssl.create_default_context(cafile=certifi.where())
opener = build_opener(HTTPSHandler(context=ctx))
@@ -66,6 +69,7 @@ def _fetch_url_bytes(url: str, timeout: float = 30.0) -> bytes:
"downloads without certificate validation. Consider installing/"
"updating the 'certifi' package for secure downloads.")
_ssl_warning_shown = True
# noinspection PyUnresolvedReferences,PyProtectedMember
ctx = ssl._create_unverified_context()
opener = build_opener(HTTPSHandler(context=ctx))
with opener.open(req, timeout=timeout) as resp:
+6 -3
View File
@@ -4,17 +4,18 @@ from os.path import realpath, join, dirname, isabs, splitext, basename
from datetime import datetime
import folder_paths
from .load_image_from_path import LoadImageFromPathEnhanced
from .stitcher import H3MotionContextClipStitcher, H3ContextLatentConverter
from .stitcher import (H3MotionContextClipStitcher, H3ContextLatentConverter,
H3MotionContextClipPurge)
MANIFEST = {"name": "noEmbryo Nodes",
"version": (1, 6, 5),
"version": (1, 6, 6),
"author": "noEmbryo",
"project": "https://github.com/noembryo/ComfyUI-noEmbryo",
"description": "Nodes for ComfyUI",
"license": "MIT",
}
__author__ = "noEmbryo"
__version__ = "1.6.5"
__version__ = "1.6.6"
LISTS_PATH = join(dirname(realpath(__file__)), "TermLists")
@@ -481,6 +482,7 @@ NODE_CLASS_MAPPINGS = {f"JsonPromptLoader -{__author__}": JsonPromptLoader,
f"Auto Save Workflow -{__author__}": AutoSaveWorkflow,
f"Load Image (from path) -{__author__}": LoadImageFromPathEnhanced,
f"H3MotionContextClipStitcher -{__author__}": H3MotionContextClipStitcher,
f"H3MotionContextClipPurge -{__author__}": H3MotionContextClipPurge,
f"H3ContextLatentConverter -{__author__}": H3ContextLatentConverter,
"PromptTermList1": PromptTermList1,
"PromptTermList2": PromptTermList2,
@@ -496,6 +498,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {f"JsonPromptLoader -{__author__}": f"Json Prompt L
f"Auto Save Workflow -{__author__}": f"Auto Save Workflow /{__author__}",
f"Load Image (from path) -{__author__}": f"Load Image (from path) /{__author__}",
f"H3MotionContextClipStitcher -{__author__}": f"H3 Motion Context Clip Stitcher /{__author__}",
f"H3MotionContextClipPurge -{__author__}": f"H3 Motion Context Clip Purge /{__author__}",
f"H3ContextLatentConverter -{__author__}": f"H3 Context Latent Converter /{__author__}",
"PromptTermList1": f"PromptTermList 1 /{__author__}",
"PromptTermList2": f"PromptTermList 2 /{__author__}",
+3 -2
View File
@@ -5,13 +5,14 @@ A collection of nodes for ComyUI. \n
* "Load Image (from path)" lets you load an image from any path in your computer or a URL, and use a selection rectangle at the preview to crop it. It can also
limit the output's size in megapixels. \n
* "H3 Motion Context Clip Stitcher" concatenates H3 Motion Context clip archives. \n
* "H3 Motion Context Clip Purge" clears all H3 Motion Context clip archives. \n
* "JsonPromptLoader" enhances a propt using a .json file with `item:prompt` pairs. \n
* "Resolution Scale" resizes an image using pixels or scale factor. \n
* "Regex Text Chopper" cuts text based on regex. \n
* "PromptTermList (1-6)" nodes to help with the creation of Prompts. \n
* "Auto Save Workflow" can save the current workflow to a .json file automatically. \n
"""
version = "1.6.5"
version = "1.6.6"
license = {text = "MIT License"}
[project.urls]
@@ -20,5 +21,5 @@ Repository = "https://github.com/noembryo/ComfyUI-noEmbryo"
[tool.comfy]
PublisherId = "noembryo"
DisplayName = "noEmbryo"
DisplayName = "noEmbryoNodes"
Icon = "https://iili.io/JmSdmAJ.png"
+90 -2
View File
@@ -9,6 +9,7 @@ into Motion Context.
The archive format is the sampler output, and this node is a final-media assembly tool.
"""
import fnmatch
import glob
import logging
import os
@@ -134,8 +135,7 @@ def _decode_audio(audio_vae, audio_latent):
audio = audio_vae.decode(audio_latent)
# Current ComfyUI audio VAE returns [B,L,C]. Convert to [B,C,L].
if audio.ndim != 3:
raise RuntimeError("H3 audio VAE returned unexpected shape %s"
% (tuple(audio.shape),))
raise RuntimeError("H3 audio VAE returned unexpected shape %s" % (tuple(images.shape),))
audio = audio.movedim(-1, 1)
sr = int(getattr(audio_vae, "audio_sample_rate_output",
getattr(audio_vae, "audio_sample_rate", 32000)))
@@ -574,12 +574,100 @@ class H3ContextLatentConverter:
return (converted,)
class H3MotionContextClipPurge:
""" Delete the saved H3 Motion Context clip archive files from a folder.
"""
@classmethod
def INPUT_TYPES(cls):
return {"required": {"mode": ("BOOLEAN", {"default": True,
"label_on": "Purge", "label_off": "Preview (dry run)",
"tooltip": "Purge (Enabled): delete the matching files.\n"
"Preview (dry run, Disabled): delete nothing; the report "
"just lists the files that would be deleted."}),
"folder": ("STRING", {"default": "h3_context",
"tooltip": "Folder whose root-level clip archives will be deleted.\n"
"Absolute paths and paths relative to ComfyUI/output are "
"accepted."}),
"pattern": ("STRING", {"default": "clip_*.safetensors",
"tooltip": "Filename glob. Only root-level FILES matching this "
"pattern are deleted.\nSub-folders are never touched."}), },
"hidden": {"mode": "BOOLEAN"}}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("report",)
FUNCTION = "purge"
CATEGORY = "noEmbryo"
OUTPUT_NODE = True
DESCRIPTION = ("Deletes the numbered h3_motion_context_av_v1 clip archive files "
"at the root of a folder (default: h3_context).\n"
"Purge (Enabled): deletes the files.\n"
"Preview (Disabled): dry run - the report only lists what would "
"be deleted.\nOnly files matching the pattern are removed; "
"sub-folders and everything inside them are left untouched.")
# noinspection PyUnusedLocal
@classmethod
def IS_CHANGED(cls, mode, folder, pattern):
return float("NaN")
@staticmethod
def purge(mode, folder, pattern):
d = _resolve_folder(folder)
pattern = (pattern or "clip_*.safetensors").strip()
doomed = []
for entry in os.scandir(d):
if entry.is_file(follow_symlinks=False) and not entry.is_dir():
if fnmatch.fnmatch(entry.name, pattern):
doomed.append((entry.name, entry.stat().st_size))
if not mode: # Preview (dry run)
lines = ["H3 clip purge (DRY RUN) in %s - nothing was deleted:" % d]
lines += [" would delete: %s (%s)" % (name, _fmt_size(size))
for name, size in doomed] or [" no matching files."]
lines.append("TOTAL: %d file(s), %s" %
(len(doomed), _fmt_size(sum(s for _, s in doomed))))
report = "\n".join(lines)
log_.info(report)
return (report,)
deleted = 0
freed = 0
lines = ["H3 clip purge in %s:" % d]
for name, size in doomed:
try:
os.remove(os.path.join(d, name))
deleted += 1
freed += size
lines.append(" deleted: %s (%s)" % (name, _fmt_size(size)))
except OSError as e:
lines.append(" FAILED to delete %s: %s" % (name, e))
if not deleted and not doomed:
lines.append(" no matching files.")
lines.append("TOTAL: deleted %d file(s), freed %s" %
(deleted, _fmt_size(freed)))
report = "\n".join(lines)
log_.info(report)
return (report,)
def _fmt_size(num_bytes):
size = float(num_bytes)
for unit in ("B", "KiB", "MiB", "GiB"):
if size < 1024.0:
return "%.1f %s" % (size, unit)
size /= 1024.0
return "%.1f TiB" % size
NODE_CLASS_MAPPINGS = {
"H3MotionContextClipStitcher": H3MotionContextClipStitcher,
"H3ContextLatentConverter": H3ContextLatentConverter,
"H3MotionContextClipPurge": H3MotionContextClipPurge,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"H3MotionContextClipStitcher": "H3 Motion Context Clip Stitcher",
"H3ContextLatentConverter": "H3 Context Latent Converter",
"H3MotionContextClipPurge": "H3 Motion Context Clip Purge",
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 31 KiB