From eed08ee1f439de830c609f17160544c28b553381 Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Mon, 23 Mar 2026 20:26:01 -0400 Subject: [PATCH 1/7] Added new parameters to Runware Audio Inference Settings node --- clientlibs/utils.js | 28 ++++++++ modules/audioInferenceInputs.py | 18 ++++- modules/audioSettings.py | 117 ++++++++++++++++++++++++++++++-- 3 files changed, 156 insertions(+), 7 deletions(-) diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 4fc3010..85721b8 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -1144,6 +1144,20 @@ function audioSettingsToggleHandler(settingsNode) { const turboWidget = settingsNode.widgets.find(w => w && w.name === "turbo"); const useTextNormalizationWidget = settingsNode.widgets.find(w => w && w.name === "useTextNormalization"); const textNormalizationWidget = settingsNode.widgets.find(w => w && w.name === "textNormalization"); + const useBpmWidget = settingsNode.widgets.find(w => w && w.name === "useBpm"); + const bpmWidget = settingsNode.widgets.find(w => w && w.name === "bpm"); + const useKeyScaleWidget = settingsNode.widgets.find(w => w && w.name === "useKeyScale"); + const keyScaleWidget = settingsNode.widgets.find(w => w && w.name === "keyScale"); + const useTimeSignatureWidget = settingsNode.widgets.find(w => w && w.name === "useTimeSignature"); + const timeSignatureWidget = settingsNode.widgets.find(w => w && w.name === "timeSignature"); + const useVocalLanguageWidget = settingsNode.widgets.find(w => w && w.name === "useVocalLanguage"); + const vocalLanguageWidget = settingsNode.widgets.find(w => w && w.name === "vocalLanguage"); + const useCoverConditioningScaleWidget = settingsNode.widgets.find(w => w && w.name === "useCoverConditioningScale"); + const coverConditioningScaleWidget = settingsNode.widgets.find(w => w && w.name === "coverConditioningScale"); + const useRepaintingStartWidget = settingsNode.widgets.find(w => w && w.name === "useRepaintingStart"); + const repaintingStartWidget = settingsNode.widgets.find(w => w && w.name === "repaintingStart"); + const useRepaintingEndWidget = settingsNode.widgets.find(w => w && w.name === "useRepaintingEnd"); + const repaintingEndWidget = settingsNode.widgets.find(w => w && w.name === "repaintingEnd"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; @@ -1167,6 +1181,13 @@ function audioSettingsToggleHandler(settingsNode) { if (useLanguageBoostWidget && languageBoostWidget) toggleWidgetState(useLanguageBoostWidget, languageBoostWidget, "languageBoost"); if (useTurboWidget && turboWidget) toggleWidgetState(useTurboWidget, turboWidget, "turbo"); if (useTextNormalizationWidget && textNormalizationWidget) toggleWidgetState(useTextNormalizationWidget, textNormalizationWidget, "textNormalization"); + if (useBpmWidget && bpmWidget) toggleWidgetState(useBpmWidget, bpmWidget, "bpm"); + if (useKeyScaleWidget && keyScaleWidget) toggleWidgetState(useKeyScaleWidget, keyScaleWidget, "keyScale"); + if (useTimeSignatureWidget && timeSignatureWidget) toggleWidgetState(useTimeSignatureWidget, timeSignatureWidget, "timeSignature"); + if (useVocalLanguageWidget && vocalLanguageWidget) toggleWidgetState(useVocalLanguageWidget, vocalLanguageWidget, "vocalLanguage"); + if (useCoverConditioningScaleWidget && coverConditioningScaleWidget) toggleWidgetState(useCoverConditioningScaleWidget, coverConditioningScaleWidget, "coverConditioningScale"); + if (useRepaintingStartWidget && repaintingStartWidget) toggleWidgetState(useRepaintingStartWidget, repaintingStartWidget, "repaintingStart"); + if (useRepaintingEndWidget && repaintingEndWidget) toggleWidgetState(useRepaintingEndWidget, repaintingEndWidget, "repaintingEnd"); } function videoSettingsToggleHandler(settingsNode) { @@ -4088,6 +4109,8 @@ function regionalPromptingRegionsToggleHandler(regionsNode) { function audioInferenceInputsToggleHandler(audioInputsNode) { // Find widgets + const useAudioWidget = audioInputsNode.widgets.find(w => w.name === "useAudio"); + const audioWidget = audioInputsNode.widgets.find(w => w.name === "Audio"); const useVideoWidget = audioInputsNode.widgets.find(w => w.name === "useVideo"); const videoWidget = audioInputsNode.widgets.find(w => w.name === "Video"); const useVideosWidget = audioInputsNode.widgets.find(w => w.name === "useVideos"); @@ -4134,6 +4157,11 @@ function audioInferenceInputsToggleHandler(audioInputsNode) { setTimeout(toggleEnabled, 100); } + // Set up toggle handler for single audio + if (useAudioWidget && audioWidget) { + toggleWidgetState(useAudioWidget, audioWidget, "Audio"); + } + // Set up toggle handler for single video if (useVideoWidget && videoWidget) { toggleWidgetState(useVideoWidget, videoWidget, "Video"); diff --git a/modules/audioInferenceInputs.py b/modules/audioInferenceInputs.py index 7d670b7..524ffca 100644 --- a/modules/audioInferenceInputs.py +++ b/modules/audioInferenceInputs.py @@ -10,6 +10,14 @@ class audioInferenceInputs: @classmethod def INPUT_TYPES(cls): optionalInputs = { + "useAudio": ("BOOLEAN", { + "tooltip": "Enable to include single audio input in API request.", + "default": False, + }), + "Audio": ("STRING", { + "tooltip": "Audio URL or mediaUUID for audio generation. Can be a direct URL or a mediaUUID from Runware Media Upload node. Only used when 'Use Audio' is enabled.", + "default": "", + }), "useVideo": ("BOOLEAN", { "tooltip": "Enable to include single video input in API request.", "default": False, @@ -37,7 +45,7 @@ class audioInferenceInputs: "optional": optionalInputs } - DESCRIPTION = "Configure custom inputs for Runware Audio Inference, including single or multiple video inputs for audio extraction or generation." + DESCRIPTION = "Configure custom inputs for Runware Audio Inference, including optional audio URL/mediaUUID, and single or multiple video inputs for audio extraction or generation." FUNCTION = "createInputs" RETURN_TYPES = ("RUNWAREAUDIOINFERENCEINPUTS",) RETURN_NAMES = ("Audio Inference Inputs",) @@ -45,12 +53,18 @@ class audioInferenceInputs: def createInputs(self, **kwargs) -> tuple[Dict[str, Any]]: """Create audio inference inputs from provided parameters""" + useAudio = kwargs.get("useAudio", False) + audio = kwargs.get("Audio", None) useVideo = kwargs.get("useVideo", False) video = kwargs.get("Video", None) useVideos = kwargs.get("useVideos", False) inputs = {} - + + # Handle single audio (inputs.audio) + if useAudio and audio is not None and audio.strip() != "": + inputs["audio"] = audio.strip() + # Handle single video (inputs.video) if useVideo and video is not None and video.strip() != "": inputs["video"] = video.strip() diff --git a/modules/audioSettings.py b/modules/audioSettings.py index 4f4810c..69e2f22 100644 --- a/modules/audioSettings.py +++ b/modules/audioSettings.py @@ -1,14 +1,22 @@ """ Runware Audio Inference Settings Node -Provides lyrics, guidanceType, languageBoost, turbo, temperature, and textNormalization -settings for Runware Audio Inference. +Provides lyrics, guidanceType, languageBoost, turbo, temperature, textNormalization, +bpm, keyScale, timeSignature, vocalLanguage, coverConditioningScale, repaintingStart, +and repaintingEnd for Runware Audio Inference. """ from typing import Dict, Any +_VOCAL_LANGUAGE_CODES = [ + "ar", "az", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "es", "fa", "fi", "fr", + "he", "hi", "hr", "ht", "hu", "id", "is", "it", "ja", "ko", "la", "lt", "ms", "ne", + "nl", "no", "pa", "pl", "pt", "ro", "ru", "sa", "sk", "sr", "sv", "sw", "ta", "te", + "th", "tl", "tr", "uk", "ur", "vi", "yue", "zh", "unknown", +] + class RunwareAudioSettings: - """Runware Audio Inference Settings Node (lyrics, guidanceType, languageBoost, turbo, temperature, textNormalization).""" + """Runware Audio Inference Settings Node.""" @classmethod def INPUT_TYPES(cls): @@ -41,7 +49,7 @@ class RunwareAudioSettings: "default": False, }), "guidanceType": (["apg", "cfg"], { - "tooltip": "Controls how the guidance value is used. apg = Adversarial Perceptual Guidance, cfg = Classifier-Free Guidance", + "tooltip": "Controls how the guidance value is used. See API GuidanceType: apg | cfg.", "default": "apg", }), "useLanguageBoost": ("BOOLEAN", { @@ -76,6 +84,70 @@ class RunwareAudioSettings: "label_on": "true", "label_off": "false", }), + "useBpm": ("BOOLEAN", { + "tooltip": "Enable to include bpm (tempo) in audio generation settings. If disabled, the model decides automatically.", + "default": False, + }), + "bpm": ("INT", { + "tooltip": "Beats per minute (30–300). If not set via API, the model decides. Common: 60–80 ballad, 90–110 pop, 120–130 house, 140–170 DnB. Only used when 'Use Bpm' is enabled.", + "default": 120, + "min": 30, + "max": 300, + "step": 1, + }), + "useKeyScale": ("BOOLEAN", { + "tooltip": "Enable to include keyScale (musical key and scale). Empty value lets the model decide.", + "default": False, + }), + "keyScale": ("STRING", { + "default": "", + "tooltip": "Musical key and scale. Empty string lets the model decide. Format: '{Note}{Accidental} {Mode}' (Note A–G, Accidental '' | '#' | 'b' | '♯' | '♭', Mode 'major' | 'minor'). Examples: 'C major', 'F# minor', 'B♭ major'.", + }), + "useTimeSignature": ("BOOLEAN", { + "tooltip": "Enable to include timeSignature (beats per measure). If disabled, the model decides automatically.", + "default": False, + }), + "timeSignature": (["", "2", "3", "4", "6"], { + "tooltip": "Time signature: '2' duple, '3' waltz, '4' common time, '6' compound duple. Empty = model decides. Most pop uses '4'. Only used when 'Use Time Signature' is enabled.", + "default": "", + }), + "useVocalLanguage": ("BOOLEAN", { + "tooltip": "Enable to include vocalLanguage (ISO 639-1) for vocal generation.", + "default": False, + }), + "vocalLanguage": (_VOCAL_LANGUAGE_CODES, { + "tooltip": "ISO 639-1 language code for vocals. Use 'unknown' for instrumental or automatic detection. Only used when 'Use Vocal Language' is enabled.", + "default": "en", + }), + "useCoverConditioningScale": ("BOOLEAN", { + "tooltip": "Enable to include coverConditioningScale (source-audio conditioning fraction for cover tasks). Only effective when input audio is provided.", + "default": False, + }), + "coverConditioningScale": ("FLOAT", { + "tooltip": "Fraction of denoising steps using source-audio conditioning (cover task). 1.0 = all steps; 0.5 = first half source then text-only. Only used when 'Use Cover Conditioning Scale' is enabled.", + "default": 1.0, + "min": 0.0, + "max": 1.0, + "step": 0.01, + }), + "useRepaintingStart": ("BOOLEAN", { + "tooltip": "Enable to include repaintingStart (seconds). Requires input audio. Sets repaint region with repaintingEnd; negative values prepend (outpaint before start).", + "default": False, + }), + "repaintingStart": ("FLOAT", { + "tooltip": "Start time in seconds for repaint/inpaint/outpaint region. Only used when 'Use Repainting Start' is enabled.", + "default": 0.0, + "step": 0.01, + }), + "useRepaintingEnd": ("BOOLEAN", { + "tooltip": "Enable to include repaintingEnd (seconds). Requires input audio. Values beyond source duration append (outpaint).", + "default": False, + }), + "repaintingEnd": ("FLOAT", { + "tooltip": "End time in seconds for repaint region. Only used when 'Use Repainting End' is enabled.", + "default": 0.0, + "step": 0.01, + }), } } @@ -83,7 +155,7 @@ class RunwareAudioSettings: RETURN_NAMES = ("settings",) FUNCTION = "createSettings" CATEGORY = "Runware/Audio" - DESCRIPTION = "Configure audio generation settings (lyrics, guidanceType, languageBoost, turbo, temperature, textNormalization) for Runware Audio Inference. Connect to Runware Audio Inference node." + DESCRIPTION = "Configure audio generation settings (lyrics, guidanceType, languageBoost, turbo, temperature, textNormalization, bpm, keyScale, timeSignature, vocalLanguage, coverConditioningScale, repaintingStart, repaintingEnd) for Runware Audio Inference. Connect to Runware Audio Inference node." def createSettings(self, **kwargs) -> tuple[Dict[str, Any]]: """Create audio settings dict for API""" @@ -99,6 +171,20 @@ class RunwareAudioSettings: turbo = kwargs.get("turbo", False) use_text_normalization = kwargs.get("useTextNormalization", False) text_normalization = kwargs.get("textNormalization", True) + use_bpm = kwargs.get("useBpm", False) + bpm = kwargs.get("bpm", 120) + use_key_scale = kwargs.get("useKeyScale", False) + key_scale = kwargs.get("keyScale", "") + use_time_signature = kwargs.get("useTimeSignature", False) + time_signature = kwargs.get("timeSignature", "") + use_vocal_language = kwargs.get("useVocalLanguage", False) + vocal_language = kwargs.get("vocalLanguage", "en") + use_cover_conditioning_scale = kwargs.get("useCoverConditioningScale", False) + cover_conditioning_scale = kwargs.get("coverConditioningScale", 1.0) + use_repainting_start = kwargs.get("useRepaintingStart", False) + repainting_start = kwargs.get("repaintingStart", 0.0) + use_repainting_end = kwargs.get("useRepaintingEnd", False) + repainting_end = kwargs.get("repaintingEnd", 0.0) settings: Dict[str, Any] = {} @@ -120,6 +206,27 @@ class RunwareAudioSettings: if use_text_normalization: settings["textNormalization"] = bool(text_normalization) + if use_bpm: + settings["bpm"] = int(bpm) + + if use_key_scale: + settings["keyScale"] = key_scale if key_scale is not None else "" + + if use_time_signature: + settings["timeSignature"] = time_signature + + if use_vocal_language: + settings["vocalLanguage"] = vocal_language + + if use_cover_conditioning_scale: + settings["coverConditioningScale"] = round(float(cover_conditioning_scale), 2) + + if use_repainting_start: + settings["repaintingStart"] = round(float(repainting_start), 2) + + if use_repainting_end: + settings["repaintingEnd"] = round(float(repainting_end), 2) + return (settings,) From cc695dd138925b3d5f0526fb251ec52a30bc7439 Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Tue, 24 Mar 2026 16:17:49 -0400 Subject: [PATCH 2/7] Fixed conditional statemnets --- clientlibs/utils.js | 12 ++++++------ modules/audioSettings.py | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 85721b8..1910887 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -4109,11 +4109,11 @@ function regionalPromptingRegionsToggleHandler(regionsNode) { function audioInferenceInputsToggleHandler(audioInputsNode) { // Find widgets - const useAudioWidget = audioInputsNode.widgets.find(w => w.name === "useAudio"); - const audioWidget = audioInputsNode.widgets.find(w => w.name === "Audio"); - const useVideoWidget = audioInputsNode.widgets.find(w => w.name === "useVideo"); - const videoWidget = audioInputsNode.widgets.find(w => w.name === "Video"); - const useVideosWidget = audioInputsNode.widgets.find(w => w.name === "useVideos"); + const useAudioWidget = audioInputsNode.widgets.find(w => w && w.name === "useAudio"); + const audioWidget = audioInputsNode.widgets.find(w => w && w.name === "Audio"); + const useVideoWidget = audioInputsNode.widgets.find(w => w && w.name === "useVideo"); + const videoWidget = audioInputsNode.widgets.find(w => w && w.name === "Video"); + const useVideosWidget = audioInputsNode.widgets.find(w => w && w.name === "useVideos"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { @@ -4173,7 +4173,7 @@ function audioInferenceInputsToggleHandler(audioInputsNode) { const enabled = useVideosWidget.value === true; for (let i = 1; i <= 4; i++) { - const videoWidget = audioInputsNode.widgets.find(w => w.name === `Video${i}`); + const videoWidget = audioInputsNode.widgets.find(w => w && w.name === `Video${i}`); if (videoWidget) { if (videoWidget.inputEl) { videoWidget.inputEl.disabled = !enabled; diff --git a/modules/audioSettings.py b/modules/audioSettings.py index 69e2f22..173638a 100644 --- a/modules/audioSettings.py +++ b/modules/audioSettings.py @@ -112,11 +112,11 @@ class RunwareAudioSettings: "default": "", }), "useVocalLanguage": ("BOOLEAN", { - "tooltip": "Enable to include vocalLanguage (ISO 639-1) for vocal generation.", + "tooltip": "Enable to include vocalLanguage (language code) for vocal generation. See dropdown for available codes.", "default": False, }), "vocalLanguage": (_VOCAL_LANGUAGE_CODES, { - "tooltip": "ISO 639-1 language code for vocals. Use 'unknown' for instrumental or automatic detection. Only used when 'Use Vocal Language' is enabled.", + "tooltip": "Language code for vocals. Supports values from the dropdown list (including 'yue', 'zh', and 'unknown'). Use 'unknown' for instrumental or automatic detection. Only used when 'Use Vocal Language' is enabled.", "default": "en", }), "useCoverConditioningScale": ("BOOLEAN", { @@ -212,7 +212,7 @@ class RunwareAudioSettings: if use_key_scale: settings["keyScale"] = key_scale if key_scale is not None else "" - if use_time_signature: + if use_time_signature and str(time_signature).strip(): settings["timeSignature"] = time_signature if use_vocal_language: From acf9e0455929551da8662b75422e02503d63cc2d Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Tue, 24 Mar 2026 16:20:24 -0400 Subject: [PATCH 3/7] Fixed conditional statemnets --- modules/audioSettings.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/audioSettings.py b/modules/audioSettings.py index 173638a..17dc689 100644 --- a/modules/audioSettings.py +++ b/modules/audioSettings.py @@ -209,11 +209,11 @@ class RunwareAudioSettings: if use_bpm: settings["bpm"] = int(bpm) - if use_key_scale: - settings["keyScale"] = key_scale if key_scale is not None else "" + if use_key_scale and str(key_scale).strip(): + settings["keyScale"] = str(key_scale).strip() if use_time_signature and str(time_signature).strip(): - settings["timeSignature"] = time_signature + settings["timeSignature"] = str(time_signature).strip() if use_vocal_language: settings["vocalLanguage"] = vocal_language From dd6a8f0d9c0f970fee719343d9c4136d61e76dc7 Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Thu, 26 Mar 2026 22:07:16 -0400 Subject: [PATCH 4/7] Fixed param types --- clientlibs/utils.js | 2 ++ modules/audioModelSearch.py | 2 ++ modules/audioSettings.py | 15 +++++++++------ modules/utils/runwareUtils.py | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 1910887..7c61ce3 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -2789,6 +2789,8 @@ function audioModelSearchFilterHandler(audioModelSearchNode) { ], "Ace": [ "runware:ace-step@0 (ACE Step v1 3.5B)", + "runware:ace-step@v1.5-base (ACE-Step v1.5 Base)", + "runware:ace-step@v1.5-turbo (ACE-Step v1.5 Turbo)", ], "Dia": [ "runware:dia@v1.0 (Dia 1.6B)", diff --git a/modules/audioModelSearch.py b/modules/audioModelSearch.py index 7e3a607..e5f881b 100644 --- a/modules/audioModelSearch.py +++ b/modules/audioModelSearch.py @@ -16,6 +16,8 @@ class RunwareAudioModelSearch: ], "Ace": [ "runware:ace-step@0 (ACE Step v1 3.5B)", + "runware:ace-step@v1.5-base (ACE-Step v1.5 Base)", + "runware:ace-step@v1.5-turbo (ACE-Step v1.5 Turbo)", ], "Dia": [ "runware:dia@v1.0 (Dia 1.6B)", diff --git a/modules/audioSettings.py b/modules/audioSettings.py index 17dc689..bfba7fe 100644 --- a/modules/audioSettings.py +++ b/modules/audioSettings.py @@ -107,9 +107,12 @@ class RunwareAudioSettings: "tooltip": "Enable to include timeSignature (beats per measure). If disabled, the model decides automatically.", "default": False, }), - "timeSignature": (["", "2", "3", "4", "6"], { - "tooltip": "Time signature: '2' duple, '3' waltz, '4' common time, '6' compound duple. Empty = model decides. Most pop uses '4'. Only used when 'Use Time Signature' is enabled.", - "default": "", + "timeSignature": ("INT", { + "default": 4, + "min": 1, + "max": 32, + "step": 1, + "tooltip": "Time signature as integer beats per bar (e.g. 2, 3, 4, 6). Only used when 'Use Time Signature' is enabled.", }), "useVocalLanguage": ("BOOLEAN", { "tooltip": "Enable to include vocalLanguage (language code) for vocal generation. See dropdown for available codes.", @@ -176,7 +179,7 @@ class RunwareAudioSettings: use_key_scale = kwargs.get("useKeyScale", False) key_scale = kwargs.get("keyScale", "") use_time_signature = kwargs.get("useTimeSignature", False) - time_signature = kwargs.get("timeSignature", "") + time_signature = kwargs.get("timeSignature", 4) use_vocal_language = kwargs.get("useVocalLanguage", False) vocal_language = kwargs.get("vocalLanguage", "en") use_cover_conditioning_scale = kwargs.get("useCoverConditioningScale", False) @@ -212,8 +215,8 @@ class RunwareAudioSettings: if use_key_scale and str(key_scale).strip(): settings["keyScale"] = str(key_scale).strip() - if use_time_signature and str(time_signature).strip(): - settings["timeSignature"] = str(time_signature).strip() + if use_time_signature: + settings["timeSignature"] = int(time_signature) if use_vocal_language: settings["vocalLanguage"] = vocal_language diff --git a/modules/utils/runwareUtils.py b/modules/utils/runwareUtils.py index 97000e7..07f5983 100644 --- a/modules/utils/runwareUtils.py +++ b/modules/utils/runwareUtils.py @@ -158,7 +158,7 @@ def getCustomEndpoint(): custom_endpoint = os.getenv("RUNWARE_CUSTOM_ENDPOINT") if custom_endpoint and isinstance(custom_endpoint, str): return custom_endpoint - return "https://api.runware.ai/v1" + return "https://api.runware.dev/v1" SESSION_TIMEOUT = getTimeout() RUNWARE_API_KEY = getAPIKey() From 052356238f8f998d233dc49fb8e2e95c5bad25bb Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Thu, 26 Mar 2026 22:08:23 -0400 Subject: [PATCH 5/7] Fixed endpoint --- modules/utils/runwareUtils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/utils/runwareUtils.py b/modules/utils/runwareUtils.py index 07f5983..97000e7 100644 --- a/modules/utils/runwareUtils.py +++ b/modules/utils/runwareUtils.py @@ -158,7 +158,7 @@ def getCustomEndpoint(): custom_endpoint = os.getenv("RUNWARE_CUSTOM_ENDPOINT") if custom_endpoint and isinstance(custom_endpoint, str): return custom_endpoint - return "https://api.runware.dev/v1" + return "https://api.runware.ai/v1" SESSION_TIMEOUT = getTimeout() RUNWARE_API_KEY = getAPIKey() From 3b800132471e12c095d62f7b0152cfc3c92b3ffd Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Thu, 26 Mar 2026 22:16:47 -0400 Subject: [PATCH 6/7] audio widget handling --- clientlibs/utils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 7c61ce3..7669e43 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -4110,6 +4110,8 @@ function regionalPromptingRegionsToggleHandler(regionsNode) { } function audioInferenceInputsToggleHandler(audioInputsNode) { + if (!audioInputsNode?.widgets) return; + // Find widgets const useAudioWidget = audioInputsNode.widgets.find(w => w && w.name === "useAudio"); const audioWidget = audioInputsNode.widgets.find(w => w && w.name === "Audio"); From 13906ad1a21a58dcf8d6b8b8f22d41d891448606 Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Fri, 27 Mar 2026 16:09:04 -0400 Subject: [PATCH 7/7] Removed rounding off --- clientlibs/utils.js | 20 +++++++++++++++++--- modules/audioSettings.py | 6 +++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 7669e43..0e23548 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -8,6 +8,9 @@ const TIMEOUT_RANGE = { min: 5, default: 90, max: 99 }; const OUTPUT_QUALITY_RANGE = { min: 20, default: 95, max: 99 }; const CACHE_SIZE_RANGE = { min: 30, default: 150, max: 4096 }; +/** Must match `audioInferenceInputs.MAX_VIDEOS` in modules/audioInferenceInputs.py */ +const AUDIO_INFERENCE_INPUTS_MAX_VIDEOS = 4; + let openDialog = false; let lastTimeout = false; let lastOutputFormat = false; @@ -4171,12 +4174,23 @@ function audioInferenceInputsToggleHandler(audioInputsNode) { toggleWidgetState(useVideoWidget, videoWidget, "Video"); } - // Set up toggle handlers for multiple videos (Video1, Video2, Video3, Video4) + // Set up toggle handlers for multiple videos (Video1 … VideoN; N from widgets, fallback to AUDIO_INFERENCE_INPUTS_MAX_VIDEOS) if (useVideosWidget) { + function getAudioInferenceVideoSlotCount() { + let max = 0; + for (const w of audioInputsNode.widgets) { + if (!w?.name) continue; + const m = /^Video(\d+)$/.exec(w.name); + if (m) max = Math.max(max, parseInt(m[1], 10)); + } + return max > 0 ? max : AUDIO_INFERENCE_INPUTS_MAX_VIDEOS; + } + function toggleVideosEnabled() { const enabled = useVideosWidget.value === true; - - for (let i = 1; i <= 4; i++) { + const slotCount = getAudioInferenceVideoSlotCount(); + + for (let i = 1; i <= slotCount; i++) { const videoWidget = audioInputsNode.widgets.find(w => w && w.name === `Video${i}`); if (videoWidget) { if (videoWidget.inputEl) { diff --git a/modules/audioSettings.py b/modules/audioSettings.py index bfba7fe..e5a7151 100644 --- a/modules/audioSettings.py +++ b/modules/audioSettings.py @@ -222,13 +222,13 @@ class RunwareAudioSettings: settings["vocalLanguage"] = vocal_language if use_cover_conditioning_scale: - settings["coverConditioningScale"] = round(float(cover_conditioning_scale), 2) + settings["coverConditioningScale"] = float(cover_conditioning_scale) if use_repainting_start: - settings["repaintingStart"] = round(float(repainting_start), 2) + settings["repaintingStart"] = float(repainting_start) if use_repainting_end: - settings["repaintingEnd"] = round(float(repainting_end), 2) + settings["repaintingEnd"] = float(repainting_end) return (settings,)