mirror of
https://github.com/justUmen/Bjornulf_custom_nodes.git
synced 2026-03-21 12:42:11 -03:00
0.23
This commit is contained in:
15
README.md
15
README.md
@@ -1,4 +1,4 @@
|
||||
# 🔗 Comfyui : Bjornulf_custom_nodes v0.22 🔗
|
||||
# 🔗 Comfyui : Bjornulf_custom_nodes v0.23 🔗
|
||||
|
||||
# ☁ Usage in cloud :
|
||||
|
||||
@@ -65,6 +65,7 @@ wget --content-disposition -P /workspace/ComfyUI/models/checkpoints "https://civ
|
||||
- **v0.20**: Changes for lobechat save image : include the code of free VRAM hack + ignore missing images filenames
|
||||
- **v0.21**: Add a new write text node that also display the text in the comfyui console (good for debugging)
|
||||
- **v0.22**: Allow write text node to use random selection like this {hood|helmet} will randomly choose between hood or helmet.
|
||||
- **v0.23**: And a new node: Pause, resume or stop workflow.
|
||||
|
||||
# 📝 Nodes descriptions
|
||||
|
||||
@@ -326,3 +327,15 @@ So, not perfect but better than being stuck at 6GB of VRAM used if I know I won'
|
||||
Just connect this node with your workflow, it takes an image as input and return the same image without any changes.
|
||||
❗ Comfyui is using cache to run faster (like not reloading checkpoints), so only use this free VRAM node when you need it.
|
||||
❗ For this node to work properly, you need to enable the dev/api mode in ComfyUI. (You can do that in the settings)
|
||||
|
||||
### 35 - ⏸️ Paused. Resume or Stop ?
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
**Description:**
|
||||
Automatically pause the workflow, and rings a bell when it does. (play the audio `bell.m4a` file provided)
|
||||
You can then manually resume or stop the workflow by clicking on the node's buttons.
|
||||
I do that let's say for example if I have a very long upscaling process, I can check if the input is good before continuing. Sometimes I might stop the workflow and restart it with another seed.
|
||||
You can connect any type of node to the pause node, above is an example with text, but you can send an IMAGE or whatever else, in the node `input = output`. (Of course you need to send the output to something that has the correct format...)
|
||||
@@ -40,7 +40,7 @@ from .character_description import CharacterDescriptionGenerator
|
||||
from .text_to_speech import TextToSpeech
|
||||
from .loop_combine_texts_by_lines import CombineTextsByLines
|
||||
from .free_vram_hack import FreeVRAM
|
||||
# from .pause_resume import PauseResume
|
||||
from .pause_resume_stop import PauseResume
|
||||
# from .check_black_image import CheckBlackImage
|
||||
# from .clear_vram import ClearVRAM
|
||||
|
||||
@@ -49,7 +49,7 @@ from .free_vram_hack import FreeVRAM
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
# "Bjornulf_CustomStringType": CustomStringType,
|
||||
"Bjornulf_ollamaLoader": ollamaLoader,
|
||||
# "Bjornulf_PauseResume": PauseResume,
|
||||
"Bjornulf_PauseResume": PauseResume,
|
||||
"Bjornulf_FreeVRAM": FreeVRAM,
|
||||
"Bjornulf_CombineTextsByLines": CombineTextsByLines,
|
||||
"Bjornulf_TextToSpeech": TextToSpeech,
|
||||
@@ -98,7 +98,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
# "Bjornulf_CustomStringType": "!!! CUSTOM STRING TYPE !!!",
|
||||
"Bjornulf_ollamaLoader": "🦙 Ollama (Description)",
|
||||
# "Bjornulf_PauseResume": "⏸️ Pause/Resume",
|
||||
"Bjornulf_PauseResume": "⏸️ Paused. Resume or Stop ?",
|
||||
"Bjornulf_FreeVRAM": "🧹 Free VRAM hack",
|
||||
"Bjornulf_CombineTextsByLines": "♻ Loop (All Lines from input 🔗 combine by lines)",
|
||||
"Bjornulf_TextToSpeech": "🔊 TTS - Text to Speech",
|
||||
|
||||
63
pause_resume_stop.py
Normal file
63
pause_resume_stop.py
Normal file
@@ -0,0 +1,63 @@
|
||||
import time
|
||||
from aiohttp import web
|
||||
from server import PromptServer
|
||||
import logging
|
||||
from pydub import AudioSegment
|
||||
from pydub.playback import play
|
||||
import os
|
||||
|
||||
class Everything(str):
|
||||
def __ne__(self, __value: object) -> bool:
|
||||
return False
|
||||
|
||||
class PauseResume:
|
||||
is_paused = True
|
||||
should_stop = False
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input": (Everything("*"), {"forceInput": True})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (Everything("*"),)
|
||||
RETURN_NAMES = ("output",)
|
||||
FUNCTION = "loop_resume_or_stop"
|
||||
CATEGORY = "Bjornulf"
|
||||
|
||||
def play_audio(self):
|
||||
audio_file = os.path.join(os.path.dirname(__file__), 'bell.m4a')
|
||||
sound = AudioSegment.from_file(audio_file, format="m4a")
|
||||
play(sound)
|
||||
|
||||
def loop_resume_or_stop(self, input):
|
||||
self.play_audio()
|
||||
self.input = input
|
||||
while PauseResume.is_paused and not PauseResume.should_stop:
|
||||
logging.info(f"PauseResume.is_paused: {PauseResume.is_paused}, PauseResume.should_stop: {PauseResume.should_stop}")
|
||||
time.sleep(1) # Sleep to prevent busy waiting
|
||||
|
||||
if PauseResume.should_stop:
|
||||
PauseResume.should_stop = False # Reset for next run
|
||||
PauseResume.is_paused = True
|
||||
PauseResume.should_stop = False
|
||||
raise Exception("Workflow stopped by user")
|
||||
|
||||
PauseResume.is_paused = True
|
||||
PauseResume.should_stop = False
|
||||
return (self.input,)
|
||||
|
||||
@PromptServer.instance.routes.get("/bjornulf_resume")
|
||||
async def resume_node(request):
|
||||
logging.info("Resume node called")
|
||||
PauseResume.is_paused = False
|
||||
return web.Response(text="Node resumed")
|
||||
|
||||
@PromptServer.instance.routes.get("/bjornulf_stop")
|
||||
async def stop_node(request):
|
||||
logging.info("Stop node called")
|
||||
PauseResume.should_stop = True
|
||||
PauseResume.is_paused = False # Ensure the loop exits
|
||||
return web.Response(text="Workflow stopped")
|
||||
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "bjornulf_custom_nodes"
|
||||
description = "Nodes: Ollama, Text to Speech, Save image for Bjornulf LobeChat, Text with random Seed, Random line from input, Combine images (Background + Overlay alpha), Image to grayscale (black & white), Remove image Transparency (alpha), Resize Image, ..."
|
||||
version = "0.21"
|
||||
version = "0.23"
|
||||
license = {file = "LICENSE"}
|
||||
|
||||
[project.urls]
|
||||
|
||||
BIN
screenshots/pause1.png
Normal file
BIN
screenshots/pause1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
screenshots/pause2.png
Normal file
BIN
screenshots/pause2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
BIN
screenshots/pause3.png
Normal file
BIN
screenshots/pause3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
37
web/js/pauseresume.js
Normal file
37
web/js/pauseresume.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { app } from "../../../scripts/app.js";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Bjornulf.PauseResume",
|
||||
async nodeCreated(node) {
|
||||
if (node.comfyClass === "Bjornulf_PauseResume") {
|
||||
const resumeButton = node.addWidget("button", "Resume", "Resume", () => {
|
||||
fetch('/bjornulf_resume', { method: 'GET' })
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
console.log('Resume response:', data);
|
||||
// You can update the UI here if needed
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
});
|
||||
const stopButton = node.addWidget("button", "Stop", "Stop", () => {
|
||||
fetch('/bjornulf_stop', { method: 'GET' })
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
console.log('Stop response:', data);
|
||||
// You can update the UI here if needed
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// BASIC BUTTON
|
||||
// app.registerExtension({
|
||||
// name: "Bjornulf.PauseResume",
|
||||
// async nodeCreated(node) {
|
||||
// if (node.comfyClass === "Bjornulf_PauseResume") {
|
||||
// node.addWidget("button","Resume","Resume", (...args) => { console.log("lol"); } )
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
Reference in New Issue
Block a user