From 0801cceac4d65963cc34144d01a09cd8bf58d1af Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Sun, 5 Apr 2026 08:02:28 +0530 Subject: [PATCH] Added voiceDescription --- clientlibs/utils.js | 3 +++ modules/utils/runwareUtils.py | 2 +- modules/videoInference.py | 4 ++-- modules/videoInferenceSpeechInput.py | 12 +++++++----- modules/videoSettings.py | 20 ++++++++++++++++++-- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 8bdeb18..58bdefd 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -1359,6 +1359,8 @@ function videoSettingsToggleHandler(settingsNode) { const removeBackgroundWidget = settingsNode.widgets.find(w => w && w.name === "removeBackground"); const useExpressivenessWidget = settingsNode.widgets.find(w => w && w.name === "useExpressiveness"); const expressivenessWidget = settingsNode.widgets.find(w => w && w.name === "expressiveness"); + const useVoiceDescriptionWidget = settingsNode.widgets.find(w => w && w.name === "useVoiceDescription"); + const voiceDescriptionWidget = settingsNode.widgets.find(w => w && w.name === "voiceDescription"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; @@ -1382,6 +1384,7 @@ function videoSettingsToggleHandler(settingsNode) { if (useBackgroundColorWidget && backgroundColorWidget) toggleWidgetState(useBackgroundColorWidget, backgroundColorWidget, "backgroundColor"); if (useRemoveBackgroundWidget && removeBackgroundWidget) toggleWidgetState(useRemoveBackgroundWidget, removeBackgroundWidget, "removeBackground"); if (useExpressivenessWidget && expressivenessWidget) toggleWidgetState(useExpressivenessWidget, expressivenessWidget, "expressiveness"); + if (useVoiceDescriptionWidget && voiceDescriptionWidget) toggleWidgetState(useVoiceDescriptionWidget, voiceDescriptionWidget, "voiceDescription"); } function audioInferenceSpeechToggleHandler(speechNode) { diff --git a/modules/utils/runwareUtils.py b/modules/utils/runwareUtils.py index 0c97b0f..75ba920 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() diff --git a/modules/videoInference.py b/modules/videoInference.py index 4b93bfc..684f19f 100644 --- a/modules/videoInference.py +++ b/modules/videoInference.py @@ -141,7 +141,7 @@ class txt2vid: "tooltip": "Connect a Runware Accelerator Options Node to configure caching and acceleration settings.", }), "settings": ("RUNWAREVIDEOSETTINGS", { - "tooltip": "Connect a Runware Video Inference Settings node to configure draft, audio, and promptUpsampling.", + "tooltip": "Connect a Runware Video Inference Settings node to configure draft, audio, promptUpsampling, voiceDescription, etc.", }), } } @@ -347,7 +347,7 @@ class txt2vid: if runwareAccelerator is not None and isinstance(runwareAccelerator, dict) and len(runwareAccelerator) > 0: genConfig[0]["acceleratorOptions"] = runwareAccelerator - # Add settings if provided (draft, audio, promptUpsampling) + # Add settings if provided (draft, audio, promptUpsampling, voiceDescription, ...) if settings is not None and isinstance(settings, dict) and len(settings) > 0: genConfig[0]["settings"] = settings diff --git a/modules/videoInferenceSpeechInput.py b/modules/videoInferenceSpeechInput.py index c716cfa..3d3637d 100644 --- a/modules/videoInferenceSpeechInput.py +++ b/modules/videoInferenceSpeechInput.py @@ -28,7 +28,7 @@ class RunwareVideoInferenceSpeechInput: }), "text": ("STRING", { "multiline": True, - "tooltip": "Text script for the avatar to speak. Requires voice. Mutually exclusive with audio-driven input. Only used when 'Use Text' is enabled.", + "tooltip": "Text script for the avatar to speak. Use with voice, or text-only when voice is described via settings.voiceDescription on Runware Video Inference Settings. Only used when 'Use Text' is enabled.", "default": "", }), "useSpeed": ("BOOLEAN", { @@ -69,13 +69,15 @@ class RunwareVideoInferenceSpeechInput: FUNCTION = "createSpeech" CATEGORY = "Runware" DESCRIPTION = ( - "Configure speech synthesis for Runware Video Inference. Connect to Runware Video Inference speech input. " - "Speech is only sent when both voice and text are enabled and non-empty; otherwise the node outputs nothing. " + "Configure speech synthesis for Runware Video Inference. Connect to Runware Video Inference → speech, " + "or to Video Inference Inputs → Speech Inputs. " + "Outputs speech when at least one of voice or text is included (non-empty with its toggle); " + "text-only is valid when voice is supplied via settings.voiceDescription. " "Optional fields (speed, pitch, language) are added only when their toggles are on." ) def createSpeech(self, **kwargs) -> tuple: - """Build speech dict for genConfig[0]['speech']. Only include non-empty values; return None unless both voice and text are present.""" + """Build speech for inputs.speech or top-level speech. Returns None if neither voice nor text is set.""" speech: Dict[str, Any] = {} voice = (kwargs.get("voice") or "").strip() @@ -95,7 +97,7 @@ class RunwareVideoInferenceSpeechInput: if lang: speech["language"] = lang - if "voice" not in speech or "text" not in speech: + if "voice" not in speech and "text" not in speech: return (None,) return (speech,) diff --git a/modules/videoSettings.py b/modules/videoSettings.py index 15f9c4a..1bf0842 100644 --- a/modules/videoSettings.py +++ b/modules/videoSettings.py @@ -1,6 +1,6 @@ """ Runware Video Inference Settings Node -Provides settings (draft, audio, promptUpsampling) for Runware Video Inference. +Provides settings (draft, audio, promptUpsampling, voiceDescription, etc.) for Runware Video Inference. """ from typing import Dict, Any @@ -70,6 +70,15 @@ class RunwareVideoSettings: "tooltip": "Avatar expressiveness level. Applies to photo avatars only. Only used when 'Use Expressiveness' is enabled.", "default": "low", }), + "useVoiceDescription": ("BOOLEAN", { + "tooltip": "Enable to include voiceDescription in video inference settings.", + "default": False, + }), + "voiceDescription": ("STRING", { + "default": "", + "multiline": True, + "tooltip": "Voice description text (max 10000 characters). Not supported when inputs.audio is given.", + }), } } @@ -77,7 +86,10 @@ class RunwareVideoSettings: RETURN_NAMES = ("settings",) FUNCTION = "createSettings" CATEGORY = "Runware" - DESCRIPTION = "Configure video inference settings (draft, audio, promptUpsampling) for Runware Video Inference. Connect to Runware Video Inference node." + DESCRIPTION = ( + "Configure video inference settings (draft, audio, promptUpsampling, voiceDescription, etc.) for Runware Video Inference. " + "Connect to Runware Video Inference node." + ) def createSettings(self, **kwargs) -> tuple[Dict[str, Any]]: """Create settings dict for Video Inference API""" @@ -93,6 +105,8 @@ class RunwareVideoSettings: remove_background = kwargs.get("removeBackground", False) use_expressiveness = kwargs.get("useExpressiveness", False) expressiveness = kwargs.get("expressiveness", "low") + use_voice_description = kwargs.get("useVoiceDescription", False) + voice_description = (kwargs.get("voiceDescription") or "").strip() settings: Dict[str, Any] = {} @@ -108,6 +122,8 @@ class RunwareVideoSettings: settings["removeBackground"] = bool(remove_background) if use_expressiveness: settings["expressiveness"] = expressiveness + if use_voice_description and voice_description: + settings["voiceDescription"] = voice_description return (settings,)