diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 18856d4..56f3f67 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -1275,6 +1275,12 @@ function audioSettingsToggleHandler(settingsNode) { 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"); + const useXVectorOnlyWidget = settingsNode.widgets.find(w => w && w.name === "useXVectorOnly"); + const xVectorOnlyWidget = settingsNode.widgets.find(w => w && w.name === "xVectorOnly"); + const useMaxNewTokensWidget = settingsNode.widgets.find(w => w && w.name === "useMaxNewTokens"); + const maxNewTokensWidget = settingsNode.widgets.find(w => w && w.name === "maxNewTokens"); + const useTranscriptWidget = settingsNode.widgets.find(w => w && w.name === "useTranscript"); + const transcriptWidget = settingsNode.widgets.find(w => w && w.name === "transcript"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; @@ -1305,6 +1311,9 @@ function audioSettingsToggleHandler(settingsNode) { if (useCoverConditioningScaleWidget && coverConditioningScaleWidget) toggleWidgetState(useCoverConditioningScaleWidget, coverConditioningScaleWidget, "coverConditioningScale"); if (useRepaintingStartWidget && repaintingStartWidget) toggleWidgetState(useRepaintingStartWidget, repaintingStartWidget, "repaintingStart"); if (useRepaintingEndWidget && repaintingEndWidget) toggleWidgetState(useRepaintingEndWidget, repaintingEndWidget, "repaintingEnd"); + if (useXVectorOnlyWidget && xVectorOnlyWidget) toggleWidgetState(useXVectorOnlyWidget, xVectorOnlyWidget, "xVectorOnly"); + if (useMaxNewTokensWidget && maxNewTokensWidget) toggleWidgetState(useMaxNewTokensWidget, maxNewTokensWidget, "maxNewTokens"); + if (useTranscriptWidget && transcriptWidget) toggleWidgetState(useTranscriptWidget, transcriptWidget, "transcript"); } function textInferenceSettingsToggleHandler(settingsNode) { @@ -1417,6 +1426,8 @@ function audioInferenceSpeechToggleHandler(speechNode) { const emotionWidget = speechNode.widgets.find(w => w && w.name === "emotion"); const useToneWidget = speechNode.widgets.find(w => w && w.name === "useTone"); const toneWidget = speechNode.widgets.find(w => w && w.name === "tone"); + const useLanguageWidget = speechNode.widgets.find(w => w && w.name === "useLanguage"); + const languageWidget = speechNode.widgets.find(w => w && w.name === "language"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; @@ -1439,6 +1450,7 @@ function audioInferenceSpeechToggleHandler(speechNode) { if (usePitchWidget && pitchWidget) toggleWidgetState(usePitchWidget, pitchWidget, "pitch"); if (useEmotionWidget && emotionWidget) toggleWidgetState(useEmotionWidget, emotionWidget, "emotion"); if (useToneWidget && toneWidget) toggleWidgetState(useToneWidget, toneWidget, "tone"); + if (useLanguageWidget && languageWidget) toggleWidgetState(useLanguageWidget, languageWidget, "language"); if (useVoiceWidget && voiceWidget) toggleWidgetState(useVoiceWidget, voiceWidget, "voice"); } @@ -3021,6 +3033,11 @@ function audioModelSearchFilterHandler(audioModelSearchNode) { "runware:ace-step@v1.5-base (ACE-Step v1.5 Base)", "runware:ace-step@v1.5-turbo (ACE-Step v1.5 Turbo)", ], + "Alibaba": [ + "alibaba:qwen@3-tts-1.7b-voicedesign (Qwen3 TTS 1.7B Voice Design)", + "alibaba:qwen@3-tts-1.7b-customvoice (Qwen3 TTS 1.7B Custom Voice)", + "alibaba:qwen@3-tts-1.7b-base (Qwen3 TTS 1.7B Base)", + ], "Dia": [ "runware:dia@v1.0 (Dia 1.6B)", ], diff --git a/modules/audioInference.py b/modules/audioInference.py index 09dd6a4..c41558c 100644 --- a/modules/audioInference.py +++ b/modules/audioInference.py @@ -136,7 +136,7 @@ class RunwareAudioInference: "tooltip": "Custom inputs for audio generation (e.g., video URL for audio extraction)" }), "settings": ("RUNWAREAUDIOSETTINGS", { - "tooltip": "Connect Runware Audio Inference Settings for lyrics, guidanceType, languageBoost, turbo, temperature, textNormalization." + "tooltip": "Connect Runware Audio Inference Settings for lyrics, guidanceType, languageBoost, turbo, temperature, textNormalization, xVectorOnly, maxNewTokens, transcript, etc." }), "speech": ("RUNWARESPEECH", { "tooltip": "Connect Runware Audio Inference Speech for speech synthesis (e.g. Minimax)" diff --git a/modules/audioInferenceSpeech.py b/modules/audioInferenceSpeech.py index 3d9768a..7805637 100644 --- a/modules/audioInferenceSpeech.py +++ b/modules/audioInferenceSpeech.py @@ -1,124 +1,153 @@ -""" -Runware Audio Inference Speech node: builds the speech payload for Runware Audio Inference. -Connect its output to the "speech" input of Runware Audio Inference for speech synthesis (e.g. Minimax). -""" - -from typing import Dict, Any - - -class RunwareAudioInferenceSpeech: - """Builds speech payload (text, voice, speed, volume, pitch?, emotion?, tone?) for Runware Audio Inference.""" - - EMOTIONS = [ - "happy", "sad", "angry", "fearful", "disgusted", "surprised", - "calm", "fluent", "whisper", - ] - - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "text": ("STRING", { - "multiline": True, - "default": "Hello, this is a test of the speech synthesis model.", - "tooltip": "Text to synthesize as speech (speech.text)", - }), - }, - "optional": { - "useVoice": ("BOOLEAN", { - "default": False, - "tooltip": "Enable to include voice in speech synthesis (speech.voice).", - }), - "voice": ("STRING", { - "default": "", - "tooltip": "Voice identifier.", - }), - "useSpeed": ("BOOLEAN", {"default": True, "tooltip": "Include speed (speech.speed)"}), - "speed": ("FLOAT", { - "default": 1.0, - "min": 0.5, - "max": 2.0, - "step": 0.01, - "tooltip": "Speech rate multiplier (speech.speed)", - }), - "useVolume": ("BOOLEAN", {"default": True, "tooltip": "Include volume (speech.volume)"}), - "volume": ("FLOAT", { - "default": 1.0, - "min": 1.0, - "max": 10.0, - "step": 0.1, - "tooltip": "Volume level 1-10 (speech.volume)", - }), - "usePitch": ("BOOLEAN", {"default": False, "tooltip": "Include pitch (speech.pitch)"}), - "pitch": ("FLOAT", { - "default": 0.0, - "min": -12.0, - "max": 12.0, - "step": 0.1, - "tooltip": "Pitch multiplier -12 to 12 (speech.pitch)", - }), - "useEmotion": ("BOOLEAN", {"default": False, "tooltip": "Include emotion (not available for speech.turbo)"}), - "emotion": (cls.EMOTIONS, {"default": "calm", "tooltip": "Emotion for speech (speech.emotion)"}), - "useTone": ("BOOLEAN", {"default": False, "tooltip": "Include pronunciation dictionary (speech.tone)"}), - "tone": ("STRING", { - "multiline": True, - "default": "", - "placeholder": "omg/oh my god\nother/other expansion", - "tooltip": "Pronunciation dictionary, one mapping per line (e.g. omg/oh my god)", - }), - } - } - - RETURN_TYPES = ("RUNWARESPEECH",) - RETURN_NAMES = ("speech",) - FUNCTION = "createSpeech" - CATEGORY = "Runware/Audio" - DESCRIPTION = "Build speech parameters for Runware Audio Inference. Connect output to the 'speech' input of Runware Audio Inference." - - def createSpeech(self, **kwargs) -> tuple: - """Build the speech object for the API (connect to Runware Audio Inference 'speech' input).""" - text = (kwargs.get("text") or "").strip() - voice = (kwargs.get("voice") or "").strip() - use_voice = kwargs.get("useVoice", False) - use_speed = kwargs.get("useSpeed", True) - speed = float(kwargs.get("speed", 1.0)) - use_volume = kwargs.get("useVolume", True) - volume = float(kwargs.get("volume", 1.0)) - use_pitch = kwargs.get("usePitch", False) - pitch = float(kwargs.get("pitch", 0.0)) - use_emotion = kwargs.get("useEmotion", False) - emotion = kwargs.get("emotion", "calm") - use_tone = kwargs.get("useTone", False) - tone_str = kwargs.get("tone", "") or "" - - speech: Dict[str, Any] = {"text": text} - if use_voice: - speech["voice"] = voice - if use_speed: - speech["speed"] = speed - if use_volume: - speech["volume"] = volume - if use_pitch: - speech["pitch"] = pitch - if use_emotion: - speech["emotion"] = emotion - if use_tone and tone_str.strip(): - tone_lines = [s.strip() for s in tone_str.replace(",", "\n").split("\n") if s.strip()] - if tone_lines: - speech["tone"] = tone_lines - - if not text: - return ({},) - return (speech,) - - -NODE_CLASS_MAPPINGS = { - "RunwareAudioInferenceSpeech": RunwareAudioInferenceSpeech, -} - -NODE_DISPLAY_NAME_MAPPINGS = { - "RunwareAudioInferenceSpeech": "Runware Audio Inference Speech", -} +""" +Runware Audio Inference Speech node: builds the speech payload for Runware Audio Inference. +Connect its output to the "speech" input of Runware Audio Inference for speech synthesis (e.g. Minimax). +""" + +from typing import Dict, Any + + +class RunwareAudioInferenceSpeech: + """Builds speech payload (text, voice, speed, volume, pitch?, emotion?, tone?) for Runware Audio Inference.""" + + EMOTIONS = [ + "happy", "sad", "angry", "fearful", "disgusted", "surprised", + "calm", "fluent", "whisper", + ] + + SPEECH_LANGUAGES = [ + "Auto", + "Chinese", + "English", + "Japanese", + "Korean", + "German", + "French", + "Russian", + "Portuguese", + "Spanish", + "Italian", + ] + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "text": ("STRING", { + "multiline": True, + "default": "Hello, this is a test of the speech synthesis model.", + "tooltip": "Text to synthesize as speech (speech.text)", + }), + }, + "optional": { + "useVoice": ("BOOLEAN", { + "default": False, + "tooltip": "Enable to include voice in speech synthesis (speech.voice).", + }), + "voice": ("STRING", { + "default": "", + "tooltip": "Voice identifier.", + }), + "useSpeed": ("BOOLEAN", {"default": True, "tooltip": "Include speed (speech.speed)"}), + "speed": ("FLOAT", { + "default": 1.0, + "min": 0.5, + "max": 2.0, + "step": 0.01, + "tooltip": "Speech rate multiplier (speech.speed)", + }), + "useVolume": ("BOOLEAN", {"default": True, "tooltip": "Include volume (speech.volume)"}), + "volume": ("FLOAT", { + "default": 1.0, + "min": 1.0, + "max": 10.0, + "step": 0.1, + "tooltip": "Volume level 1-10 (speech.volume)", + }), + "usePitch": ("BOOLEAN", {"default": False, "tooltip": "Include pitch (speech.pitch)"}), + "pitch": ("FLOAT", { + "default": 0.0, + "min": -12.0, + "max": 12.0, + "step": 0.1, + "tooltip": "Pitch multiplier -12 to 12 (speech.pitch)", + }), + "useEmotion": ("BOOLEAN", {"default": False, "tooltip": "Include emotion (not available for speech.turbo)"}), + "emotion": (cls.EMOTIONS, {"default": "calm", "tooltip": "Emotion for speech (speech.emotion)"}), + "useTone": ("BOOLEAN", {"default": False, "tooltip": "Include pronunciation dictionary (speech.tone)"}), + "tone": ("STRING", { + "multiline": True, + "default": "", + "placeholder": "omg/oh my god\nother/other expansion", + "tooltip": "Pronunciation dictionary, one mapping per line (e.g. omg/oh my god)", + }), + "useLanguage": ("BOOLEAN", { + "default": False, + "tooltip": "Enable to include language (speech.language).", + }), + "language": (cls.SPEECH_LANGUAGES, { + "default": "Auto", + "tooltip": "Language of the input text. Options: Auto, Chinese, English, Japanese, Korean, German, French, Russian, Portuguese, Spanish, Italian. Applies to all variants. Only used when 'Use Language' is enabled.", + }), + } + } + + RETURN_TYPES = ("RUNWARESPEECH",) + RETURN_NAMES = ("speech",) + FUNCTION = "createSpeech" + CATEGORY = "Runware/Audio" + DESCRIPTION = ( + "Build speech parameters for Runware Audio Inference (text, voice, speed, volume, pitch, emotion, tone, language, etc.). " + "Connect output to the 'speech' input of Runware Audio Inference." + ) + + def createSpeech(self, **kwargs) -> tuple: + """Build the speech object for the API (connect to Runware Audio Inference 'speech' input).""" + text = (kwargs.get("text") or "").strip() + voice = (kwargs.get("voice") or "").strip() + use_voice = kwargs.get("useVoice", False) + use_speed = kwargs.get("useSpeed", True) + speed = float(kwargs.get("speed", 1.0)) + use_volume = kwargs.get("useVolume", True) + volume = float(kwargs.get("volume", 1.0)) + use_pitch = kwargs.get("usePitch", False) + pitch = float(kwargs.get("pitch", 0.0)) + use_emotion = kwargs.get("useEmotion", False) + emotion = kwargs.get("emotion", "calm") + use_tone = kwargs.get("useTone", False) + tone_str = kwargs.get("tone", "") or "" + use_language = kwargs.get("useLanguage", False) + language = kwargs.get("language", "Auto") + + speech: Dict[str, Any] = {"text": text} + if use_voice: + speech["voice"] = voice + if use_speed: + speech["speed"] = speed + if use_volume: + speech["volume"] = volume + if use_pitch: + speech["pitch"] = pitch + if use_emotion: + speech["emotion"] = emotion + if use_tone and tone_str.strip(): + tone_lines = [s.strip() for s in tone_str.replace(",", "\n").split("\n") if s.strip()] + if tone_lines: + speech["tone"] = tone_lines + if use_language: + speech["language"] = language + + if not text: + return ({},) + return (speech,) + + +NODE_CLASS_MAPPINGS = { + "RunwareAudioInferenceSpeech": RunwareAudioInferenceSpeech, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "RunwareAudioInferenceSpeech": "Runware Audio Inference Speech", +} diff --git a/modules/audioModelSearch.py b/modules/audioModelSearch.py index e5f881b..a003590 100644 --- a/modules/audioModelSearch.py +++ b/modules/audioModelSearch.py @@ -19,6 +19,11 @@ class RunwareAudioModelSearch: "runware:ace-step@v1.5-base (ACE-Step v1.5 Base)", "runware:ace-step@v1.5-turbo (ACE-Step v1.5 Turbo)", ], + "Alibaba": [ + "alibaba:qwen@3-tts-1.7b-voicedesign (Qwen3 TTS 1.7B Voice Design)", + "alibaba:qwen@3-tts-1.7b-customvoice (Qwen3 TTS 1.7B Custom Voice)", + "alibaba:qwen@3-tts-1.7b-base (Qwen3 TTS 1.7B Base)", + ], "Dia": [ "runware:dia@v1.0 (Dia 1.6B)", ], @@ -40,6 +45,7 @@ class RunwareAudioModelSearch: "KlingAI", "Mirelo", "Ace", + "Alibaba", "Dia", "xAI", "MiniMax", diff --git a/modules/audioSettings.py b/modules/audioSettings.py index e5a7151..ebe062b 100644 --- a/modules/audioSettings.py +++ b/modules/audioSettings.py @@ -2,7 +2,7 @@ Runware Audio Inference Settings Node Provides lyrics, guidanceType, languageBoost, turbo, temperature, textNormalization, bpm, keyScale, timeSignature, vocalLanguage, coverConditioningScale, repaintingStart, -and repaintingEnd for Runware Audio Inference. +repaintingEnd, xVectorOnly, maxNewTokens, transcript, and more for Runware Audio Inference. """ from typing import Dict, Any @@ -151,6 +151,36 @@ class RunwareAudioSettings: "default": 0.0, "step": 0.01, }), + "useXVectorOnly": ("BOOLEAN", { + "tooltip": "Enable to include xVectorOnly in audio generation settings.", + "default": False, + }), + "xVectorOnly": ("BOOLEAN", { + "tooltip": "true = speaker embedding only (no transcript needed, lower similarity). false = ICL mode (needs transcript, higher quality). Only used when 'Use X Vector Only' is enabled.", + "default": False, + "label_on": "true", + "label_off": "false", + }), + "useMaxNewTokens": ("BOOLEAN", { + "tooltip": "Enable to include maxNewTokens (audio output token cap) in audio generation settings.", + "default": False, + }), + "maxNewTokens": ("INT", { + "tooltip": "Audio output token cap. Higher = longer audio, but risk of generation hangs. Applies to all variants. Only used when 'Use Max New Tokens' is enabled.", + "default": 4096, + "min": 1, + "max": 262144, + "step": 1, + }), + "useTranscript": ("BOOLEAN", { + "tooltip": "Enable to include transcript (reference audio transcript) in audio generation settings.", + "default": False, + }), + "transcript": ("STRING", { + "multiline": True, + "default": "", + "tooltip": "Transcript of the reference audio. Required for ICL mode; omit or leave empty for x-vector-only mode. Base variant only. Only used when 'Use Transcript' is enabled.", + }), } } @@ -158,7 +188,11 @@ class RunwareAudioSettings: RETURN_NAMES = ("settings",) FUNCTION = "createSettings" CATEGORY = "Runware/Audio" - 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." + DESCRIPTION = ( + "Configure audio generation settings (lyrics, guidanceType, languageBoost, turbo, temperature, textNormalization, " + "bpm, keyScale, timeSignature, vocalLanguage, coverConditioningScale, repaintingStart, repaintingEnd, " + "xVectorOnly, maxNewTokens, transcript, etc.) for Runware Audio Inference. Connect to Runware Audio Inference node." + ) def createSettings(self, **kwargs) -> tuple[Dict[str, Any]]: """Create audio settings dict for API""" @@ -188,6 +222,12 @@ class RunwareAudioSettings: repainting_start = kwargs.get("repaintingStart", 0.0) use_repainting_end = kwargs.get("useRepaintingEnd", False) repainting_end = kwargs.get("repaintingEnd", 0.0) + use_x_vector_only = kwargs.get("useXVectorOnly", False) + x_vector_only = kwargs.get("xVectorOnly", False) + use_max_new_tokens = kwargs.get("useMaxNewTokens", False) + max_new_tokens = kwargs.get("maxNewTokens", 4096) + use_transcript = kwargs.get("useTranscript", False) + transcript = kwargs.get("transcript", "") or "" settings: Dict[str, Any] = {} @@ -230,6 +270,15 @@ class RunwareAudioSettings: if use_repainting_end: settings["repaintingEnd"] = float(repainting_end) + if use_x_vector_only: + settings["xVectorOnly"] = bool(x_vector_only) + + if use_max_new_tokens: + settings["maxNewTokens"] = int(max_new_tokens) + + if use_transcript and transcript.strip(): + settings["transcript"] = transcript.strip() + return (settings,) diff --git a/workflows/Runware_Audio_Inference_Qwen.json b/workflows/Runware_Audio_Inference_Qwen.json new file mode 100644 index 0000000..f3e6df9 --- /dev/null +++ b/workflows/Runware_Audio_Inference_Qwen.json @@ -0,0 +1 @@ +{"id":"4704fbfa-824d-41b8-b8f2-f3865b83828b","revision":0,"last_node_id":5,"last_link_id":4,"nodes":[{"id":5,"type":"Runware Audio Model Search","pos":[201.83511352539062,576.8184204101562],"size":[270,130],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"Model Search","name":"Model Search","type":"STRING","widget":{"name":"Model Search"},"link":null},{"localized_name":"Model Provider","name":"Model Provider","type":"COMBO","widget":{"name":"Model Provider"},"link":null},{"localized_name":"AudioList","name":"AudioList","type":"COMBO","widget":{"name":"AudioList"},"link":null},{"localized_name":"Use Search Value","name":"Use Search Value","type":"BOOLEAN","widget":{"name":"Use Search Value"},"link":null}],"outputs":[{"localized_name":"model","name":"model","type":"RUNWAREAUDIOMODEL","links":[4]}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"480fd9769359e8e40203f928086427ab202b18d3","Node name for S&R":"Runware Audio Model Search"},"widgets_values":["","Alibaba","alibaba:qwen@3-tts-1.7b-voicedesign (Qwen3 TTS 1.7B Voice Design)",false],"bgcolor":"#5345bf"},{"id":4,"type":"SaveAudioMP3","pos":[1010.2057495117188,499.1061706542969],"size":[270,136],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"audio","name":"audio","type":"AUDIO","link":1},{"localized_name":"filename_prefix","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"quality","name":"quality","type":"COMBO","widget":{"name":"quality"},"link":null},{"localized_name":"audioUI","name":"audioUI","type":"AUDIO_UI","widget":{"name":"audioUI"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.46","Node name for S&R":"SaveAudioMP3"},"widgets_values":["audio/ComfyUI","V0"]},{"id":3,"type":"Runware Audio Inference Settings","pos":[1001.6655883789062,703.0296020507812],"size":[400,862],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"useTemperature","name":"useTemperature","shape":7,"type":"BOOLEAN","widget":{"name":"useTemperature"},"link":null},{"localized_name":"temperature","name":"temperature","shape":7,"type":"FLOAT","widget":{"name":"temperature"},"link":null},{"localized_name":"useLyrics","name":"useLyrics","shape":7,"type":"BOOLEAN","widget":{"name":"useLyrics"},"link":null},{"localized_name":"lyrics","name":"lyrics","shape":7,"type":"STRING","widget":{"name":"lyrics"},"link":null},{"localized_name":"useGuidanceType","name":"useGuidanceType","shape":7,"type":"BOOLEAN","widget":{"name":"useGuidanceType"},"link":null},{"localized_name":"guidanceType","name":"guidanceType","shape":7,"type":"COMBO","widget":{"name":"guidanceType"},"link":null},{"localized_name":"useLanguageBoost","name":"useLanguageBoost","shape":7,"type":"BOOLEAN","widget":{"name":"useLanguageBoost"},"link":null},{"localized_name":"languageBoost","name":"languageBoost","shape":7,"type":"COMBO","widget":{"name":"languageBoost"},"link":null},{"localized_name":"useTurbo","name":"useTurbo","shape":7,"type":"BOOLEAN","widget":{"name":"useTurbo"},"link":null},{"localized_name":"turbo","name":"turbo","shape":7,"type":"BOOLEAN","widget":{"name":"turbo"},"link":null},{"localized_name":"useTextNormalization","name":"useTextNormalization","shape":7,"type":"BOOLEAN","widget":{"name":"useTextNormalization"},"link":null},{"localized_name":"textNormalization","name":"textNormalization","shape":7,"type":"BOOLEAN","widget":{"name":"textNormalization"},"link":null},{"localized_name":"useBpm","name":"useBpm","shape":7,"type":"BOOLEAN","widget":{"name":"useBpm"},"link":null},{"localized_name":"bpm","name":"bpm","shape":7,"type":"INT","widget":{"name":"bpm"},"link":null},{"localized_name":"useKeyScale","name":"useKeyScale","shape":7,"type":"BOOLEAN","widget":{"name":"useKeyScale"},"link":null},{"localized_name":"keyScale","name":"keyScale","shape":7,"type":"STRING","widget":{"name":"keyScale"},"link":null},{"localized_name":"useTimeSignature","name":"useTimeSignature","shape":7,"type":"BOOLEAN","widget":{"name":"useTimeSignature"},"link":null},{"localized_name":"timeSignature","name":"timeSignature","shape":7,"type":"INT","widget":{"name":"timeSignature"},"link":null},{"localized_name":"useVocalLanguage","name":"useVocalLanguage","shape":7,"type":"BOOLEAN","widget":{"name":"useVocalLanguage"},"link":null},{"localized_name":"vocalLanguage","name":"vocalLanguage","shape":7,"type":"COMBO","widget":{"name":"vocalLanguage"},"link":null},{"localized_name":"useCoverConditioningScale","name":"useCoverConditioningScale","shape":7,"type":"BOOLEAN","widget":{"name":"useCoverConditioningScale"},"link":null},{"localized_name":"coverConditioningScale","name":"coverConditioningScale","shape":7,"type":"FLOAT","widget":{"name":"coverConditioningScale"},"link":null},{"localized_name":"useRepaintingStart","name":"useRepaintingStart","shape":7,"type":"BOOLEAN","widget":{"name":"useRepaintingStart"},"link":null},{"localized_name":"repaintingStart","name":"repaintingStart","shape":7,"type":"FLOAT","widget":{"name":"repaintingStart"},"link":null},{"localized_name":"useRepaintingEnd","name":"useRepaintingEnd","shape":7,"type":"BOOLEAN","widget":{"name":"useRepaintingEnd"},"link":null},{"localized_name":"repaintingEnd","name":"repaintingEnd","shape":7,"type":"FLOAT","widget":{"name":"repaintingEnd"},"link":null},{"localized_name":"useXVectorOnly","name":"useXVectorOnly","shape":7,"type":"BOOLEAN","widget":{"name":"useXVectorOnly"},"link":null},{"localized_name":"xVectorOnly","name":"xVectorOnly","shape":7,"type":"BOOLEAN","widget":{"name":"xVectorOnly"},"link":null},{"localized_name":"useMaxNewTokens","name":"useMaxNewTokens","shape":7,"type":"BOOLEAN","widget":{"name":"useMaxNewTokens"},"link":null},{"localized_name":"maxNewTokens","name":"maxNewTokens","shape":7,"type":"INT","widget":{"name":"maxNewTokens"},"link":null},{"localized_name":"useTranscript","name":"useTranscript","shape":7,"type":"BOOLEAN","widget":{"name":"useTranscript"},"link":null},{"localized_name":"transcript","name":"transcript","shape":7,"type":"STRING","widget":{"name":"transcript"},"link":null}],"outputs":[{"localized_name":"settings","name":"settings","type":"RUNWAREAUDIOSETTINGS","links":[2]}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"480fd9769359e8e40203f928086427ab202b18d3","Node name for S&R":"Runware Audio Inference Settings"},"widgets_values":[false,1,false,"",false,"apg",false,"auto",false,false,false,true,false,120,false,"",false,4,false,"en",false,1,false,0,false,0,false,false,true,4096,false,""],"bgcolor":"#5345bf"},{"id":1,"type":"Runware Audio Inference","pos":[557.121337890625,508.376708984375],"size":[400,746],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"model","name":"model","type":"RUNWAREAUDIOMODEL","link":4},{"localized_name":"inputs","name":"inputs","shape":7,"type":"RUNWAREAUDIOINFERENCEINPUTS","link":null},{"localized_name":"settings","name":"settings","shape":7,"type":"RUNWAREAUDIOSETTINGS","link":2},{"localized_name":"speech","name":"speech","shape":7,"type":"RUNWARESPEECH","link":3},{"localized_name":"voiceModify","name":"voiceModify","shape":7,"type":"RUNWAREVOICEMODIFY","link":null},{"localized_name":"providerSettings","name":"providerSettings","shape":7,"type":"RUNWAREPROVIDERSETTINGS","link":null},{"localized_name":"usePositivePrompt","name":"usePositivePrompt","type":"BOOLEAN","widget":{"name":"usePositivePrompt"},"link":null},{"localized_name":"positivePrompt","name":"positivePrompt","type":"STRING","widget":{"name":"positivePrompt"},"link":null},{"localized_name":"negativePrompt","name":"negativePrompt","type":"STRING","widget":{"name":"negativePrompt"},"link":null},{"localized_name":"useDuration","name":"useDuration","type":"BOOLEAN","widget":{"name":"useDuration"},"link":null},{"localized_name":"duration","name":"duration","type":"INT","widget":{"name":"duration"},"link":null},{"localized_name":"useSampleRate","name":"useSampleRate","type":"BOOLEAN","widget":{"name":"useSampleRate"},"link":null},{"localized_name":"sampleRate","name":"sampleRate","type":"COMBO","widget":{"name":"sampleRate"},"link":null},{"localized_name":"useBitrate","name":"useBitrate","type":"BOOLEAN","widget":{"name":"useBitrate"},"link":null},{"localized_name":"bitrate","name":"bitrate","type":"COMBO","widget":{"name":"bitrate"},"link":null},{"localized_name":"useChannels","name":"useChannels","type":"BOOLEAN","widget":{"name":"useChannels"},"link":null},{"localized_name":"channels","name":"channels","type":"INT","widget":{"name":"channels"},"link":null},{"localized_name":"outputType","name":"outputType","type":"COMBO","widget":{"name":"outputType"},"link":null},{"localized_name":"outputFormat","name":"outputFormat","type":"COMBO","widget":{"name":"outputFormat"},"link":null},{"localized_name":"numberResults","name":"numberResults","type":"INT","widget":{"name":"numberResults"},"link":null},{"localized_name":"useSeed","name":"useSeed","type":"BOOLEAN","widget":{"name":"useSeed"},"link":null},{"localized_name":"seed","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"useSteps","name":"useSteps","type":"BOOLEAN","widget":{"name":"useSteps"},"link":null},{"localized_name":"steps","name":"steps","type":"INT","widget":{"name":"steps"},"link":null},{"localized_name":"useStrength","name":"useStrength","type":"BOOLEAN","widget":{"name":"useStrength"},"link":null},{"localized_name":"strength","name":"strength","type":"FLOAT","widget":{"name":"strength"},"link":null},{"localized_name":"useCFGScale","name":"useCFGScale","type":"BOOLEAN","widget":{"name":"useCFGScale"},"link":null},{"localized_name":"CFGScale","name":"CFGScale","type":"FLOAT","widget":{"name":"CFGScale"},"link":null}],"outputs":[{"localized_name":"audio","name":"audio","type":"AUDIO","links":[1]},{"localized_name":"video","name":"video","type":"VIDEO","links":null}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"480fd9769359e8e40203f928086427ab202b18d3","Node name for S&R":"Runware Audio Inference"},"widgets_values":[true,"A warm, cheerful male voice with moderate pace and a slight British accen","",false,10,false,32000,false,128,false,2,"URL","MP3",1,false,400597415,"randomize",false,20,false,0.8,false,12],"bgcolor":"#5345bf"},{"id":2,"type":"Runware Audio Inference Speech","pos":[109.24061584472656,785.9152221679688],"size":[400,454],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"text","name":"text","type":"STRING","widget":{"name":"text"},"link":null},{"localized_name":"useVoice","name":"useVoice","shape":7,"type":"BOOLEAN","widget":{"name":"useVoice"},"link":null},{"localized_name":"voice","name":"voice","shape":7,"type":"STRING","widget":{"name":"voice"},"link":null},{"localized_name":"useSpeed","name":"useSpeed","shape":7,"type":"BOOLEAN","widget":{"name":"useSpeed"},"link":null},{"localized_name":"speed","name":"speed","shape":7,"type":"FLOAT","widget":{"name":"speed"},"link":null},{"localized_name":"useVolume","name":"useVolume","shape":7,"type":"BOOLEAN","widget":{"name":"useVolume"},"link":null},{"localized_name":"volume","name":"volume","shape":7,"type":"FLOAT","widget":{"name":"volume"},"link":null},{"localized_name":"usePitch","name":"usePitch","shape":7,"type":"BOOLEAN","widget":{"name":"usePitch"},"link":null},{"localized_name":"pitch","name":"pitch","shape":7,"type":"FLOAT","widget":{"name":"pitch"},"link":null},{"localized_name":"useEmotion","name":"useEmotion","shape":7,"type":"BOOLEAN","widget":{"name":"useEmotion"},"link":null},{"localized_name":"emotion","name":"emotion","shape":7,"type":"COMBO","widget":{"name":"emotion"},"link":null},{"localized_name":"useTone","name":"useTone","shape":7,"type":"BOOLEAN","widget":{"name":"useTone"},"link":null},{"localized_name":"tone","name":"tone","shape":7,"type":"STRING","widget":{"name":"tone"},"link":null},{"localized_name":"useLanguage","name":"useLanguage","shape":7,"type":"BOOLEAN","widget":{"name":"useLanguage"},"link":null},{"localized_name":"language","name":"language","shape":7,"type":"COMBO","widget":{"name":"language"},"link":null}],"outputs":[{"localized_name":"speech","name":"speech","type":"RUNWARESPEECH","links":[3]}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"480fd9769359e8e40203f928086427ab202b18d3","Node name for S&R":"Runware Audio Inference Speech"},"widgets_values":["Hello, this is a test of the Qwen 3 TTS VoiceDesign model.",true,"placeholder",true,1,false,1,false,0,false,"calm",false,"",true,"English"],"bgcolor":"#5345bf"}],"links":[[1,1,0,4,0,"AUDIO"],[2,3,0,1,2,"RUNWAREAUDIOSETTINGS"],[3,2,0,1,3,"RUNWARESPEECH"],[4,5,0,1,0,"RUNWAREAUDIOMODEL"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.6271586751617864,"offset":[366.33835426215654,-367.9205409415209]}},"version":0.4} \ No newline at end of file