[Audio Download][Added] Notification in the GUI when we download

- In addition to the progress
- Now we also show warnings and errors in the regular GUI, not just
  the console.
This commit is contained in:
Salvador E. Tropea
2025-07-18 19:39:21 -03:00
parent 8b8536dd60
commit 67b3beb2c3
4 changed files with 130 additions and 2 deletions
+32
View File
@@ -0,0 +1,32 @@
// Copyright (c) 2025 Salvador E. Tropea
// Copyright (c) 2025 Instituto Nacional de Tecnología Industrial
// License: GPLv3
// Project: ComfyUI-AudioBatch
// This script adds an event named "set-audiobatch-toast"
// Used to notify the user in the GUI using the Toast API
import { app } from "/scripts/app.js";
// Register a new extension
app.registerExtension({
name: "SET.AudioBatch.ToastHandler", // Unique name
// The setup function is executed when the extension is loaded
setup() {
// Add a listener for our custom event
app.api.addEventListener("set-audiobatch-toast", (event) => {
// The data from Python is in event.detail
const { message, summary, severity } = event.detail;
// Use the ComfyUI toast API to show the message
// app.ui.toast.addMessage is the modern way to do this
app.extensionManager.toast.add({
severity: severity,
summary: summary,
detail: message,
life: 6000
});
});
},
});
+3 -1
View File
@@ -14,6 +14,7 @@ from .utils.logger import main_logger
from .utils.misc import parse_time_to_seconds, parse_note_to_frequency
from .utils.downmix import spectral_downmix
from .utils.downloader import download_model
from .utils.comfy_notification import send_toast_notification
try:
from folder_paths import get_input_directory # To get the ComfyUI input directory
except ModuleNotFoundError:
@@ -1083,13 +1084,14 @@ class AudioDownload:
if not base_url.endswith('/'):
base_url += '/'
download_url = base_url + filename
send_toast_notification(f"Downloading `{filename}`", "Download")
# --- Use your existing download_model function ---
try:
download_model(url=download_url, save_dir=save_dir, file_name=filename)
except Exception as e:
logger.error(f"Download failed for {download_url}: {e}", exc_info=True)
raise # Re-raise to stop the workflow and show the error
send_toast_notification("Finished downloading", "Download", 'success')
else:
logger.info(f"Found existing file, skipping download: '{local_filepath}'")
+47
View File
@@ -0,0 +1,47 @@
# Copyright (c) 2025 Salvador E. Tropea
# Copyright (c) 2025 Instituto Nacional de Tecnología Industrial
# License: GPLv3
# Project: ComfyUI-AudioBatch
#
# ComfyUI Toast API messages
# Original code from Gemini 2.5 Pro, which was really outdated
# Took ideas from Easy Use nodes and looking at ComfyUI code
import logging
from typing import Optional
# ComfyUI imports
try:
from server import PromptServer
with_comfy = True
except Exception:
with_comfy = False
# Local imports
from .misc import NODES_NAME
logger = logging.getLogger(f"{NODES_NAME}.comfy_notification")
def send_toast_notification(message: str, summary: str = "Warning", severity: str = "warn", sid: Optional[str] = None):
"""
Sends a toast notification event to the ComfyUI client.
Args:
message (str): The message content of the toast.
severity (str): The type of toast. Can be 'success' | 'info' | 'warn' | 'error' | 'secondary' | 'contrast'
summary (str): Short explanation
sid (str, optional): The session ID of the client to send to.
If None, broadcasts to all clients. Defaults to None.
"""
if not with_comfy:
return
try:
PromptServer.instance.send_sync(
"set-audioseparation-toast", # This is our custom event name
{
'message': message,
'summary': summary,
'severity': severity
},
sid
)
except Exception as e:
logger.error(f"when trying to use ComfyUI PromptServer: {e}")
+48 -1
View File
@@ -6,8 +6,9 @@ from __future__ import annotations # Good practice
import logging
import os
import sys
from typing import Any
from typing import Any, Callable
from .misc import NODES_NAME, NODES_DEBUG_VAR
from .comfy_notification import send_toast_notification
# 1. Initialize variables with the `Any` type.
@@ -56,10 +57,56 @@ class CustomFormatter(logging.Formatter):
return formatter.format(record)
def on_log_error_or_warning(record: logging.LogRecord) -> None:
"""
This function is called whenever a log with level WARNING or higher is emitted.
The 'record' object contains all information about the log event.
"""
if record.levelno == logging.WARNING:
summary = "Warning"
severity = "warn"
else:
summary = "Error"
severity = "error"
send_toast_notification(record.getMessage(), summary=summary, severity=severity)
class WarningAndErrorFilter(logging.Filter):
"""
A custom log filter that intercepts logs of a certain level.
"""
def __init__(self, callback: Callable, level: int = logging.WARNING):
"""
Initializes the filter.
Args:
callback: The function to call when a log record meets the level criteria.
level: The minimum level to trigger the callback.
"""
super().__init__()
self._callback = callback
self._level = level
def filter(self, record: logging.LogRecord) -> bool:
"""
This method is called for every log record.
"""
# Check if the log level is WARNING or higher
if record.levelno >= self._level:
self._callback(record)
# Always return True to ensure the log is always processed
# by the handlers after this filter.
return True
# Create a new logger
logger = logging.getLogger(NODES_NAME)
logger.propagate = False
# Add the custom filter to the logger.
logger.addFilter(WarningAndErrorFilter(callback=on_log_error_or_warning))
# Add handler if we don't have one.
if not logger.handlers:
handler = logging.StreamHandler(sys.stdout)