From 8a1ff27e43e4e73ea0793d17df2b70a1773f413b Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Wed, 12 Nov 2025 15:49:34 -0500 Subject: [PATCH] add support for midjourney provider settings --- __init__.py | 2 + clientlibs/main.js | 4 +- clientlibs/types.js | 5 + clientlibs/utils.js | 23 ++++ .../midjourneyProviderSettings.py | 120 ++++++++++++++++++ modules/utils/runwareUtils.py | 2 +- modules/videoUpscaler.py | 50 +++++--- 7 files changed, 185 insertions(+), 21 deletions(-) create mode 100644 modules/providerSettings/midjourneyProviderSettings.py diff --git a/__init__.py b/__init__.py index 192cec1..531b990 100644 --- a/__init__.py +++ b/__init__.py @@ -49,6 +49,7 @@ from .modules.providerSettings.minimaxProviderSettings import RunwareMiniMaxProv from .modules.providerSettings.klingProviderSettings import RunwareKlingProviderSettings from .modules.providerSettings.runwayProviderSettings import RunwareRunwayProviderSettings from .modules.providerSettings.lumaProviderSettings import RunwareLumaProviderSettings +from .modules.providerSettings.midjourneyProviderSettings import RunwareMidjourneyProviderSettings from .modules.vectorize import vectorize from .modules.videoBgRemoval import videoBgRemoval from .modules.videoUpscaler import videoUpscaler @@ -119,6 +120,7 @@ NODE_CLASS_MAPPINGS = { "Runware Luma Provider Settings": RunwareLumaProviderSettings, "Runware KlingAI Provider Settings": RunwareKlingProviderSettings, "Runware Runway Provider Settings": RunwareRunwayProviderSettings, + "Runware Midjourney Provider Settings": RunwareMidjourneyProviderSettings, "Runware Vectorize": vectorize, "Runware Video Background Removal": videoBgRemoval, "Runware Video Upscaler": videoUpscaler, diff --git a/clientlibs/main.js b/clientlibs/main.js index a7cfa05..1d68aef 100644 --- a/clientlibs/main.js +++ b/clientlibs/main.js @@ -1,6 +1,6 @@ import { app } from "../../scripts/app.js"; import { api } from "../../scripts/api.js"; -import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, mediaUUIDHandler, videoTranscriptionHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler } from "./utils.js"; +import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, mediaUUIDHandler, videoTranscriptionHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler } from "./utils.js"; import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js"; const nodeInitList = []; @@ -51,6 +51,8 @@ app.registerExtension({ videoInferenceDimensionsHandler(node); } else if(nodeClass === RUNWARE_NODE_TYPES.UPSCALER) { upscalerToggleHandler(node); + } else if(nodeClass === RUNWARE_NODE_TYPES.VIDEOUPSCALER) { + videoUpscalerToggleHandler(node); } else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOINFERENCE) { audioInferenceToggleHandler(node); } else if(nodeClass === RUNWARE_NODE_TYPES.ACCELERATOROPTIONS) { diff --git a/clientlibs/types.js b/clientlibs/types.js index ef7bc0d..1561993 100644 --- a/clientlibs/types.js +++ b/clientlibs/types.js @@ -98,6 +98,7 @@ const RUNWARE_NODE_TYPES = { KLINGPROVIDERSETTINGS: "Runware KlingAI Provider Settings", RUNWAYPROVIDERSETTINGS: "Runware Runway Provider Settings", LUMAPROVIDERSETTINGS: "Runware Luma Provider Settings", + MIDJOURNEYPROVIDERSETTINGS: "Runware Midjourney Provider Settings", VECTORIZE: "Runware Vectorize", VIDEOBGREMOVAL: "Runware Video Background Removal", VIDEOUPSCALER: "Runware Video Upscaler", @@ -314,6 +315,10 @@ const RUNWARE_NODE_PROPS = { bgColor: DEFAULT_BGCOLOR, colorModeOnly: true, }, + [RUNWARE_NODE_TYPES.MIDJOURNEYPROVIDERSETTINGS]: { + bgColor: DEFAULT_BGCOLOR, + colorModeOnly: true, + }, [RUNWARE_NODE_TYPES.VECTORIZE]: { bgColor: DEFAULT_BGCOLOR, }, diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 93e34c4..771746e 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -657,6 +657,28 @@ function toggleWidgetEnabled(widget, enabled, node) { } } +function videoUpscalerToggleHandler(videoUpscalerNode) { + if (!videoUpscalerNode?.widgets) return; + + const useUpscaleFactorWidget = videoUpscalerNode.widgets.find(w => w && w.name === "useUpscaleFactor"); + const upscaleFactorWidget = videoUpscalerNode.widgets.find(w => w && w.name === "upscaleFactor"); + + if (!useUpscaleFactorWidget || !upscaleFactorWidget) return; + + function applyToggleState() { + const enabled = useUpscaleFactorWidget.value === true; + toggleWidgetEnabled(upscaleFactorWidget, enabled, videoUpscalerNode); + videoUpscalerNode.setDirtyCanvas(true); + } + + // Initialize state once widgets are rendered + setTimeout(applyToggleState, 100); + + appendWidgetCB(useUpscaleFactorWidget, () => { + setTimeout(applyToggleState, 50); + }); +} + function useParameterToggleHandler(node) { // Prevent double registration if (node._useParameterToggleHandlerRegistered) return; @@ -1947,6 +1969,7 @@ export { useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, + videoUpscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, diff --git a/modules/providerSettings/midjourneyProviderSettings.py b/modules/providerSettings/midjourneyProviderSettings.py new file mode 100644 index 0000000..1aefb68 --- /dev/null +++ b/modules/providerSettings/midjourneyProviderSettings.py @@ -0,0 +1,120 @@ +""" +Runware Midjourney Provider Settings Node +Provides Midjourney-specific settings for image generation workflows. +""" + +from typing import Any, Dict, Optional, Tuple + + +class RunwareMidjourneyProviderSettings: + """Runware Midjourney Provider Settings Node""" + + QUALITY_STEP = 0.25 + QUALITY_MIN = 0.25 + QUALITY_MAX = 2.0 + DEFAULT_QUALITY = 1.0 + + DEFAULT_STYLIZE = 0 + STYLIZE_MIN = 0 + STYLIZE_MAX = 1000 + + DEFAULT_CHAOS = 0 + CHAOS_MIN = 0 + CHAOS_MAX = 100 + + DEFAULT_WEIRD = 0 + WEIRD_MIN = 0 + WEIRD_MAX = 3000 + + NIJI_OPTIONS = [ + "", # Allow provider default when omitted + "close", + "0", + "5", + "6", + ] + + @classmethod + def INPUT_TYPES(cls): + return { + "required": {}, + "optional": { + "quality": ("FLOAT", { + "tooltip": "Midjourney quality multiplier (provider key: providerSettings.midjourney.quality).", + "default": cls.DEFAULT_QUALITY, + "min": cls.QUALITY_MIN, + "max": cls.QUALITY_MAX, + "step": cls.QUALITY_STEP, + }), + "stylize": ("INT", { + "tooltip": "Controls how strongly Midjourney's artistic style is applied (provider key: providerSettings.midjourney.stylize).", + "default": cls.DEFAULT_STYLIZE, + "min": cls.STYLIZE_MIN, + "max": cls.STYLIZE_MAX, + }), + "chaos": ("INT", { + "tooltip": "Controls variation and unpredictability (provider key: providerSettings.midjourney.chaos).", + "default": cls.DEFAULT_CHAOS, + "min": cls.CHAOS_MIN, + "max": cls.CHAOS_MAX, + }), + "weird": ("INT", { + "tooltip": "Adds surreal, experimental characteristics (provider key: providerSettings.midjourney.weird).", + "default": cls.DEFAULT_WEIRD, + "min": cls.WEIRD_MIN, + "max": cls.WEIRD_MAX, + }), + "niji": (cls.NIJI_OPTIONS, { + "tooltip": "Select the Midjourney anime-focused rendering engine (provider key: providerSettings.midjourney.niji).", + "default": "close", + }), + } + } + + RETURN_TYPES = ("RUNWAREPROVIDERSETTINGS",) + RETURN_NAMES = ("Provider Settings",) + FUNCTION = "create_provider_settings" + CATEGORY = "Runware/Provider Settings" + DESCRIPTION = "Configure Midjourney-specific provider settings such as quality, stylize, chaos, weird, and niji options for image generation." + + def create_provider_settings(self, **kwargs) -> Tuple[Optional[Dict[str, Any]],]: + """Build Midjourney provider settings payload.""" + + quality = kwargs.get("quality", self.DEFAULT_QUALITY) + stylize = kwargs.get("stylize", self.DEFAULT_STYLIZE) + chaos = kwargs.get("chaos", self.DEFAULT_CHAOS) + weird = kwargs.get("weird", self.DEFAULT_WEIRD) + niji = kwargs.get("niji", "close") + + settings: Dict[str, Any] = {} + + if quality is not None: + settings["quality"] = float(quality) + + if stylize is not None: + settings["stylize"] = int(stylize) + + if chaos is not None: + settings["chaos"] = int(chaos) + + if weird is not None: + settings["weird"] = int(weird) + + if isinstance(niji, str) and niji.strip(): + settings["niji"] = niji.strip() + + # Clean None values so the inference request only includes populated options. + settings = {k: v for k, v in settings.items() if v is not None} + + return (settings if settings else None,) + + +NODE_CLASS_MAPPINGS = { + "RunwareMidjourneyProviderSettings": RunwareMidjourneyProviderSettings, +} + + +NODE_DISPLAY_NAME_MAPPINGS = { + "RunwareMidjourneyProviderSettings": "Runware Midjourney Provider Settings", +} + diff --git a/modules/utils/runwareUtils.py b/modules/utils/runwareUtils.py index 8c2a4d5..76b392b 100644 --- a/modules/utils/runwareUtils.py +++ b/modules/utils/runwareUtils.py @@ -158,7 +158,7 @@ def getCustomEndpoint(): custom_endpoint = os.getenv("RUNWARE_CUSTOM_ENDPOINT") if custom_endpoint and isinstance(custom_endpoint, str): return custom_endpoint - return "https://api.runware.ai/v1" + return "https://api.runware.dev/v1" SESSION_TIMEOUT = getTimeout() RUNWARE_API_KEY = getAPIKey() diff --git a/modules/videoUpscaler.py b/modules/videoUpscaler.py index c3acf17..4380801 100644 --- a/modules/videoUpscaler.py +++ b/modules/videoUpscaler.py @@ -14,16 +14,22 @@ class videoUpscaler: "Video": ("STRING", { "tooltip": "MediaUUID from Runware Media Upload node for the video to upscale." }), - "upscaleFactor": ([2, 4], { - "tooltip": "Integer scale factor for upscaling (2x or 4x).", - "default": 2, - }), "Model": (list(cls.RUNWARE_VUPSCALER_MODELS.keys()), { "tooltip": "Select the video upscaler model to use.", "default": "Bria Video Upscaler", }), + "useUpscaleFactor": ("BOOLEAN", { + "label_on": "Yes", + "label_off": "No", + "tooltip": "Enable to explicitly set the upscale factor for the request.", + "default": False, + }), }, "optional": { + "upscaleFactor": ([2, 4], { + "tooltip": "Integer scale factor for upscaling (2x or 4x).", + "default": 2, + }), "Output Format": (["mp4", "webm"], { "default": "mp4", "tooltip": "Choose the output video format.", @@ -39,7 +45,8 @@ class videoUpscaler: def upscale(self, **kwargs): video_uuid = kwargs.get("Video") - upscaleFactor = kwargs.get("upscaleFactor", 2) + useUpscaleFactor = kwargs.get("useUpscaleFactor", False) + upscaleFactor = kwargs.get("upscaleFactor") modelName = kwargs.get("Model", "Bria Video Upscaler") outputFormat = kwargs.get("Output Format", "mp4") @@ -51,20 +58,25 @@ class videoUpscaler: modelAIR = self.RUNWARE_VUPSCALER_MODELS.get(modelName, "bria:50@1") # Build the API request - genConfig = [ - { - "taskType": "upscale", - "taskUUID": rwUtils.genRandUUID(), - "upscaleFactor": upscaleFactor, - "inputs": { - "video": video_uuid - }, - "outputType": "URL", - "outputFormat": outputFormat.upper(), - "model": modelAIR, - "includeCost": True - } - ] + task_payload = { + "taskType": "upscale", + "taskUUID": rwUtils.genRandUUID(), + "inputs": { + "video": video_uuid + }, + "outputType": "URL", + "outputFormat": outputFormat.upper(), + "model": modelAIR, + "includeCost": True + } + + if useUpscaleFactor: + if upscaleFactor in (2, 4): + task_payload["upscaleFactor"] = upscaleFactor + else: + raise ValueError("upscaleFactor must be 2 or 4 when useUpscaleFactor is enabled.") + + genConfig = [task_payload] try: # Debug: Print the request being sent