[Nodes] Moved the image downloader

To ComfyUI-ImageMisc
This commit is contained in:
Salvador E. Tropea
2025-07-21 09:11:03 -03:00
parent 1460083f23
commit fe0f05bee8
2 changed files with 5 additions and 129 deletions
+5 -26
View File
@@ -45,8 +45,6 @@ workflows, especially when dealing with multiple audio inputs or outputs.
- [15. Audio Normalize (Peak)](#15-audio-normalize-peak)
- [16. Audio Apply Batched Gain](#16-audio-apply-batched-gain)
- [17. Audio Download and Load](#17-audio-download-and-load)
- ✨ [Extra nodes](#-extra-nodes)
- [1. Image Download and Load](#1-image-download-and-load)
- 📝 [Usage Notes](#-usage-notes)
- 🛠️ [Future Improvements / TODO](#️-future-improvements--todo)
- 📜 [Project History](#-project-history)
@@ -323,28 +321,6 @@ workflows, especially when dealing with multiple audio inputs or outputs.
- **Player**: This node uses an `AUDIO_UI` widget to allow playing the downloaded song.
## ✨ Extra nodes
These nodes are just complements for the other nodes. I.e. they share a lot of code.
### 1. Image Download and Load
- **Display Name:** `Image Download and Load`
- **Internal Name:** `SET_ImageDownload`
- **Category:** `image/io`
- **Description:** Downloads an image file from a URL into the `ComfyUI/input/` directory if it's not already there, and then loads it as an image and mask. This is perfect for creating self-contained, shareable workflows with example image.
- **Inputs:**
- `image_bypass` (IMAGE, Optional): If an image is provided here it will be used for the output. You can connect a `Load Image` node here, if the connected node is muted (bypassed) we download the file, otherwise we use the image from the `Load Image` node.
- `mask_bypass` (MASK, Optional): This input complements `image_bypass`.
- `base_url` (STRING): The URL of the directory containing the image file.
- `filename` (STRING): The name of the image file to download (e.g., photo.jpg, art.png).
- **Output:**
- `image` (IMAGE): The loaded image.
- `alpha_mask` (MASK): The alpha mask for the loaded image.
- **Behavior Details:**
- **Caching:** The node checks the `ComfyUI/input/` folder first. If the file with the specified `filename` already exists, the download is skipped.
- **Bypass:** If only one of `image_bypass` and `mask_bypass` is connected the other will be assumed to be empty. You should connect both or avoid using the output corresponding to the unconnected input.
## 🚀 Installation
You can install the nodes from the ComfyUI nodes manager, the name is *Audio Batch*, or just do it manually:
@@ -356,19 +332,22 @@ You can install the nodes from the ComfyUI nodes manager, the name is *Audio Bat
```
2. Restart ComfyUI.
The nodes should then appear under the "audio/batch" and "audio/conversion" categories in the "Add Node" menu.
The nodes should then appear under the "audio/batch", "audio/conversion","audio/manipulation", "audio/generation" and "audio/io" categories in the "Add Node" menu.
## 📦 Dependencies
- PyTorch
- Torchaudio (for resampling and potentially other audio operations)
- NumPy (often used with audio data)
- Requests (optional): Usually an indirect ComfyUI dependency. If installed it will be used for downloads, it should be more robust than then built-in `urllib`, used as fallback.
- Colorama (optional): Might help to get colored log messages on some terminals. We use ANSI escape sequences when it isn't installed.
These are typically already present in a standard ComfyUI environment.
## 🖼️ Examples
Once installed the examples are available in the ComfyUI workflow templates, in the *Audio Batch* section.
Once installed the examples are available in the ComfyUI workflow templates, in the *Audio Batch* section (or ComfyUI-AudioBatch).
- [audio_batch_select_example.json](example_workflows/audio_batch_select_example.json): Shows how to create a batch and
how to extract a single element from the batch.
-103
View File
@@ -21,12 +21,6 @@ except ModuleNotFoundError:
# No ComfyUI, this is a test environment
def get_input_directory():
return ""
try:
# We need to import the built-in LoadImage class for ImageDownload
from nodes import LoadImage # type: ignore[attr-defined]
has_load_image = True
except Exception:
has_load_image = False
logger = main_logger
BASE_CATEGORY = "audio"
@@ -1149,100 +1143,3 @@ class AudioDownload:
except Exception as e:
logger.error(f"Failed to load or process audio file '{local_filepath}': {e}", exc_info=True)
raise IOError(f"Could not load or process the audio file: {filename}. It may be missing or corrupt.") from e
if has_load_image:
class ImageDownload:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"base_url": ("STRING", {
"default":
"https://raw.githubusercontent.com/set-soft/AudioSeparation/refs/heads/main/example_workflows/",
"tooltip": "The base URL where the image file is located."
}),
"filename": ("STRING", {
"default": "audioseparation_logo.jpg",
"tooltip": "The name of the image file to download (e.g., photo.jpg, art.png)."
}),
},
"optional": {
"image_bypass": ("IMAGE", {
"tooltip": "If this image is present will be used instead of the downloaded one"
}),
"mask_bypass": ("MASK", {"tooltip": "If this mask is present will be used instead of the downloaded one"}),
}
}
RETURN_TYPES = ("IMAGE", "MASK")
RETURN_NAMES = ("image", "alpha_mask")
FUNCTION = "load_or_download_image"
CATEGORY = "image" + "/" + IO_CATEGORY
DESCRIPTION = ("Downloads an image to ComfyUI's 'input' directory if it doesn't exist, then loads it using the "
"built-in LoadImage logic.")
UNIQUE_NAME = "SET_ImageDownload"
DISPLAY_NAME = "Image Download and Load"
OUTPUT_NODE = True
def load_or_download_image(self, base_url: str, filename: str, image_bypass: Optional[torch.Tensor] = None,
mask_bypass: Optional[torch.Tensor] = None):
# If we have something at the bypass inputs use it
if image_bypass is not None or mask_bypass is not None:
if image_bypass is None:
# Just a mask
assert mask_bypass is not None, "This should not be possible if image_bypass is None" # For mypy
image_bypass = torch.zeros(mask_bypass.shape + (3,), dtype=torch.float32, device="cpu")
logger.warning("ImageDownload: Returning an empty image")
elif mask_bypass is None:
# This is ComfyUI behavior when we don't have transparency
mask_bypass = torch.zeros((64, 64), dtype=torch.float32, device="cpu").unsqueeze(0)
logger.warning("ImageDownload: Returning an empty mask")
return (image_bypass, mask_bypass)
save_dir = get_input_directory()
local_filepath = os.path.join(save_dir, filename)
if not os.path.exists(local_filepath):
logger.info(f"File '{filename}' not found locally. Attempting to download.")
if not base_url.endswith('/'):
base_url += '/'
download_url = base_url + filename
try:
download_model(url=download_url, save_dir=save_dir, file_name=filename, kind="image")
except Exception as e:
logger.error(f"Download failed for {download_url}: {e}", exc_info=True)
raise
else:
logger.info(f"Found existing file, skipping download: '{local_filepath}'")
# --- REUSE ComfyUI's LoadImage LOGIC ---
try:
# Instantiate the built-in LoadImage node
loader_instance = LoadImage()
# The LoadImage node's `load_image` method expects the filename as passed
# by the ComfyUI widget, which is just the filename. It internally
# resolves the path using folder_paths.
logger.debug(f"Calling built-in LoadImage.load_image() with filename: '{filename}'")
# Call the method and return its result directly
result = loader_instance.load_image(filename)
downloaded_file = {
"images": [{
"filename": filename,
"subfolder": "",
"type": "input" # We stored the file in the "input" folder
}]
}
return {"ui": downloaded_file, "result": result}
except Exception as e:
logger.error(f"Failed to load image '{filename}' using built-in LoadImage node: {e}", exc_info=True)
# Re-raise to make the error visible in ComfyUI
raise IOError(f"Could not load the image file '{filename}' using the standard loader. "
"It may be corrupt or in an unsupported format.") from e