Merge branch 'main' into feature-syncUpdateVideoInference
This commit is contained in:
+9
-1
@@ -46,6 +46,7 @@ from .modules.providerSettings.briaProviderSettings import RunwareBriaProviderSe
|
||||
from .modules.providerSettings.briaProviderMask import RunwareBriaProviderMask
|
||||
from .modules.audioInference import RunwareAudioInference
|
||||
from .modules.audioInferenceSpeech import RunwareAudioInferenceSpeech
|
||||
from .modules.audioInferenceSpeechVoices import RunwareAudioInferenceSpeechVoices
|
||||
from .modules.audioModelSearch import RunwareAudioModelSearch
|
||||
from .modules.textModelSearch import RunwareTextModelSearch
|
||||
from .modules.textInferenceMessages import RunwareTextInferenceMessages
|
||||
@@ -67,6 +68,7 @@ from .modules.speechInput import RunwareSpeechInput
|
||||
from .modules.speechInputCombine import RunwareSpeechInputCombine
|
||||
from .modules.referenceVideos import referenceVideos
|
||||
from .modules.referenceVoices import referenceVoices
|
||||
from .modules.referenceAudios import referenceAudios
|
||||
from .modules.videoInferenceInputs import videoInferenceInputs
|
||||
from .modules.videoInferenceElements import (
|
||||
RunwareVideoInferenceElements,
|
||||
@@ -167,6 +169,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"Runware Bria Provider Mask": RunwareBriaProviderMask,
|
||||
"Runware Audio Inference": RunwareAudioInference,
|
||||
"Runware Audio Inference Speech": RunwareAudioInferenceSpeech,
|
||||
"Runware Audio Inference Speech Voices": RunwareAudioInferenceSpeechVoices,
|
||||
"Runware Audio Model Search": RunwareAudioModelSearch,
|
||||
"Runware Text Model Search": RunwareTextModelSearch,
|
||||
"Runware Text Inference Messages": RunwareTextInferenceMessages,
|
||||
@@ -186,8 +189,13 @@ NODE_CLASS_MAPPINGS = {
|
||||
"Runware Video Audio Input": RunwareAudioInput,
|
||||
"Runware Video Speech Input": RunwareSpeechInput,
|
||||
"Runware Speech Inputs Combine": RunwareSpeechInputCombine,
|
||||
# Backward-compatible aliases for existing workflows
|
||||
"Runware Reference Videos": referenceVideos,
|
||||
"Runware Reference Voices": referenceVoices,
|
||||
"Runware Video Inputs References": videoInputsReferences,
|
||||
"Runware Video Inference Inputs Reference Videos": referenceVideos,
|
||||
"Runware Video Inference Inputs Reference Voices": referenceVoices,
|
||||
"Runware Video Inference Inputs Reference Audios": referenceAudios,
|
||||
"Runware Video Inference Inputs": videoInferenceInputs,
|
||||
"Runware Video Inference Elements": RunwareVideoInferenceElements,
|
||||
"Runware Video Inference Elements Combine": RunwareVideoInferenceElementsCombine,
|
||||
@@ -220,7 +228,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"Runware Vectorize": vectorize,
|
||||
"Runware Video Background Removal": videoBgRemoval,
|
||||
"Runware Video Upscaler": videoUpscaler,
|
||||
"Runware Video Inputs References": videoInputsReferences,
|
||||
"Runware Video Inference Inputs Reference Images": videoInputsReferences,
|
||||
"Runware Video Inputs Frame Images": RunwareVideoInputsFrameImages,
|
||||
"Runware Safety Inputs": safetyInputs,
|
||||
"Runware Settings": RunwareSettings,
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, saveTextHandler, mediaUUIDHandler, save3DFilepathHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, textModelSearchFilterHandler, vectorizeModelSearchFilterHandler, vectorizeToggleHandler, useParameterToggleHandler, imageInferenceToggleHandler, imageInferenceAdvancedFeaturesToggleHandler, watermarkAdvancedFeatureToggleHandler, videoInferenceSpeechInputToggleHandler, regionalPromptingRegionsToggleHandler, upscalerToggleHandler, imageUpscalerSettingsToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, audioInferenceSpeechToggleHandler, audioSettingsToggleHandler, textInferenceSettingsToggleHandler, videoSettingsToggleHandler, videoInferenceSettingsTtsToggleHandler, videoInferenceSettingsActiveSpeakerDetectionToggleHandler, videoInferenceSettingsActiveSpeakerBoundingBoxesToggleHandler, videoInferenceSettingsSegmentsToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, threeDInferenceToggleHandler, threeDInferenceSettingsToggleHandler, threeDInferenceSettingsLatToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, safetyInputsToggleHandler, imageInferenceSettingsColorPaletteToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler } from "./utils.js";
|
||||
import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, saveTextHandler, mediaUUIDHandler, save3DFilepathHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, textModelSearchFilterHandler, vectorizeModelSearchFilterHandler, vectorizeToggleHandler, useParameterToggleHandler, imageInferenceToggleHandler, imageInferenceAdvancedFeaturesToggleHandler, watermarkAdvancedFeatureToggleHandler, videoInferenceSpeechInputToggleHandler, regionalPromptingRegionsToggleHandler, upscalerToggleHandler, imageUpscalerSettingsToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, audioInferenceSpeechToggleHandler, audioSettingsToggleHandler, textInferenceSettingsToggleHandler, videoSettingsToggleHandler, videoInferenceSettingsTtsToggleHandler, videoInferenceSettingsActiveSpeakerDetectionToggleHandler, videoInferenceSettingsActiveSpeakerBoundingBoxesToggleHandler, videoInferenceSettingsSegmentsToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, threeDInferenceToggleHandler, threeDInferenceSettingsToggleHandler, threeDInferenceSettingsLatToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, safetyInputsToggleHandler, imageInferenceSettingsColorPaletteToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler, audioInferenceSpeechVoicesToggleHandler } from "./utils.js";
|
||||
import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js";
|
||||
|
||||
const nodeInitList = [];
|
||||
@@ -91,6 +91,8 @@ app.registerExtension({
|
||||
regionalPromptingRegionsToggleHandler(node);
|
||||
} else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOINFERENCESPEECH) {
|
||||
audioInferenceSpeechToggleHandler(node);
|
||||
} else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOINFERENCESPEECHVOICES) {
|
||||
audioInferenceSpeechVoicesToggleHandler(node);
|
||||
} else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOSETTINGS) {
|
||||
audioSettingsToggleHandler(node);
|
||||
} else if(nodeClass === RUNWARE_NODE_TYPES.TEXTINFERENCESETTINGS) {
|
||||
|
||||
+28
-3
@@ -82,6 +82,7 @@ const RUNWARE_NODE_TYPES = {
|
||||
FRAMEIMAGES: "Runware Frame Images",
|
||||
AUDIOINFERENCE: "Runware Audio Inference",
|
||||
AUDIOINFERENCESPEECH: "Runware Audio Inference Speech",
|
||||
AUDIOINFERENCESPEECHVOICES: "Runware Audio Inference Speech Voices",
|
||||
AUDIOMODELSEARCH: "Runware Audio Model Search",
|
||||
TEXTMODELSEARCH: "Runware Text Model Search",
|
||||
TEXTINFERENCE: "Runware Text Inference",
|
||||
@@ -105,8 +106,12 @@ const RUNWARE_NODE_TYPES = {
|
||||
INPUTAUDIOS: "Runware Input Audios",
|
||||
AUDIOINPUT: "Runware Video Audio Input",
|
||||
SPEECHINPUT: "Runware Video Speech Input",
|
||||
REFERENCEVIDEOS: "Runware Reference Videos",
|
||||
REFERENCEVOICES: "Runware Reference Voices",
|
||||
REFERENCEVIDEOS: "Runware Video Inference Inputs Reference Videos",
|
||||
REFERENCEVIDEOS_LEGACY: "Runware Reference Videos",
|
||||
REFERENCEVOICES: "Runware Video Inference Inputs Reference Voices",
|
||||
REFERENCEVOICES_LEGACY: "Runware Reference Voices",
|
||||
REFERENCEAUDIOS: "Runware Video Inference Inputs Reference Audios",
|
||||
VIDEOINPUTSREFERENCES_LEGACY: "Runware Video Inputs References",
|
||||
VIDEOINFERENCEINPUTS: "Runware Video Inference Inputs",
|
||||
VIDEOINFERENCEELEMENTS: "Runware Video Inference Elements",
|
||||
VIDEOINFERENCEELEMENTSCOMBINE: "Runware Video Inference Elements Combine",
|
||||
@@ -138,7 +143,7 @@ const RUNWARE_NODE_TYPES = {
|
||||
VECTORIZE: "Runware Vectorize",
|
||||
VIDEOBGREMOVAL: "Runware Video Background Removal",
|
||||
VIDEOUPSCALER: "Runware Video Upscaler",
|
||||
VIDEOINPUTSREFERENCES: "Runware Video Inputs References",
|
||||
VIDEOINPUTSREFERENCES: "Runware Video Inference Inputs Reference Images",
|
||||
VIDEOINPUTSFRAMEIMAGES: "Runware Video Inputs Frame Images",
|
||||
ACCELERATOROPTIONS: "Runware Accelerator Options",
|
||||
VIDEOTRANSCRIPTION: "Runware Video Transcription",
|
||||
@@ -299,6 +304,10 @@ const RUNWARE_NODE_PROPS = {
|
||||
[RUNWARE_NODE_TYPES.AUDIOINFERENCESPEECH]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.AUDIOINFERENCESPEECHVOICES]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.AUDIOMODELSEARCH]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
liveSearch: true,
|
||||
@@ -405,10 +414,22 @@ const RUNWARE_NODE_PROPS = {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.REFERENCEVIDEOS_LEGACY]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.REFERENCEVOICES]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.REFERENCEVOICES_LEGACY]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.REFERENCEAUDIOS]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.VIDEOINFERENCEINPUTS]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
@@ -509,6 +530,10 @@ const RUNWARE_NODE_PROPS = {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.VIDEOINPUTSREFERENCES_LEGACY]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.VIDEOINPUTSFRAMEIMAGES]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
|
||||
+92
-1
@@ -1337,7 +1337,7 @@ function textInferenceSettingsToggleHandler(settingsNode) {
|
||||
if (!settingsNode?.widgets) return;
|
||||
|
||||
const useSystemPromptWidget = settingsNode.widgets.find(w => w && w.name === "useSystemPrompt");
|
||||
const systemWidget = settingsNode.widgets.find(w => w && w.name === "system");
|
||||
const systemWidget = settingsNode.widgets.find(w => w && (w.name === "systemPrompt" || w.name === "system"));
|
||||
const useMaxTokensWidget = settingsNode.widgets.find(w => w && w.name === "useMaxTokens");
|
||||
const maxTokensWidget = settingsNode.widgets.find(w => w && w.name === "maxTokens");
|
||||
const useTemperatureWidget = settingsNode.widgets.find(w => w && w.name === "useTemperature");
|
||||
@@ -1346,6 +1346,16 @@ function textInferenceSettingsToggleHandler(settingsNode) {
|
||||
const topPWidget = settingsNode.widgets.find(w => w && w.name === "topP");
|
||||
const useTopKWidget = settingsNode.widgets.find(w => w && w.name === "useTopK");
|
||||
const topKWidget = settingsNode.widgets.find(w => w && w.name === "topK");
|
||||
const useStopSequencesWidget = settingsNode.widgets.find(w => w && w.name === "useStopSequences");
|
||||
const stopSequencesWidget = settingsNode.widgets.find(w => w && w.name === "stopSequences");
|
||||
const usePresencePenaltyWidget = settingsNode.widgets.find(w => w && w.name === "usePresencePenalty");
|
||||
const presencePenaltyWidget = settingsNode.widgets.find(w => w && w.name === "presencePenalty");
|
||||
const useFrequencyPenaltyWidget = settingsNode.widgets.find(w => w && w.name === "useFrequencyPenalty");
|
||||
const frequencyPenaltyWidget = settingsNode.widgets.find(w => w && w.name === "frequencyPenalty");
|
||||
const useToolsWidget = settingsNode.widgets.find(w => w && w.name === "useTools");
|
||||
const toolsWidget = settingsNode.widgets.find(w => w && w.name === "tools");
|
||||
const useToolChoiceWidget = settingsNode.widgets.find(w => w && w.name === "useToolChoice");
|
||||
const toolChoiceWidget = settingsNode.widgets.find(w => w && w.name === "toolChoice");
|
||||
|
||||
function toggleWidgetState(useWidget, paramWidget) {
|
||||
if (!useWidget || !paramWidget) return;
|
||||
@@ -1368,6 +1378,11 @@ function textInferenceSettingsToggleHandler(settingsNode) {
|
||||
if (useTemperatureWidget && temperatureWidget) toggleWidgetState(useTemperatureWidget, temperatureWidget);
|
||||
if (useTopPWidget && topPWidget) toggleWidgetState(useTopPWidget, topPWidget);
|
||||
if (useTopKWidget && topKWidget) toggleWidgetState(useTopKWidget, topKWidget);
|
||||
if (useStopSequencesWidget && stopSequencesWidget) toggleWidgetState(useStopSequencesWidget, stopSequencesWidget);
|
||||
if (usePresencePenaltyWidget && presencePenaltyWidget) toggleWidgetState(usePresencePenaltyWidget, presencePenaltyWidget);
|
||||
if (useFrequencyPenaltyWidget && frequencyPenaltyWidget) toggleWidgetState(useFrequencyPenaltyWidget, frequencyPenaltyWidget);
|
||||
if (useToolsWidget && toolsWidget) toggleWidgetState(useToolsWidget, toolsWidget);
|
||||
if (useToolChoiceWidget && toolChoiceWidget) toggleWidgetState(useToolChoiceWidget, toolChoiceWidget);
|
||||
}
|
||||
|
||||
function videoSettingsToggleHandler(settingsNode) {
|
||||
@@ -2727,6 +2742,8 @@ function videoModelSearchFilterHandler(videoModelSearchNode) {
|
||||
"bytedance:2@1 (Seedance 1.0 Pro)", "bytedance:1@1 (Seedance 1.0 Lite)",
|
||||
"bytedance:5@1 (OmniHuman 1)", "bytedance:5@2 (OmniHuman 1.5)",
|
||||
"bytedance:seedance@1.5-pro (Seedance 1.5 Pro)",
|
||||
"bytedance:seedance@2.0-fast (Seedance 2.0 Fast)",
|
||||
"bytedance:seedance@2.0 (Seedance 2.0)",
|
||||
],
|
||||
"MiniMax": [
|
||||
"minimax:1@1 (MiniMax 01 Base)", "minimax:2@1 (MiniMax 01 Director)",
|
||||
@@ -2838,6 +2855,8 @@ function videoModelSearchFilterHandler(videoModelSearchNode) {
|
||||
"bytedance:5@1": {"width": 1024, "height": 1024},
|
||||
"bytedance:5@2": {"width": 1024, "height": 1024},
|
||||
"bytedance:seedance@1.5-pro": {"width": 864, "height": 496},
|
||||
"bytedance:seedance@2.0-fast": {"width": 864, "height": 496},
|
||||
"bytedance:seedance@2.0": {"width": 864, "height": 496},
|
||||
"minimax:1@1": {"width": 1366, "height": 768},
|
||||
"minimax:2@1": {"width": 1366, "height": 768},
|
||||
"minimax:2@3": {"width": 1366, "height": 768},
|
||||
@@ -2928,6 +2947,8 @@ function videoModelSearchFilterHandler(videoModelSearchNode) {
|
||||
"bytedance:5@1": null, // No resolution support
|
||||
"bytedance:5@2": null, // No resolution support
|
||||
"bytedance:seedance@1.5-pro": "480p",
|
||||
"bytedance:seedance@2.0-fast": "480p",
|
||||
"bytedance:seedance@2.0": "480p",
|
||||
"minimax:1@1": "768p",
|
||||
"minimax:2@1": "768p",
|
||||
"minimax:2@3": "768p",
|
||||
@@ -3200,6 +3221,9 @@ function textModelSearchFilterHandler(textModelSearchNode) {
|
||||
"Google": [
|
||||
"google:gemini@3-flash (Gemini 3 Flash)",
|
||||
],
|
||||
"Zai": [
|
||||
"zai-glm-5-1 (ZAI GLM 5.1)",
|
||||
],
|
||||
};
|
||||
|
||||
function filterModelList() {
|
||||
@@ -3272,6 +3296,9 @@ function audioModelSearchFilterHandler(audioModelSearchNode) {
|
||||
"inworld:tts@1.5-mini (Inworld TTS-1.5 Mini)",
|
||||
"inworld:tts@1.5-max (Inworld TTS-1.5 Max)",
|
||||
],
|
||||
"Google": [
|
||||
"google:gemini@3.1-flash-tts (Gemini 3.1 Flash TTS)",
|
||||
],
|
||||
};
|
||||
|
||||
function filterModelList() {
|
||||
@@ -4749,6 +4776,64 @@ function audioInferenceInputsToggleHandler(audioInputsNode) {
|
||||
}
|
||||
}
|
||||
|
||||
function audioInferenceSpeechVoicesToggleHandler(voicesNode) {
|
||||
if (!voicesNode?.widgets) return;
|
||||
|
||||
function toggleWidgetState(useWidget, paramWidget, paramName) {
|
||||
if (!useWidget || !paramWidget) return;
|
||||
|
||||
function toggleEnabled() {
|
||||
const enabled = useWidget.value === true;
|
||||
|
||||
if (paramWidget.inputEl) {
|
||||
paramWidget.inputEl.disabled = !enabled;
|
||||
paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5";
|
||||
paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed";
|
||||
paramWidget.inputEl.readOnly = !enabled;
|
||||
}
|
||||
|
||||
paramWidget.disabled = !enabled;
|
||||
|
||||
if (!paramWidget.inputEl) {
|
||||
const nodeElement = voicesNode.htmlElements?.widgetsContainer || voicesNode.htmlElements;
|
||||
if (nodeElement) {
|
||||
const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`);
|
||||
if (input) {
|
||||
input.disabled = !enabled;
|
||||
input.style.opacity = enabled ? "1" : "0.5";
|
||||
input.style.cursor = enabled ? "text" : "not-allowed";
|
||||
input.readOnly = !enabled;
|
||||
if (input.tagName === "SELECT") {
|
||||
input.style.pointerEvents = enabled ? "auto" : "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
voicesNode.setDirtyCanvas(true);
|
||||
}
|
||||
|
||||
appendWidgetCB(useWidget, () => {
|
||||
setTimeout(toggleEnabled, 50);
|
||||
});
|
||||
|
||||
setTimeout(toggleEnabled, 100);
|
||||
}
|
||||
|
||||
for (let i = 1; i <= 4; i++) {
|
||||
const useVoiceWidget = voicesNode.widgets.find((w) => w && w.name === `useVoice${i}`);
|
||||
const speakerWidget = voicesNode.widgets.find((w) => w && w.name === `speaker${i}`);
|
||||
const voiceWidget = voicesNode.widgets.find((w) => w && w.name === `voice${i}`);
|
||||
|
||||
if (useVoiceWidget && speakerWidget) {
|
||||
toggleWidgetState(useVoiceWidget, speakerWidget, `speaker${i}`);
|
||||
}
|
||||
if (useVoiceWidget && voiceWidget) {
|
||||
toggleWidgetState(useVoiceWidget, voiceWidget, `voice${i}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
notifyUser,
|
||||
promptEnhanceHandler,
|
||||
@@ -4816,6 +4901,7 @@ export {
|
||||
wanAnimateAdvancedFeatureSettingsToggleHandler,
|
||||
videoAdvancedFeatureInputsToggleHandler,
|
||||
audioInferenceInputsToggleHandler,
|
||||
audioInferenceSpeechVoicesToggleHandler,
|
||||
};
|
||||
|
||||
function googleProviderSettingsToggleHandler(googleNode) {
|
||||
@@ -4900,6 +4986,8 @@ function settingsToggleHandler(settingsNode) {
|
||||
const trueCFGScaleWidget = settingsNode.widgets.find(w => w.name === "trueCFGScale");
|
||||
const useQualityWidget = settingsNode.widgets.find(w => w.name === "useQuality");
|
||||
const qualityWidget = settingsNode.widgets.find(w => w.name === "quality");
|
||||
const useBackgroundWidget = settingsNode.widgets.find(w => w.name === "useBackground");
|
||||
const backgroundWidget = settingsNode.widgets.find(w => w.name === "background");
|
||||
const usePromptExtendWidget = settingsNode.widgets.find(w => w.name === "usePromptExtend");
|
||||
const promptExtendWidget = settingsNode.widgets.find(w => w.name === "promptExtend");
|
||||
const useEditRegionsWidget = settingsNode.widgets.find(w => w.name === "useEditRegions");
|
||||
@@ -4972,6 +5060,9 @@ function settingsToggleHandler(settingsNode) {
|
||||
if (useQualityWidget && qualityWidget) {
|
||||
toggleWidgetState(useQualityWidget, qualityWidget, "quality");
|
||||
}
|
||||
if (useBackgroundWidget && backgroundWidget) {
|
||||
toggleWidgetState(useBackgroundWidget, backgroundWidget, "background");
|
||||
}
|
||||
if (usePromptExtendWidget && promptExtendWidget) {
|
||||
toggleWidgetState(usePromptExtendWidget, promptExtendWidget, "promptExtend");
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class RunwareAudioInference:
|
||||
"default": "URL",
|
||||
"tooltip": "Output type for the generated audio"
|
||||
}),
|
||||
"outputFormat": (["MP3", "MP4"], {
|
||||
"outputFormat": (["MP3", "MP4", "WAV", "FLAC", "OGG"], {
|
||||
"default": "MP3",
|
||||
"tooltip": "Format of the output audio"
|
||||
}),
|
||||
|
||||
@@ -14,20 +14,6 @@ class RunwareAudioInferenceSpeech:
|
||||
"calm", "fluent", "whisper",
|
||||
]
|
||||
|
||||
SPEECH_LANGUAGES = [
|
||||
"Auto",
|
||||
"Chinese",
|
||||
"English",
|
||||
"Japanese",
|
||||
"Korean",
|
||||
"German",
|
||||
"French",
|
||||
"Russian",
|
||||
"Portuguese",
|
||||
"Spanish",
|
||||
"Italian",
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@@ -50,7 +36,7 @@ class RunwareAudioInferenceSpeech:
|
||||
"default": "",
|
||||
"tooltip": "Voice identifier.",
|
||||
}),
|
||||
"useSpeed": ("BOOLEAN", {"default": True, "tooltip": "Include speed (speech.speed)"}),
|
||||
"useSpeed": ("BOOLEAN", {"default": False, "tooltip": "Include speed (speech.speed)"}),
|
||||
"speed": ("FLOAT", {
|
||||
"default": 1.0,
|
||||
"min": 0.5,
|
||||
@@ -58,7 +44,7 @@ class RunwareAudioInferenceSpeech:
|
||||
"step": 0.01,
|
||||
"tooltip": "Speech rate multiplier (speech.speed)",
|
||||
}),
|
||||
"useVolume": ("BOOLEAN", {"default": True, "tooltip": "Include volume (speech.volume)"}),
|
||||
"useVolume": ("BOOLEAN", {"default": False, "tooltip": "Include volume (speech.volume)"}),
|
||||
"volume": ("FLOAT", {
|
||||
"default": 1.0,
|
||||
"min": 1.0,
|
||||
@@ -87,9 +73,12 @@ class RunwareAudioInferenceSpeech:
|
||||
"default": False,
|
||||
"tooltip": "Enable to include language (speech.language).",
|
||||
}),
|
||||
"language": (cls.SPEECH_LANGUAGES, {
|
||||
"language": ("STRING", {
|
||||
"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.",
|
||||
"tooltip": "Language of the input text (for example: en-US). Applies to all variants. Only used when 'Use Language' is enabled.",
|
||||
}),
|
||||
"voices": ("RUNWAREAUDIOINFERENCESPEECHVOICES", {
|
||||
"tooltip": "Optional multi-speaker voices array (speech.voices[]). If provided, it takes precedence over speech.voice.",
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -108,9 +97,9 @@ class RunwareAudioInferenceSpeech:
|
||||
text = (kwargs.get("text") or "").strip()
|
||||
voice = (kwargs.get("voice") or "").strip()
|
||||
use_voice = kwargs.get("useVoice", False)
|
||||
use_speed = kwargs.get("useSpeed", True)
|
||||
use_speed = kwargs.get("useSpeed", False)
|
||||
speed = float(kwargs.get("speed", 1.0))
|
||||
use_volume = kwargs.get("useVolume", True)
|
||||
use_volume = kwargs.get("useVolume", False)
|
||||
volume = float(kwargs.get("volume", 1.0))
|
||||
use_pitch = kwargs.get("usePitch", False)
|
||||
pitch = float(kwargs.get("pitch", 0.0))
|
||||
@@ -119,10 +108,13 @@ class RunwareAudioInferenceSpeech:
|
||||
use_tone = kwargs.get("useTone", False)
|
||||
tone_str = kwargs.get("tone", "") or ""
|
||||
use_language = kwargs.get("useLanguage", False)
|
||||
language = kwargs.get("language", "Auto")
|
||||
language = (kwargs.get("language") or "Auto").strip()
|
||||
voices = kwargs.get("voices")
|
||||
|
||||
speech: Dict[str, Any] = {"text": text}
|
||||
if use_voice:
|
||||
if isinstance(voices, list) and len(voices) > 0:
|
||||
speech["voices"] = voices
|
||||
elif use_voice:
|
||||
speech["voice"] = voice
|
||||
if use_speed:
|
||||
speech["speed"] = speed
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
"""
|
||||
Runware Audio Inference Speech Voices node:
|
||||
Builds speech.voices[] for multi-speaker audio inference speech payloads.
|
||||
"""
|
||||
|
||||
import re
|
||||
from typing import Dict, List
|
||||
|
||||
|
||||
class RunwareAudioInferenceSpeechVoices:
|
||||
"""Build speech.voices[] list for Runware Audio Inference."""
|
||||
|
||||
MAX_VOICES = 4
|
||||
_SPEAKER_ALIAS_PATTERN = re.compile(r"^[A-Za-z0-9]+$")
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
optional_inputs = {}
|
||||
for i in range(1, cls.MAX_VOICES + 1):
|
||||
optional_inputs[f"useVoice{i}"] = ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": f"Enable to include speaker/voice pair #{i} in speech.voices.",
|
||||
})
|
||||
optional_inputs[f"speaker{i}"] = ("STRING", {
|
||||
"default": f"Speaker{i}",
|
||||
"tooltip": "Unique alphanumeric speaker alias (speech.voices[].speaker).",
|
||||
})
|
||||
optional_inputs[f"voice{i}"] = ("STRING", {
|
||||
"default": "",
|
||||
"tooltip": "Voice name for this speaker (speech.voices[].voice).",
|
||||
})
|
||||
|
||||
return {
|
||||
"required": {},
|
||||
"optional": optional_inputs,
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("RUNWAREAUDIOINFERENCESPEECHVOICES",)
|
||||
RETURN_NAMES = ("voices",)
|
||||
FUNCTION = "createVoices"
|
||||
CATEGORY = "Runware/Audio"
|
||||
DESCRIPTION = (
|
||||
"Build speech.voices[] for multi-speaker synthesis. "
|
||||
"Each item contains speaker (unique alphanumeric alias) and voice name."
|
||||
)
|
||||
|
||||
def createVoices(self, **kwargs) -> tuple[list[dict[str, str]],]:
|
||||
voices: list[dict[str, str]] = []
|
||||
seen_speakers = set()
|
||||
|
||||
for i in range(1, self.MAX_VOICES + 1):
|
||||
use_voice = bool(kwargs.get(f"useVoice{i}", False))
|
||||
if not use_voice:
|
||||
continue
|
||||
|
||||
speaker = (kwargs.get(f"speaker{i}") or "").strip()
|
||||
voice = (kwargs.get(f"voice{i}") or "").strip()
|
||||
|
||||
if not speaker or not voice:
|
||||
raise Exception(
|
||||
f"Voice #{i} is enabled, but speaker{i} and voice{i} must both be provided."
|
||||
)
|
||||
if not self._SPEAKER_ALIAS_PATTERN.match(speaker):
|
||||
raise Exception(
|
||||
f"speaker{i} must be alphanumeric only (got: '{speaker}')."
|
||||
)
|
||||
if speaker in seen_speakers:
|
||||
raise Exception(
|
||||
f"Duplicate speaker alias '{speaker}'. Each speaker must be unique."
|
||||
)
|
||||
|
||||
seen_speakers.add(speaker)
|
||||
voices.append({
|
||||
"speaker": speaker,
|
||||
"voice": voice,
|
||||
})
|
||||
|
||||
return (voices,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareAudioInferenceSpeechVoices": RunwareAudioInferenceSpeechVoices,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareAudioInferenceSpeechVoices": "Runware Audio Inference Speech Voices",
|
||||
}
|
||||
@@ -40,6 +40,9 @@ class RunwareAudioModelSearch:
|
||||
"inworld:tts@1.5-mini (Inworld TTS-1.5 Mini)",
|
||||
"inworld:tts@1.5-max (Inworld TTS-1.5 Max)",
|
||||
],
|
||||
"Google": [
|
||||
"google:gemini@3.1-flash-tts (Gemini 3.1 Flash TTS)",
|
||||
],
|
||||
}
|
||||
|
||||
MODEL_PROVIDERS = [
|
||||
@@ -53,6 +56,7 @@ class RunwareAudioModelSearch:
|
||||
"xAI",
|
||||
"MiniMax",
|
||||
"Inworld",
|
||||
"Google",
|
||||
]
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
from typing import List
|
||||
|
||||
|
||||
class referenceAudios:
|
||||
"""Reference Audios node for configuring reference audio inputs"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
"Audio1": ("STRING", {
|
||||
"default": "",
|
||||
"tooltip": "MediaUUID for the first reference audio from Runware Media Upload node.",
|
||||
}),
|
||||
"Audio2": ("STRING", {
|
||||
"default": "",
|
||||
"tooltip": "MediaUUID for the second reference audio from Runware Media Upload node.",
|
||||
}),
|
||||
"Audio3": ("STRING", {
|
||||
"default": "",
|
||||
"tooltip": "MediaUUID for the third reference audio from Runware Media Upload node.",
|
||||
}),
|
||||
"Audio4": ("STRING", {
|
||||
"default": "",
|
||||
"tooltip": "MediaUUID for the fourth reference audio from Runware Media Upload node.",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
DESCRIPTION = "Configure multiple reference audios (mediaUUIDs) for video inference inputs."
|
||||
FUNCTION = "createReferenceAudios"
|
||||
RETURN_TYPES = ("RUNWAREINPUTAUDIOS",)
|
||||
RETURN_NAMES = ("Reference Audios",)
|
||||
CATEGORY = "Runware"
|
||||
|
||||
def createReferenceAudios(self, **kwargs) -> tuple[List[str]]:
|
||||
"""Create list of reference audio UUIDs from provided parameters"""
|
||||
audioList = []
|
||||
|
||||
for i in range(1, 5):
|
||||
audioKey = f"Audio{i}"
|
||||
audioUuid = kwargs.get(audioKey)
|
||||
|
||||
if audioUuid and audioUuid.strip() != "":
|
||||
audioList.append(audioUuid.strip())
|
||||
|
||||
return (audioList,)
|
||||
+3
-3
@@ -35,7 +35,7 @@ class RunwareSave3D:
|
||||
FUNCTION = "save_3d"
|
||||
OUTPUT_NODE = True
|
||||
CATEGORY = "Runware"
|
||||
DESCRIPTION = "Save 3D model files (GLB/PLY) from Runware 3D Inference to the output folder."
|
||||
DESCRIPTION = "Save 3D model files (GLB/PLY/FBX) from Runware 3D Inference to the output folder."
|
||||
|
||||
def save_3d(self, filenamePrefix="ComfyUI", **kwargs):
|
||||
"""Save 3D file from URL"""
|
||||
@@ -55,8 +55,8 @@ class RunwareSave3D:
|
||||
url_without_params = file_url.split('?')[0]
|
||||
extension = url_without_params.split('.')[-1].lower()
|
||||
|
||||
if extension not in ["glb", "ply"]:
|
||||
raise Exception(f"Unsupported 3D file extension '{extension}' from URL. Expected .glb or .ply.")
|
||||
if extension not in ["glb", "ply", "fbx"]:
|
||||
raise Exception(f"Unsupported 3D file extension '{extension}' from URL. Expected .glb, .ply, or .fbx.")
|
||||
|
||||
# Sanitize filenamePrefix to prevent path traversal or arbitrary subdir creation
|
||||
prefix_basename = os.path.basename(
|
||||
|
||||
+17
-3
@@ -1,7 +1,9 @@
|
||||
"""
|
||||
Runware Image Inference Settings (registered as Runware Settings for workflow compatibility).
|
||||
Provides settings for image generation including temperature, systemPrompt, topP,
|
||||
editRegions, thinking (boolean), thinkingLevel (high/medium/low), sequential, and colorPalette (from Runware Image Inference Settings Color Palette).
|
||||
Provides settings for image generation including temperature, systemPrompt, topP, layers,
|
||||
quality, background, promptExtend, editRegions, thinking (boolean),
|
||||
thinkingLevel (high/medium/low), sequential, and colorPalette
|
||||
(from Runware Image Inference Settings Color Palette).
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -126,6 +128,14 @@ class RunwareSettings:
|
||||
"default": "high",
|
||||
"tooltip": "Reasoning level for visual understanding. Only used when 'Use Thinking Level' is enabled.",
|
||||
}),
|
||||
"useBackground": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include background style in API request",
|
||||
"default": False,
|
||||
}),
|
||||
"background": (["auto", "transparent", "opaque"], {
|
||||
"default": "auto",
|
||||
"tooltip": "Background style for the generated image. Only used when 'Use Background' is enabled.",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +144,7 @@ class RunwareSettings:
|
||||
FUNCTION = "createSettings"
|
||||
CATEGORY = "Runware"
|
||||
DESCRIPTION = (
|
||||
"Configure general settings for image generation: temperature, system prompt, top-p, layers, quality, "
|
||||
"Configure general settings for image generation: temperature, system prompt, top-p, layers, quality, background, "
|
||||
"promptExtend, editRegions (JSON), thinking (boolean), thinkingLevel (high/medium/low), sequential, and optional colorPalette from the Color Palette node."
|
||||
)
|
||||
|
||||
@@ -148,6 +158,7 @@ class RunwareSettings:
|
||||
useLayers = kwargs.get("useLayers", False)
|
||||
useTrueCFGScale = kwargs.get("useTrueCFGScale", False)
|
||||
useQuality = kwargs.get("useQuality", False)
|
||||
useBackground = kwargs.get("useBackground", False)
|
||||
usePromptExtend = kwargs.get("usePromptExtend", False)
|
||||
promptExtend = kwargs.get("promptExtend", False)
|
||||
useEditRegions = kwargs.get("useEditRegions", False)
|
||||
@@ -162,6 +173,7 @@ class RunwareSettings:
|
||||
layers = kwargs.get("layers")
|
||||
trueCFGScale = kwargs.get("trueCFGScale")
|
||||
quality = kwargs.get("quality", "medium")
|
||||
background = kwargs.get("background", "auto")
|
||||
|
||||
# Build settings dictionary - only include what is enabled
|
||||
settings: Dict[str, Any] = {}
|
||||
@@ -179,6 +191,8 @@ class RunwareSettings:
|
||||
settings["true_cfg_scale"] = float(trueCFGScale)
|
||||
if useQuality:
|
||||
settings["quality"] = quality
|
||||
if useBackground:
|
||||
settings["background"] = background
|
||||
if usePromptExtend:
|
||||
settings["promptExtend"] = bool(promptExtend)
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
from typing import Any, Dict, Tuple
|
||||
import json
|
||||
from typing import Any, Dict, List, Tuple
|
||||
|
||||
|
||||
class RunwareTextInferenceSettings:
|
||||
"""Optional generation controls for Runware Text Inference (flat task.settings per API)."""
|
||||
|
||||
_MAX_SYSTEM_CHARS = 200000
|
||||
_MAX_TOKENS_CAP = 196608
|
||||
_MAX_TOKENS_CAP = 131072
|
||||
_MAX_TOP_K = 100647
|
||||
_MAX_STOP_ITEMS = 5
|
||||
_MAX_STOP_ITEM_CHARS = 50
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -16,17 +20,17 @@ class RunwareTextInferenceSettings:
|
||||
"default": False,
|
||||
"tooltip": "Include systemPrompt in settings.",
|
||||
}),
|
||||
"system": ("STRING", {
|
||||
"systemPrompt": ("STRING", {
|
||||
"multiline": True,
|
||||
"default": "",
|
||||
"tooltip": "System instruction (max 200,000 characters). Sent as systemPrompt.",
|
||||
"tooltip": "System instruction (max 200,000 chars).",
|
||||
}),
|
||||
"useMaxTokens": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": "Include maxTokens in settings.",
|
||||
}),
|
||||
"maxTokens": ("INT", {
|
||||
"default": 32768,
|
||||
"default": 4096,
|
||||
"min": 1,
|
||||
"max": cls._MAX_TOKENS_CAP,
|
||||
"step": 1,
|
||||
@@ -38,21 +42,21 @@ class RunwareTextInferenceSettings:
|
||||
}),
|
||||
"temperature": ("FLOAT", {
|
||||
"default": 1.0,
|
||||
"min": 0.01,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"step": 0.01,
|
||||
"tooltip": "Sampling temperature on (0, 1].",
|
||||
"tooltip": "Sampling temperature (0.0–1.0).",
|
||||
}),
|
||||
"useTopP": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": "Include topP in settings.",
|
||||
}),
|
||||
"topP": ("FLOAT", {
|
||||
"default": 0.95,
|
||||
"min": 0.0,
|
||||
"default": 1.0,
|
||||
"min": 0.01,
|
||||
"max": 1.0,
|
||||
"step": 0.01,
|
||||
"tooltip": "Nucleus sampling (0.0–1.0).",
|
||||
"tooltip": "Nucleus sampling (0.01–1.0).",
|
||||
}),
|
||||
"useTopK": ("BOOLEAN", {
|
||||
"default": False,
|
||||
@@ -61,13 +65,63 @@ class RunwareTextInferenceSettings:
|
||||
"topK": ("INT", {
|
||||
"default": 40,
|
||||
"min": 1,
|
||||
"max": 128,
|
||||
"max": cls._MAX_TOP_K,
|
||||
"step": 1,
|
||||
"tooltip": "Top-k sampling (1–128).",
|
||||
"tooltip": f"Top-k sampling (1–{cls._MAX_TOP_K}).",
|
||||
}),
|
||||
"thinkingLevel": (["off", "minimal", "low", "medium", "high"], {
|
||||
"default": "off",
|
||||
"tooltip": "thinkingLevel in settings (omit when off).",
|
||||
# Keep this in the original slot to avoid shifting legacy widgets_values.
|
||||
"thinkingLevel": (["none", "low", "medium", "high"], {
|
||||
"default": "none",
|
||||
"tooltip": "Extended reasoning level: none, low, medium, high.",
|
||||
}),
|
||||
"useStopSequences": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": "Include stopSequences in settings.",
|
||||
}),
|
||||
"stopSequences": ("STRING", {
|
||||
"multiline": True,
|
||||
"default": "",
|
||||
"tooltip": "Stop sequences: one per line (max 5 items, 50 chars each).",
|
||||
}),
|
||||
"usePresencePenalty": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": "Include presencePenalty in settings.",
|
||||
}),
|
||||
"presencePenalty": ("FLOAT", {
|
||||
"default": 0.0,
|
||||
"min": -2.0,
|
||||
"max": 2.0,
|
||||
"step": 0.01,
|
||||
"tooltip": "Presence penalty (-2.0 to 2.0).",
|
||||
}),
|
||||
"useFrequencyPenalty": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": "Include frequencyPenalty in settings.",
|
||||
}),
|
||||
"frequencyPenalty": ("FLOAT", {
|
||||
"default": 0.0,
|
||||
"min": -2.0,
|
||||
"max": 2.0,
|
||||
"step": 0.01,
|
||||
"tooltip": "Frequency penalty (-2.0 to 2.0).",
|
||||
}),
|
||||
"useTools": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": "Include tools in settings.",
|
||||
}),
|
||||
"tools": ("STRING", {
|
||||
"multiline": True,
|
||||
"default": "[]",
|
||||
"tooltip": "JSON array for tools.",
|
||||
}),
|
||||
"useToolChoice": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": "Include toolChoice in settings.",
|
||||
}),
|
||||
"toolChoice": ("STRING", {
|
||||
"multiline": True,
|
||||
"default": "{}",
|
||||
"tooltip": "JSON object for toolChoice.",
|
||||
}),
|
||||
},
|
||||
}
|
||||
@@ -77,34 +131,115 @@ class RunwareTextInferenceSettings:
|
||||
FUNCTION = "create_settings"
|
||||
CATEGORY = "Runware/Text"
|
||||
DESCRIPTION = (
|
||||
"Optional text inference settings (flat: systemPrompt, maxTokens, temperature, topP, topK, thinkingLevel). "
|
||||
"Optional text inference settings (systemPrompt, maxTokens, temperature, topP, topK, "
|
||||
"stopSequences, presencePenalty, frequencyPenalty, tools, toolChoice, thinkingLevel). "
|
||||
"Connect to Runware Text Inference."
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _parse_json_setting(raw: Any, expected_type: type, field_name: str) -> Any:
|
||||
if isinstance(raw, expected_type):
|
||||
return raw
|
||||
if raw is None:
|
||||
return expected_type()
|
||||
|
||||
text = str(raw).strip()
|
||||
if not text:
|
||||
return expected_type()
|
||||
|
||||
try:
|
||||
parsed = json.loads(text)
|
||||
except Exception as exc:
|
||||
raise Exception(f"{field_name} must be valid JSON.") from exc
|
||||
|
||||
if not isinstance(parsed, expected_type):
|
||||
expected = "array" if expected_type is list else "object"
|
||||
raise Exception(f"{field_name} must be a JSON {expected}.")
|
||||
return parsed
|
||||
|
||||
def _parse_stop_sequences(self, raw: Any) -> List[str]:
|
||||
if raw is None:
|
||||
return []
|
||||
|
||||
items: List[str] = []
|
||||
if isinstance(raw, (list, tuple)):
|
||||
for item in raw:
|
||||
text = str(item).strip()
|
||||
if text:
|
||||
items.append(text)
|
||||
else:
|
||||
text = str(raw).strip()
|
||||
if text:
|
||||
normalized = text.replace("\r\n", "\n").replace(",", "\n")
|
||||
items = [segment.strip() for segment in normalized.split("\n") if segment.strip()]
|
||||
|
||||
if len(items) > self._MAX_STOP_ITEMS:
|
||||
raise Exception(f"stopSequences supports up to {self._MAX_STOP_ITEMS} items.")
|
||||
for idx, item in enumerate(items, start=1):
|
||||
if len(item) > self._MAX_STOP_ITEM_CHARS:
|
||||
raise Exception(
|
||||
f"stopSequences item {idx} exceeds {self._MAX_STOP_ITEM_CHARS} characters."
|
||||
)
|
||||
return items
|
||||
|
||||
@staticmethod
|
||||
def _normalize_thinking_level(raw: Any) -> str:
|
||||
value = str(raw or "none").strip().lower()
|
||||
# Backward compatibility with older workflows.
|
||||
aliases = {
|
||||
"off": "none",
|
||||
"minimal": "low",
|
||||
}
|
||||
value = aliases.get(value, value)
|
||||
if value not in ("none", "low", "medium", "high"):
|
||||
return "none"
|
||||
return value
|
||||
|
||||
def create_settings(self, **kwargs) -> Tuple[Dict[str, Any], ...]:
|
||||
out: Dict[str, Any] = {}
|
||||
|
||||
if kwargs.get("useSystemPrompt", False):
|
||||
sys_text = (kwargs.get("system") or "").strip()
|
||||
sys_text = (kwargs.get("systemPrompt") or kwargs.get("system") or "").strip()
|
||||
if sys_text:
|
||||
if len(sys_text) > self._MAX_SYSTEM_CHARS:
|
||||
sys_text = sys_text[: self._MAX_SYSTEM_CHARS]
|
||||
out["systemPrompt"] = sys_text
|
||||
|
||||
if kwargs.get("useMaxTokens", False):
|
||||
out["maxTokens"] = int(kwargs.get("maxTokens", 32768))
|
||||
out["maxTokens"] = int(kwargs.get("maxTokens", 4096))
|
||||
|
||||
if kwargs.get("useTemperature", False):
|
||||
out["temperature"] = float(kwargs.get("temperature", 1.0))
|
||||
|
||||
if kwargs.get("useTopP", False):
|
||||
out["topP"] = float(kwargs.get("topP", 0.95))
|
||||
out["topP"] = float(kwargs.get("topP", 1.0))
|
||||
|
||||
if kwargs.get("useTopK", False):
|
||||
out["topK"] = int(kwargs.get("topK", 40))
|
||||
|
||||
tl = kwargs.get("thinkingLevel", "off")
|
||||
if tl != "off":
|
||||
if kwargs.get("useStopSequences", False):
|
||||
parsed_stop = self._parse_stop_sequences(kwargs.get("stopSequences", ""))
|
||||
if parsed_stop:
|
||||
out["stopSequences"] = parsed_stop
|
||||
|
||||
if kwargs.get("usePresencePenalty", False):
|
||||
out["presencePenalty"] = float(kwargs.get("presencePenalty", 0.0))
|
||||
|
||||
if kwargs.get("useFrequencyPenalty", False):
|
||||
out["frequencyPenalty"] = float(kwargs.get("frequencyPenalty", 0.0))
|
||||
|
||||
if kwargs.get("useTools", False):
|
||||
parsed_tools = self._parse_json_setting(kwargs.get("tools"), list, "tools")
|
||||
if parsed_tools:
|
||||
out["tools"] = parsed_tools
|
||||
|
||||
if kwargs.get("useToolChoice", False):
|
||||
parsed_choice = self._parse_json_setting(kwargs.get("toolChoice"), dict, "toolChoice")
|
||||
if parsed_choice:
|
||||
out["toolChoice"] = parsed_choice
|
||||
|
||||
tl = self._normalize_thinking_level(kwargs.get("thinkingLevel", "none"))
|
||||
if tl != "none":
|
||||
out["thinkingLevel"] = tl
|
||||
|
||||
if not out:
|
||||
|
||||
@@ -16,6 +16,9 @@ class RunwareTextModelSearch:
|
||||
"Google": [
|
||||
"google:gemini@3-flash (Gemini 3 Flash)",
|
||||
],
|
||||
"Zai": [
|
||||
"zai-glm-5-1 (ZAI GLM 5.1)",
|
||||
],
|
||||
}
|
||||
|
||||
MODEL_PROVIDERS = [
|
||||
@@ -23,6 +26,7 @@ class RunwareTextModelSearch:
|
||||
"Google",
|
||||
"MiniMax",
|
||||
"OpenAI",
|
||||
"Zai",
|
||||
]
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -15,7 +15,7 @@ class threeDInference:
|
||||
}
|
||||
|
||||
# Output formats
|
||||
OUTPUT_FORMATS = ["GLB", "PLY"]
|
||||
OUTPUT_FORMATS = ["GLB", "PLY", "FBX"]
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
|
||||
@@ -41,14 +41,14 @@ class videoInferenceInputs:
|
||||
"Background": ("IMAGE", {
|
||||
"tooltip": "Background image for video generation. Connect a Load Image node to provide the background.",
|
||||
}),
|
||||
"References": ("RUNWAREVIDEOINPUTSREFERENCEIMAGES", {
|
||||
"tooltip": "Connect the Video Inputs References node to provide reference images."
|
||||
"References Images": ("RUNWAREVIDEOINPUTSREFERENCEIMAGES", {
|
||||
"tooltip": "Connect the Runware Video Inference Inputs Reference Images node to provide reference images."
|
||||
}),
|
||||
"Reference Videos": ("RUNWAREREFERENCEVIDEOS", {
|
||||
"tooltip": "Connect the Reference Videos node to provide reference video mediaUUIDs."
|
||||
"tooltip": "Connect the Runware Video Inference Inputs Reference Videos node to provide reference video mediaUUIDs."
|
||||
}),
|
||||
"Reference Voices": ("RUNWAREREFERENCEVOICES", {
|
||||
"tooltip": "Connect the Reference Voices node to provide reference voice URLs or mediaUUIDs."
|
||||
"tooltip": "Connect the Runware Video Inference Inputs Reference Voices node to provide reference voice URLs or mediaUUIDs."
|
||||
}),
|
||||
"draftId": ("STRING", {
|
||||
"default": "",
|
||||
@@ -63,6 +63,9 @@ class videoInferenceInputs:
|
||||
"Elements": ("RUNWAREVIDEOINFERENCEELEMENTS", {
|
||||
"tooltip": "Connect Runware Video Inference Elements (one element) or Runware Video Inference Elements Combine (several) for inputs.elements (Kling, etc.).",
|
||||
}),
|
||||
"Reference Audios": ("RUNWAREINPUTAUDIOS", {
|
||||
"tooltip": "Connect the Runware Video Inference Inputs Reference Audios node to provide reference audio mediaUUIDs."
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,8 +89,9 @@ class videoInferenceInputs:
|
||||
frame = kwargs.get("Frame", None)
|
||||
background = kwargs.get("Background", None)
|
||||
frameImages = kwargs.get("Frame Images", None)
|
||||
references = kwargs.get("References", None)
|
||||
references = kwargs.get("References Images", kwargs.get("References", None))
|
||||
referenceVideos = kwargs.get("Reference Videos", None)
|
||||
referenceAudios = kwargs.get("Reference Audios", None)
|
||||
referenceVoices = kwargs.get("Reference Voices", None)
|
||||
draftId = kwargs.get("draftId", "")
|
||||
videoId = kwargs.get("videoId", "")
|
||||
@@ -143,6 +147,9 @@ class videoInferenceInputs:
|
||||
if referenceVideos is not None and len(referenceVideos) > 0:
|
||||
inputs["referenceVideos"] = referenceVideos
|
||||
|
||||
if referenceAudios is not None and len(referenceAudios) > 0:
|
||||
inputs["referenceAudios"] = referenceAudios
|
||||
|
||||
if referenceVoices is not None and len(referenceVoices) > 0:
|
||||
inputs["referenceVoices"] = referenceVoices
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from typing import List, Dict, Any
|
||||
class videoInputsReferences:
|
||||
"""Video Inputs References node for configuring reference images with types"""
|
||||
|
||||
MAX_REFERENCES = 4
|
||||
MAX_REFERENCES = 10
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -63,5 +63,5 @@ NODE_CLASS_MAPPINGS = {
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareVideoInputsReferences": "Runware Video Inputs Reference Images",
|
||||
"RunwareVideoInputsReferences": "Runware Video Inference Inputs Reference Images",
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ class videoModelSearch:
|
||||
"bytedance:5@1 (OmniHuman 1)",
|
||||
"bytedance:5@2 (OmniHuman 1.5)",
|
||||
"bytedance:seedance@1.5-pro (Seedance 1.5 Pro)",
|
||||
"bytedance:seedance@2.0-fast (Seedance 2.0 Fast)",
|
||||
"bytedance:seedance@2.0 (Seedance 2.0)",
|
||||
],
|
||||
"MiniMax": [
|
||||
"minimax:1@1 (MiniMax 01 Base)",
|
||||
@@ -172,6 +174,8 @@ class videoModelSearch:
|
||||
"bytedance:5@1": {"width": 1024, "height": 1024},
|
||||
"bytedance:5@2": {"width": 1024, "height": 1024},
|
||||
"bytedance:seedance@1.5-pro": {"width": 864, "height": 496},
|
||||
"bytedance:seedance@2.0-fast": {"width": 864, "height": 496},
|
||||
"bytedance:seedance@2.0": {"width": 864, "height": 496},
|
||||
|
||||
# MiniMax Models
|
||||
"minimax:1@1": {"width": 1366, "height": 768},
|
||||
@@ -304,6 +308,8 @@ class videoModelSearch:
|
||||
"bytedance:5@1": None, # No resolution support (fixed 1024x1024)
|
||||
"bytedance:5@2": None, # No resolution support (fixed 1024x1024)
|
||||
"bytedance:seedance@1.5-pro": "480p",
|
||||
"bytedance:seedance@2.0-fast": "480p",
|
||||
"bytedance:seedance@2.0": "480p",
|
||||
|
||||
# MiniMax Models (support both 768p and 720p, using 768p as primary)
|
||||
"minimax:1@1": "768p",
|
||||
|
||||
@@ -26,21 +26,21 @@ class RunwareVideoSettings:
|
||||
}),
|
||||
"useAudio": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include audio (save video with audio) in video inference settings.",
|
||||
"default": True,
|
||||
"default": False,
|
||||
}),
|
||||
"audio": ("BOOLEAN", {
|
||||
"tooltip": "Save the video with audio. Only used when 'Use Audio' is enabled.",
|
||||
"default": True,
|
||||
"default": False,
|
||||
"label_on": "Enabled",
|
||||
"label_off": "Disabled",
|
||||
}),
|
||||
"usePromptUpsampling": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include promptUpsampling (enhance prompt automatically) in video inference settings.",
|
||||
"default": True,
|
||||
"default": False,
|
||||
}),
|
||||
"promptUpsampling": ("BOOLEAN", {
|
||||
"tooltip": "Enhance prompt automatically for better results. Only used when 'Use Prompt Upsampling' is enabled.",
|
||||
"default": True,
|
||||
"default": False,
|
||||
"label_on": "Enabled",
|
||||
"label_off": "Disabled",
|
||||
}),
|
||||
@@ -193,10 +193,10 @@ class RunwareVideoSettings:
|
||||
"""Create settings dict for Video Inference API"""
|
||||
use_draft = kwargs.get("useDraft", False)
|
||||
draft = kwargs.get("draft", False)
|
||||
use_audio = kwargs.get("useAudio", True)
|
||||
audio = kwargs.get("audio", True)
|
||||
use_prompt_upsampling = kwargs.get("usePromptUpsampling", True)
|
||||
prompt_upsampling = kwargs.get("promptUpsampling", True)
|
||||
use_audio = kwargs.get("useAudio", False)
|
||||
audio = kwargs.get("audio", False)
|
||||
use_prompt_upsampling = kwargs.get("usePromptUpsampling", False)
|
||||
prompt_upsampling = kwargs.get("promptUpsampling", False)
|
||||
use_background_color = kwargs.get("useBackgroundColor", False)
|
||||
background_color = (kwargs.get("backgroundColor") or "").strip()
|
||||
use_remove_background = kwargs.get("useRemoveBackground", False)
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user