Merge pull request #96 from Runware/feature-KlingMultiprompt
Add support for Kling Multiprompt
This commit is contained in:
@@ -53,6 +53,8 @@ from .modules.videoInferenceInputs import videoInferenceInputs
|
||||
from .modules.providerSettings.lightricksProviderSettings import RunwareLightricksProviderSettings
|
||||
from .modules.providerSettings.minimaxProviderSettings import RunwareMiniMaxProviderSettings
|
||||
from .modules.providerSettings.klingProviderSettings import RunwareKlingProviderSettings
|
||||
from .modules.providerSettings.klingMultiPromptSegment import RunwareKlingMultiPromptSegment
|
||||
from .modules.providerSettings.klingProviderSettingsMultiPrompt import RunwareKlingProviderSettingsMultiPrompt
|
||||
from .modules.providerSettings.runwayProviderSettings import RunwareRunwayProviderSettings
|
||||
from .modules.providerSettings.lumaProviderSettings import RunwareLumaProviderSettings
|
||||
from .modules.providerSettings.midjourneyProviderSettings import RunwareMidjourneyProviderSettings
|
||||
@@ -153,6 +155,8 @@ NODE_CLASS_MAPPINGS = {
|
||||
"Runware MiniMax Provider Settings": RunwareMiniMaxProviderSettings,
|
||||
"Runware Luma Provider Settings": RunwareLumaProviderSettings,
|
||||
"Runware KlingAI Provider Settings": RunwareKlingProviderSettings,
|
||||
"Runware Kling MultiPrompt Segment": RunwareKlingMultiPromptSegment,
|
||||
"Runware Kling Provider Settings MultiPrompt": RunwareKlingProviderSettingsMultiPrompt,
|
||||
"Runware Runway Provider Settings": RunwareRunwayProviderSettings,
|
||||
"Runware Midjourney Provider Settings": RunwareMidjourneyProviderSettings,
|
||||
"Runware Mirelo Provider Settings": RunwareMireloProviderSettings,
|
||||
|
||||
@@ -100,6 +100,8 @@ const RUNWARE_NODE_TYPES = {
|
||||
VIDEOINFERENCEINPUTS: "Runware Video Inference Inputs",
|
||||
LIGHTRICKSPROVIDERSETTINGS: "Runware Lightricks Provider Settings",
|
||||
KLINGPROVIDERSETTINGS: "Runware KlingAI Provider Settings",
|
||||
KLINGMULTIPROMPTSEGMENT: "Runware Kling MultiPrompt Segment",
|
||||
KLINGPROVIDERSETTINGSMULTIPROMPT: "Runware Kling Provider Settings MultiPrompt",
|
||||
RUNWAYPROVIDERSETTINGS: "Runware Runway Provider Settings",
|
||||
LUMAPROVIDERSETTINGS: "Runware Luma Provider Settings",
|
||||
MIDJOURNEYPROVIDERSETTINGS: "Runware Midjourney Provider Settings",
|
||||
@@ -349,6 +351,14 @@ const RUNWARE_NODE_PROPS = {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.KLINGMULTIPROMPTSEGMENT]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.KLINGPROVIDERSETTINGSMULTIPROMPT]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.RUNWAYPROVIDERSETTINGS]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
|
||||
@@ -2127,6 +2127,8 @@ function videoModelSearchFilterHandler(videoModelSearchNode) {
|
||||
"klingai:7@1 (KlingAI Lip-Sync)",
|
||||
"klingai:kling@o1 (Kling VIDEO O1)",
|
||||
"klingai:kling-video@2.6-pro (Kling VIDEO 2.6 Pro)",
|
||||
"klingai:kling-video@3-pro (Kling VIDEO 3.0 Pro)",
|
||||
"klingai:kling-video@3-standard (Kling VIDEO 3.0 Standard)",
|
||||
"klingai:avatar@2.0-standard (KlingAI Avatar 2.0 Standard)",
|
||||
"klingai:avatar@2.0-pro (KlingAI Avatar 2.0 Pro)",
|
||||
],
|
||||
@@ -2222,6 +2224,8 @@ function videoModelSearchFilterHandler(videoModelSearchNode) {
|
||||
"klingai:7@1": {"width": 0, "height": 0},
|
||||
"klingai:kling@o1": {"width": 1440, "height": 1440},
|
||||
"klingai:kling-video@2.6-pro": {"width": 1920, "height": 1080},
|
||||
"klingai:kling-video@3-pro": {"width": 1920, "height": 1080},
|
||||
"klingai:kling-video@3-standard": {"width": 1920, "height": 1080},
|
||||
"klingai:avatar@2.0-standard": {"width": 0, "height": 0},
|
||||
"klingai:avatar@2.0-pro": {"width": 0, "height": 0},
|
||||
"google:2@0": {"width": 1280, "height": 720},
|
||||
@@ -2297,6 +2301,8 @@ function videoModelSearchFilterHandler(videoModelSearchNode) {
|
||||
"klingai:7@1": null, // No resolution support
|
||||
"klingai:kling@o1": null, // No standard resolution
|
||||
"klingai:kling-video@2.6-pro": "1080p",
|
||||
"klingai:kling-video@3-pro": "1080p",
|
||||
"klingai:kling-video@3-standard": "1080p",
|
||||
"klingai:avatar@2.0-standard": null, // No resolution support
|
||||
"klingai:avatar@2.0-pro": null, // No resolution support
|
||||
"google:2@0": "720p",
|
||||
@@ -2616,6 +2622,7 @@ function klingProviderSettingsToggleHandler(klingNode) {
|
||||
const soundWidget = klingNode.widgets.find(w => w.name === "sound");
|
||||
const useCharacterOrientationWidget = klingNode.widgets.find(w => w.name === "useCharacterOrientation");
|
||||
const characterOrientationWidget = klingNode.widgets.find(w => w.name === "characterOrientation");
|
||||
const useMultipromptWidget = klingNode.widgets.find(w => w.name === "useMultiprompt");
|
||||
|
||||
// Helper function to toggle widget enabled state (EXACT same pattern as imageInferenceToggleHandler)
|
||||
// Callers guard with if (useX && xWidget) before invoking
|
||||
@@ -2698,6 +2705,25 @@ function klingProviderSettingsToggleHandler(klingNode) {
|
||||
if (useCharacterOrientationWidget && characterOrientationWidget) {
|
||||
toggleWidgetState(useCharacterOrientationWidget, characterOrientationWidget, "characterOrientation");
|
||||
}
|
||||
|
||||
// Toggle MultiPrompt Segment input slots when useMultiprompt changes
|
||||
if (useMultipromptWidget) {
|
||||
function toggleMultipromptInputs() {
|
||||
const enabled = useMultipromptWidget.value === true;
|
||||
klingNode.inputs?.forEach(inp => {
|
||||
if (inp?.name?.startsWith("MultiPrompt Segment")) {
|
||||
inp.disabled = !enabled;
|
||||
if (inp.domElement) {
|
||||
inp.domElement.style.opacity = enabled ? "1" : "0.4";
|
||||
inp.domElement.style.pointerEvents = enabled ? "auto" : "none";
|
||||
}
|
||||
}
|
||||
});
|
||||
klingNode.setDirtyCanvas(true);
|
||||
}
|
||||
appendWidgetCB(useMultipromptWidget, () => setTimeout(toggleMultipromptInputs, 50));
|
||||
setTimeout(toggleMultipromptInputs, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function alibabaProviderSettingsToggleHandler(alibabaNode) {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
Runware Kling MultiPrompt Segment Node
|
||||
Creates a single prompt/duration entry for Kling multiPrompt provider settings
|
||||
"""
|
||||
|
||||
from typing import Dict, Any
|
||||
|
||||
|
||||
class RunwareKlingMultiPromptSegment:
|
||||
"""Runware Kling MultiPrompt Segment Node"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"prompt": ("STRING", {
|
||||
"multiline": True,
|
||||
"default": "",
|
||||
"tooltip": "Prompt for this segment of the video",
|
||||
}),
|
||||
"duration": ("INT", {
|
||||
"default": 4,
|
||||
"min": 1,
|
||||
"max": 30,
|
||||
"step": 1,
|
||||
"tooltip": "Duration in seconds for this segment",
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("RUNWAREKLINGMULTIPROMPTSEGMENT",)
|
||||
RETURN_NAMES = ("MultiPrompt Segment",)
|
||||
FUNCTION = "createSegment"
|
||||
CATEGORY = "Runware/Provider Settings"
|
||||
DESCRIPTION = "Create a prompt/duration segment for Kling multiPrompt. Connect multiple segments to Runware Kling Provider Settings MultiPrompt."
|
||||
|
||||
def createSegment(self, prompt: str, duration: int) -> tuple[Dict[str, Any]]:
|
||||
return ({"prompt": prompt.strip(), "duration": int(duration)},)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareKlingMultiPromptSegment": RunwareKlingMultiPromptSegment,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareKlingMultiPromptSegment": "Runware Kling MultiPrompt Segment",
|
||||
}
|
||||
@@ -3,7 +3,7 @@ Runware KlingAI Provider Settings Node
|
||||
Provides KlingAI-specific settings for video generation
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any
|
||||
from typing import Optional, Dict, Any, List
|
||||
|
||||
|
||||
class RunwareKlingProviderSettings:
|
||||
@@ -98,6 +98,27 @@ class RunwareKlingProviderSettings:
|
||||
"tooltip": "Character orientation mode. 'image': has the same orientation as the person in the picture (reference video duration should not exceed 10 seconds). 'video': consistent with the orientation of the characters in the video (reference video duration should not exceed 30 seconds). Only used when 'Use Character Orientation' is enabled.",
|
||||
"default": "image",
|
||||
}),
|
||||
"useMultiprompt": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include multiPrompt in provider settings. When enabled, connect Runware Kling MultiPrompt Segment nodes.",
|
||||
"default": False,
|
||||
"label_on": "Enabled",
|
||||
"label_off": "Disabled",
|
||||
}),
|
||||
"MultiPrompt Segment 1": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment. Only used when 'Use Multiprompt' is enabled.",
|
||||
}),
|
||||
"MultiPrompt Segment 2": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment. Only used when 'Use Multiprompt' is enabled.",
|
||||
}),
|
||||
"MultiPrompt Segment 3": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment. Only used when 'Use Multiprompt' is enabled.",
|
||||
}),
|
||||
"MultiPrompt Segment 4": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment. Only used when 'Use Multiprompt' is enabled.",
|
||||
}),
|
||||
"MultiPrompt Segment 5": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment. Only used when 'Use Multiprompt' is enabled.",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +141,7 @@ class RunwareKlingProviderSettings:
|
||||
useKeepOriginalSound = kwargs.get("useKeepOriginalSound", False)
|
||||
useSound = kwargs.get("useSound", False)
|
||||
useCharacterOrientation = kwargs.get("useCharacterOrientation", False)
|
||||
useMultiprompt = kwargs.get("useMultiprompt", False)
|
||||
|
||||
# Get value parameters
|
||||
cameraControl = kwargs.get("cameraControl", "none")
|
||||
@@ -171,6 +193,21 @@ class RunwareKlingProviderSettings:
|
||||
if useCharacterOrientation and characterOrientation:
|
||||
klingSettings["characterOrientation"] = characterOrientation
|
||||
|
||||
# Add multiPrompt only if useMultiprompt is enabled
|
||||
if useMultiprompt:
|
||||
segments: List[Dict[str, Any]] = []
|
||||
for i in range(1, 6):
|
||||
segment = kwargs.get(f"MultiPrompt Segment {i}")
|
||||
if segment is not None and isinstance(segment, dict):
|
||||
prompt = segment.get("prompt", "").strip()
|
||||
if prompt:
|
||||
segments.append({
|
||||
"prompt": prompt,
|
||||
"duration": int(segment.get("duration", 4)),
|
||||
})
|
||||
if segments:
|
||||
klingSettings["multiPrompt"] = segments
|
||||
|
||||
# Clean up None values
|
||||
klingSettings = {k: v for k, v in klingSettings.items() if v is not None}
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
"""
|
||||
Runware Kling Provider Settings MultiPrompt Node
|
||||
Adds multiPrompt to Kling provider settings. Connects to Runware Kling Provider Settings
|
||||
and outputs merged provider settings for Video Inference.
|
||||
"""
|
||||
|
||||
from typing import Dict, Any, List
|
||||
|
||||
|
||||
class RunwareKlingProviderSettingsMultiPrompt:
|
||||
"""Runware Kling Provider Settings MultiPrompt Node"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"providerSettings": ("RUNWAREPROVIDERSETTINGS", {
|
||||
"tooltip": "Connect Runware KlingAI Provider Settings to merge with multiPrompt",
|
||||
}),
|
||||
},
|
||||
"optional": {
|
||||
"MultiPrompt Segment 1": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment",
|
||||
}),
|
||||
"MultiPrompt Segment 2": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment",
|
||||
}),
|
||||
"MultiPrompt Segment 3": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment",
|
||||
}),
|
||||
"MultiPrompt Segment 4": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment",
|
||||
}),
|
||||
"MultiPrompt Segment 5": ("RUNWAREKLINGMULTIPROMPTSEGMENT", {
|
||||
"tooltip": "Connect a Runware Kling MultiPrompt Segment",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("RUNWAREPROVIDERSETTINGS",)
|
||||
RETURN_NAMES = ("Provider Settings",)
|
||||
FUNCTION = "mergeProviderSettings"
|
||||
CATEGORY = "Runware/Provider Settings"
|
||||
DESCRIPTION = "Add multiPrompt to Kling provider settings. Connect Runware KlingAI Provider Settings and one or more Runware Kling MultiPrompt Segment nodes. Output connects to Runware Video Inference."
|
||||
|
||||
def mergeProviderSettings(self, **kwargs) -> tuple[Dict[str, Any]]:
|
||||
"""Merge Kling provider settings with multiPrompt segments"""
|
||||
|
||||
provider_settings = kwargs.get("providerSettings")
|
||||
segments: List[Dict[str, Any]] = []
|
||||
|
||||
for i in range(1, 6):
|
||||
segment = kwargs.get(f"MultiPrompt Segment {i}")
|
||||
if segment is not None and isinstance(segment, dict):
|
||||
prompt = segment.get("prompt", "").strip()
|
||||
if prompt:
|
||||
segments.append({
|
||||
"prompt": prompt,
|
||||
"duration": int(segment.get("duration", 4)),
|
||||
})
|
||||
|
||||
# Start with existing provider settings or empty dict
|
||||
if isinstance(provider_settings, dict):
|
||||
# May be flat (from Kling) or wrapped {"klingai": {...}}
|
||||
if "klingai" in provider_settings:
|
||||
kling_settings = dict(provider_settings["klingai"])
|
||||
else:
|
||||
kling_settings = dict(provider_settings)
|
||||
else:
|
||||
kling_settings = {}
|
||||
|
||||
if segments:
|
||||
kling_settings["multiPrompt"] = segments
|
||||
|
||||
if not kling_settings:
|
||||
return ({},)
|
||||
|
||||
# Output format expected by video inference: wrap with klingai if flat
|
||||
return ({"klingai": kling_settings},)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareKlingProviderSettingsMultiPrompt": RunwareKlingProviderSettingsMultiPrompt,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareKlingProviderSettingsMultiPrompt": "Runware Kling Provider Settings MultiPrompt",
|
||||
}
|
||||
@@ -18,6 +18,8 @@ class videoModelSearch:
|
||||
"klingai:7@1 (KlingAI Lip-Sync)",
|
||||
"klingai:kling@o1 (Kling VIDEO O1)",
|
||||
"klingai:kling-video@2.6-pro (Kling VIDEO 2.6 Pro)",
|
||||
"klingai:kling-video@3-pro (Kling VIDEO 3.0 Pro)",
|
||||
"klingai:kling-video@3-standard (Kling VIDEO 3.0 Standard)",
|
||||
],
|
||||
"Veo": [
|
||||
"google:2@0 (Veo 2.0)",
|
||||
@@ -132,6 +134,8 @@ class videoModelSearch:
|
||||
"klingai:7@1": {"width": 0, "height": 0},
|
||||
"klingai:kling@o1": {"width": 1440, "height": 1440},
|
||||
"klingai:kling-video@2.6-pro": {"width": 1920, "height": 1080},
|
||||
"klingai:kling-video@3-pro": {"width": 1920, "height": 1080},
|
||||
"klingai:kling-video@3-standard": {"width": 1920, "height": 1080},
|
||||
|
||||
# Veo Models
|
||||
"google:2@0": {"width": 1280, "height": 720},
|
||||
@@ -245,6 +249,8 @@ class videoModelSearch:
|
||||
"klingai:7@1": None, # No resolution support
|
||||
"klingai:kling@o1": None, # No standard resolution (1440x1440)
|
||||
"klingai:kling-video@2.6-pro": "1080p",
|
||||
"klingai:kling-video@3-pro": "1080p",
|
||||
"klingai:kling-video@3-standard": "1080p",
|
||||
|
||||
# Veo Models
|
||||
"google:2@0": "720p",
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user