This commit is contained in:
justumen
2025-02-28 10:07:58 +01:00
parent b25691ffb4
commit 44d69e8907
4 changed files with 103 additions and 10 deletions

View File

@@ -1,4 +1,4 @@
# 🔗 Comfyui : Bjornulf_custom_nodes v0.76 🔗
# 🔗 Comfyui : Bjornulf_custom_nodes v0.77 🔗
A list of 142 custom nodes for Comfyui : Display, manipulate, create and edit text, images, videos, loras, generate characters and more.
You can manage looping operations, generate randomized content, trigger logical conditions, pause and manually control your workflows and even work with external AI tools, like Ollama or Text To Speech.
@@ -232,6 +232,7 @@ Support me and my work : ❤️❤️❤️ <https://ko-fi.com/bjornulf> ❤️
`36.` [⏸️ Paused. Select input, Pick 👇](#36---%EF%B8%8F-paused-select-input-pick-one)
`117.` [📝👈🅰️ Line selector (🎲 or ♻ or ♻📑)](#117---🅰%EF%B8%8F-line-selector--or--or-)
`135.` [🔛✨ Anything Switch On/Off](#135----anything-switch-onoff)
`136.` [🔛📝 Text Switch On/Off](#136----text-switch-onoff)
## 🧠 Logic / Conditional Operations 🧠
`45.` [🔀 If-Else (input / compare_with)](#45----if-else-input--compare_with)
@@ -411,7 +412,7 @@ Fix a lot of code everywhere, a little better logging system, etc...
WIP : Rewrite of all my ffmpeg nodes. (Still need improvements and fixes, will do that in 0.71?) Maybe don't use them yet...
- **0.71**: ❗Breaking changes for Global variable nodes. (add to global variable system a "filename", which is a a separate global variable file.) bug fix speech to text node, 5 new nodes 129-133. combine text limit raised to 100. improve Save image in folder node.
- **0.71-0.75**: Many bug fixing. Civitai nodes are working on windows. (encoding, links problem are solved ? - at least on my machines...)
- **0.76**: Removed kokoro_onnx from requirements.txt due to sonflict with other nodes (need to be installed manually if you want to use this node.)
- **0.76**: Removed kokoro_onnx from requirements.txt due to some conflict with other nodes (need to be installed manually if you want to use this node.)
New syntaxes for advanced text/line selector, ex: {left|right|middle|group=LMR}+{left|right|middle|group=LMR}+{left|right|middle|group=LMR} and {A(80%)|B(15%)|C(5%)}
2 new nodes switch : 🔛✨ Anything Switch On/Off (compatible with combine images) AND 🔛📝 Text Switch On/Off (Compatible with combine texts)
2 new pick Me global nodes, using an identifier instead of chain : 🌎✒👉 Global Write Pick Me AND 🌎📥 Load Global Pick Me

View File

@@ -3,6 +3,8 @@ import numpy as np
from PIL import Image, ImageSequence, ImageOps
import torch
from aiohttp import web
from server import PromptServer
class LoadImagesFromSelectedFolder:
@classmethod
def INPUT_TYPES(cls):
@@ -94,3 +96,29 @@ class LoadImagesFromSelectedFolder:
outputs.append(placeholder_image)
return tuple(outputs)
# Define the API endpoint to get the list of image folders
@PromptServer.instance.routes.get("/get_image_folders")
async def get_image_folders(request):
# Get the ComfyUI output directory
script_dir = os.path.dirname(os.path.abspath(__file__))
comfyui_root = os.path.abspath(os.path.join(script_dir, '..', '..'))
output_dir = os.path.join(comfyui_root, 'output')
# Collect folders with images
folders = []
for root, dirs, files in os.walk(output_dir):
rel_path = os.path.relpath(root, output_dir)
if rel_path == '.':
continue # Skip the root output directory itself
# Count image files in the folder
image_count = len([f for f in os.listdir(root) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp'))])
if image_count > 0:
folder_name = f"{rel_path} ({image_count} images)"
folders.append(folder_name)
# Sort the list alphabetically (case-insensitive)
folders.sort(key=lambda x: x.lower())
# Return the folder list as JSON
return web.json_response({"success": True, "folders": folders})

View File

@@ -0,0 +1,63 @@
import { app } from "../../../scripts/app.js";
app.registerExtension({
name: "Bjornulf.LoadImagesFromSelectedFolder",
async nodeCreated(node) {
if (node.comfyClass !== "Bjornulf_LoadImagesFromSelectedFolder") return;
// Add a "Refresh Folders" button
node.addWidget(
"button",
"Refresh Folders",
null,
async () => {
if (!node.graph) return;
try {
// Fetch the folder list from the server
const response = await fetch("/get_image_folders");
const data = await response.json();
if (data.success && data.folders) {
const dropdown = node.widgets.find(w => w.name === "selected_folder");
if (dropdown) {
// Remember the current selection
const currentValue = dropdown.value;
// Update the dropdown with the new folder list
dropdown.options.values = data.folders;
// Try to keep the same folder selected (accounting for image count changes)
const folderNameRegex = /^(.+?)\s*\(\d+\s*images\)$/;
const match = currentValue.match(folderNameRegex);
let updatedValue = null;
if (match) {
const folderName = match[1]; // e.g., "folder1"
updatedValue = data.folders.find(f => f.startsWith(folderName + " ("));
}
// Set the new value: keep the folder if it exists, otherwise pick the first one
if (updatedValue) {
dropdown.value = updatedValue;
} else if (data.folders.length > 0) {
dropdown.value = data.folders[0];
} else {
dropdown.value = null; // No folders available
}
// Let you know it worked
app.ui.dialog.show("Folder list refreshed successfully.");
} else {
app.ui.dialog.show("Dropdown widget not found.");
}
} else {
app.ui.dialog.show("Failed to fetch folder list.");
}
} catch (error) {
app.ui.dialog.show("An error occurred while fetching the folder list.");
}
}
);
},
});

View File

@@ -65,7 +65,8 @@ function displayVideoPreview(component, filename, category, autoplay, mute) {
else videoWidget.videoElement.muted = false;
if(autoplay) videoWidget.videoElement.autoplay = !videoWidget.value.paused && !videoWidget.value.hidden;
else videoWidget.videoElement.autoplay = false;
videoWidget.videoElement.src = `http://localhost:8188/api/view?${urlParams.toString()}`;
// videoWidget.videoElement.src = `http://localhost:8188/api/view?${urlParams.toString()}`;
videoWidget.videoElement.src = `api/view?${urlParams.toString()}`;
adjustSize(component); // Adjust the component size
}