From a3f930d8c68bf46de7c89812a09e448ed75ae6ef Mon Sep 17 00:00:00 2001 From: justumen Date: Mon, 16 Sep 2024 00:26:40 +0200 Subject: [PATCH] 0.33 --- README.md | 1 + __init__.py | 3 ++ pause_resume_stop.py | 35 ++++++++++++++++++---- pick_input.py | 36 +++++++++++++++++++---- pyproject.toml | 2 +- web/js/pause_resume_stop.js | 18 +++++------- web/js/pick_input.js | 58 ++++++++++++++++++------------------- web/js/random_image.js | 8 ++--- 8 files changed, 104 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 9cee292..402c042 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ wget --content-disposition -P /workspace/ComfyUI/models/checkpoints "https://civ - **v0.30**: Update the basic Loop node with optional input. - **v0.31**: โ—Sorry, Breaking changes for Write/Show text nodes, cleaner system : 1 simple write text and the other is 1 advanced with console and special syntax. Also Show can now manage INT, FLOAT, TEXT. - **v0.32**: Quick rename to avoid breaking loop_text node. +- **v0.33**: Control random on paused nodes, fix pydub sound bug permissions on Windows. # ๐Ÿ“ Nodes descriptions diff --git a/__init__.py b/__init__.py index cfa6af8..6c913e3 100644 --- a/__init__.py +++ b/__init__.py @@ -47,6 +47,7 @@ from .random_image import RandomImage from .loop_model_clip_vae import LoopModelClipVae from .write_text_advanced import WriteTextAdvanced from .loop_write_text import LoopWriteText +# from .load_images_from_folder import LoadImagesFromSelectedFolder # from .show import ShowWhatever # from .pass_preview_image import PassPreviewImage @@ -59,6 +60,7 @@ NODE_CLASS_MAPPINGS = { # "Bjornulf_CustomStringType": CustomStringType, "Bjornulf_ollamaLoader": ollamaLoader, "Bjornulf_WriteText": WriteText, + # "Bjornulf_LoadImagesFromSelectedFolder": LoadImagesFromSelectedFolder, # "Bjornulf_ShowWhatever": ShowWhatever, "Bjornulf_LoopModelClipVae": LoopModelClipVae, # "Bjoenulf_RandomCheckpoint": RandomCheckpoint, @@ -162,6 +164,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "Bjornulf_TextToSpeech": "๐Ÿ”Š TTS - Text to Speech", "Bjornulf_PickInput": "โธ๏ธ๐Ÿ” Paused. Select input, Pick one", "Bjornulf_PauseResume": "โธ๏ธ Paused. Resume or Stop ?", + # "Bjornulf_LoadImagesFromSelectedFolder": "๐Ÿ“‚๐Ÿ–ผ Load Images from folder", } WEB_DIRECTORY = "./web" diff --git a/pause_resume_stop.py b/pause_resume_stop.py index b69cffe..1f264fd 100644 --- a/pause_resume_stop.py +++ b/pause_resume_stop.py @@ -5,6 +5,9 @@ import logging from pydub import AudioSegment from pydub.playback import play import os +import io +import sys +import random class Everything(str): def __ne__(self, __value: object) -> bool: @@ -18,7 +21,8 @@ class PauseResume: def INPUT_TYPES(cls): return { "required": { - "input": (Everything("*"), {"forceInput": True}) + "input": (Everything("*"), {"forceInput": True}), + "seed": ("INT", {"default": 1}), } } @@ -28,11 +32,32 @@ class PauseResume: 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) + # Check if the operating system is Windows + if sys.platform.startswith('win'): + try: + # Load the audio file into memory + audio_file = os.path.join(os.path.dirname(__file__), 'bell.m4a') + + # Load the audio segment without writing to any temp files + sound = AudioSegment.from_file(audio_file, format="m4a") + + # Export the AudioSegment to a WAV file in memory + wav_io = io.BytesIO() + sound.export(wav_io, format='wav') + wav_data = wav_io.getvalue() + + # Play the WAV data using winsound + import winsound + winsound.PlaySound(wav_data, winsound.SND_MEMORY) + except Exception as e: + print(f"An error occurred: {e}") + else: + 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): + def loop_resume_or_stop(self, input, seed): + random.seed(seed) self.play_audio() self.input = input while PauseResume.is_paused and not PauseResume.should_stop: diff --git a/pick_input.py b/pick_input.py index 0666760..3722e99 100644 --- a/pick_input.py +++ b/pick_input.py @@ -5,12 +5,14 @@ import logging from pydub import AudioSegment from pydub.playback import play import os +import sys +import io +import random class Everything(str): def __ne__(self, __value: object) -> bool: return False - class PickInput: is_paused = True should_stop = False @@ -21,9 +23,10 @@ class PickInput: return { "required": { "number_of_inputs": ("INT", {"default": 2, "min": 1, "max": 10, "step": 1}), + "seed": ("INT", {"default": 1}), }, "hidden": { - **{f"input_{i}": (Everything("*"), {"forceInput": "True"}) for i in range(2, 11)} + **{f"input_{i}": (Everything("*"), {"forceInput": "True"}) for i in range(1, 11)} } } @@ -33,11 +36,32 @@ class PickInput: 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) + # Check if the operating system is Windows + if sys.platform.startswith('win'): + try: + # Load the audio file into memory + audio_file = os.path.join(os.path.dirname(__file__), 'bell.m4a') + + # Load the audio segment without writing to any temp files + sound = AudioSegment.from_file(audio_file, format="m4a") + + # Export the AudioSegment to a WAV file in memory + wav_io = io.BytesIO() + sound.export(wav_io, format='wav') + wav_data = wav_io.getvalue() + + # Play the WAV data using winsound + import winsound + winsound.PlaySound(wav_data, winsound.SND_MEMORY) + except Exception as e: + print(f"An error occurred: {e}") + else: + audio_file = os.path.join(os.path.dirname(__file__), 'bell.m4a') + sound = AudioSegment.from_file(audio_file, format="m4a") + play(sound) - def pick_input(self, **kwargs): + def pick_input(self, seed, **kwargs): + random.seed(seed) logging.info(f"Selected input at the start: {PickInput.selected_input}") self.play_audio() diff --git a/pyproject.toml b/pyproject.toml index f677e99..9196a1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "bjornulf_custom_nodes" description = "Nodes: Ollama, Text to Speech, Combine Texts, Random Texts, Save image for Bjornulf LobeChat, Text with random Seed, Random line from input, Combine images, Image to grayscale (black & white), Remove image Transparency (alpha), Resize Image, ..." -version = "0.32" +version = "0.33" license = {file = "LICENSE"} [project.urls] diff --git a/web/js/pause_resume_stop.js b/web/js/pause_resume_stop.js index 18dc805..fbe96ad 100644 --- a/web/js/pause_resume_stop.js +++ b/web/js/pause_resume_stop.js @@ -22,16 +22,12 @@ app.registerExtension({ }) .catch(error => console.error('Error:', error)); }); + + // Set seed widget to hidden input + const seedWidget = node.widgets.find((w) => w.name === "seed"); + if (seedWidget) { + seedWidget.type = "HIDDEN"; + } } } -}); - -// BASIC BUTTON -// app.registerExtension({ -// name: "Bjornulf.PauseResume", -// async nodeCreated(node) { -// if (node.comfyClass === "Bjornulf_PauseResume") { -// node.addWidget("button","Resume","Resume", (...args) => { console.log("lol"); } ) -// } -// } -// }); \ No newline at end of file +}); \ No newline at end of file diff --git a/web/js/pick_input.js b/web/js/pick_input.js index 27319e0..a58f598 100644 --- a/web/js/pick_input.js +++ b/web/js/pick_input.js @@ -4,33 +4,31 @@ app.registerExtension({ name: "Bjornulf.PickInput", async nodeCreated(node) { if (node.comfyClass === "Bjornulf_PickInput") { - const updateInputButtons = (numInputs) => { - // Remove all existing widgets - node.widgets.length = 1; - - // Re-add the number_of_inputs widget - // const numInputsWidget = node.addWidget("number", "Number of Inputs", "number_of_inputs", (v) => { - // updateInputs(); - // app.graph.setDirtyCanvas(true); - // return v; - // }, { min: 1, max: 10, step: 1, precision: 0 }); + // Remove only the dynamic widgets (input buttons and stop button) + node.widgets = node.widgets.filter((w) => !w.dynamicWidget); // Add new input buttons - for (let i = 1; i < numInputs + 1; i++) { - node.addWidget("button", `Input ${i}`, `input_button_${i}`, () => { - fetch(`/bjornulf_select_input_${i}`, { method: "GET" }) - .then((response) => response.text()) - .then((data) => { - console.log(`Input ${i} response:`, data); - // You can update the UI here if needed - }) - .catch((error) => console.error("Error:", error)); - }); + for (let i = 1; i <= numInputs; i++) { + const inputButton = node.addWidget( + "button", + `Input ${i}`, + `input_button_${i}`, + () => { + fetch(`/bjornulf_select_input_${i}`, { method: "GET" }) + .then((response) => response.text()) + .then((data) => { + console.log(`Input ${i} response:`, data); + // You can update the UI here if needed + }) + .catch((error) => console.error("Error:", error)); + } + ); + inputButton.dynamicWidget = true; // Tag as dynamic } - // Re-add the Stop button - node.addWidget("button", "Stop", "Stop", () => { + // Add the Stop button + const stopButton = node.addWidget("button", "Stop", "Stop", () => { fetch("/bjornulf_stop_pick", { method: "GET" }) .then((response) => response.text()) .then((data) => { @@ -39,6 +37,7 @@ app.registerExtension({ }) .catch((error) => console.error("Error:", error)); }); + stopButton.dynamicWidget = true; // Tag as dynamic node.setSize(node.computeSize()); }; @@ -61,7 +60,6 @@ app.registerExtension({ input.name.startsWith("input_") ); - // const Everything = Symbol('Everything'); // Determine if we need to add or remove inputs if (existingInputs.length < numInputs) { // Add new inputs if not enough existing @@ -86,12 +84,6 @@ app.registerExtension({ node.setSize(node.computeSize()); }; - // Set seed widget to hidden input - const seedWidget = node.widgets.find((w) => w.name === "seed"); - if (seedWidget) { - seedWidget.type = "HIDDEN"; - } - // Move number_of_inputs to the top initially const numInputsWidget = node.widgets.find( (w) => w.name === "number_of_inputs" @@ -109,6 +101,12 @@ app.registerExtension({ // Delay the initial update to ensure node is fully initialized setTimeout(updateInputs, 0); + + // Hide the seed widget + const seedWidget = node.widgets.find((w) => w.name === "seed"); + if (seedWidget) { + seedWidget.type = "HIDDEN"; + } } }, -}); \ No newline at end of file +}); diff --git a/web/js/random_image.js b/web/js/random_image.js index 09b00c3..f06620e 100644 --- a/web/js/random_image.js +++ b/web/js/random_image.js @@ -36,10 +36,10 @@ app.registerExtension({ }; // Set seed widget to hidden input - const seedWidget = node.widgets.find(w => w.name === "seed"); - if (seedWidget) { - seedWidget.type = "HIDDEN"; - } + // const seedWidget = node.widgets.find(w => w.name === "seed"); + // if (seedWidget) { + // seedWidget.type = "HIDDEN"; + // } // Move number_of_images to the top initially const numInputsWidget = node.widgets.find(w => w.name === "number_of_images");