feat: Convert boolean toggles and fix provider settings
- Convert useSteps, useCFGScale, useScheduler, useSeed to BOOLEAN in ImageInference - Convert useFps to BOOLEAN in VideoInference - Reorder parameters so 'use' toggles appear above their corresponding parameters - Fix VideoInference providerSettings input type from DICT to RUNWAREPROVIDERSETTINGS - Update provider settings handling logic to match ImageInference format - Improve UX with native boolean toggles and logical parameter ordering
This commit is contained in:
+25
-13
@@ -51,20 +51,28 @@ class txt2img:
|
||||
"max": 2048,
|
||||
"step": 64,
|
||||
}),
|
||||
"useSteps": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include steps parameter in API request. Disable if your model doesn't support steps (like nano banana).",
|
||||
"default": True,
|
||||
}),
|
||||
"steps": ("INT", {
|
||||
"tooltip": "The number of steps is the number of iterations the model will perform to generate the image. Only used when 'Use Steps' is enabled.",
|
||||
"default": 4,
|
||||
"min": 1,
|
||||
"max": 100,
|
||||
}),
|
||||
"useSteps": (["enable", "disabled"], {
|
||||
"tooltip": "Enable to include steps parameter in API request. Disable if your model doesn't support steps (like nano banana).",
|
||||
"default": "enable",
|
||||
"useScheduler": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include scheduler parameter in API request. Disable if your model doesn't support scheduler.",
|
||||
"default": True,
|
||||
}),
|
||||
"scheduler": (['Default', 'DDIM', 'DDIMScheduler', 'DDPMScheduler', 'DEISMultistepScheduler', 'DPMSolverSinglestepScheduler', 'DPMSolverMultistepScheduler', 'DPMSolverMultistepInverse', 'DPM++', 'DPM++ Karras', 'DPM++ 2M', 'DPM++ 2M Karras', 'DPM++ 2M SDE Karras', 'DPM++ 2M SDE', 'DPM++ 3M', 'DPM++ 3M Karras', 'DPM++ SDE Karras', 'DPM++ SDE', 'EDMEulerScheduler', 'EDMDPMSolverMultistepScheduler', 'Euler', 'EulerDiscreteScheduler', 'Euler Karras', 'Euler a', 'EulerAncestralDiscreteScheduler', 'FlowMatchEulerDiscreteScheduler', 'Heun', 'HeunDiscreteScheduler', 'Heun Karras', 'IPNDMScheduler', 'KDPM2DiscreteScheduler', 'KDPM2AncestralDiscreteScheduler', 'LCM', 'LCMScheduler', 'LMS', 'LMSDiscreteScheduler', 'LMS Karras', 'PNDMScheduler', 'TCDScheduler', 'UniPC', 'UniPCMultistepScheduler', 'UniPC Karras', 'UniPC 2M', 'UniPC 2M Karras', 'UniPC 3M', 'UniPC 3M Karras'], {
|
||||
"tooltip": "An scheduler is a component that manages the inference process. Different schedulers can be used to achieve different results like more detailed images, faster inference, or more accurate results.",
|
||||
"default": "Default",
|
||||
}),
|
||||
"useCFGScale": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include CFG scale parameter in API request. Disable if your model doesn't support CFG scale (like nano banana).",
|
||||
"default": True,
|
||||
}),
|
||||
"cfgScale": ("FLOAT", {
|
||||
"tooltip": "Guidance scale represents how closely the images will resemble the prompt or how much freedom the AI model has. Only used when 'Use CFG Scale' is enabled.",
|
||||
"default": 6.5,
|
||||
@@ -72,9 +80,9 @@ class txt2img:
|
||||
"max": 50.0,
|
||||
"step": 0.5,
|
||||
}),
|
||||
"useCFGScale": (["enable", "disabled"], {
|
||||
"tooltip": "Enable to include CFG scale parameter in API request. Disable if your model doesn't support CFG scale (like nano banana).",
|
||||
"default": "enable",
|
||||
"useSeed": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include seed parameter in API request. Disable if your model doesn't support seed.",
|
||||
"default": True,
|
||||
}),
|
||||
"seed": ("INT", {
|
||||
"tooltip": "A value used to randomize the image generation. If you want to make images reproducible (generate the same image multiple times), you can use the same seed value.",
|
||||
@@ -187,11 +195,13 @@ class txt2img:
|
||||
height = kwargs.get("height", 512)
|
||||
width = kwargs.get("width", 512)
|
||||
steps = kwargs.get("steps", 4)
|
||||
useSteps = kwargs.get("useSteps", "enable")
|
||||
useSteps = kwargs.get("useSteps", True)
|
||||
scheduler = kwargs.get("scheduler", "Default")
|
||||
useScheduler = kwargs.get("useScheduler", True)
|
||||
cfgScale = kwargs.get("cfgScale", 6.5)
|
||||
useCFGScale = kwargs.get("useCFGScale", "enable")
|
||||
useCFGScale = kwargs.get("useCFGScale", True)
|
||||
seed = kwargs.get("seed")
|
||||
useSeed = kwargs.get("useSeed", True)
|
||||
batchSize = kwargs.get("batchSize", 1)
|
||||
|
||||
if (maskImage is not None and seedImage is None):
|
||||
@@ -205,9 +215,7 @@ class txt2img:
|
||||
"height": height,
|
||||
"width": width,
|
||||
"model": runwareModel,
|
||||
"scheduler": scheduler,
|
||||
"clipSkip": clipSkip,
|
||||
"seed": seed,
|
||||
"outputType": "base64Data",
|
||||
"outputFormat": rwUtils.OUTPUT_FORMAT,
|
||||
"outputQuality": rwUtils.OUTPUT_QUALITY,
|
||||
@@ -218,11 +226,15 @@ class txt2img:
|
||||
# For Debugging Purposes Only
|
||||
print(f"[Debugging] Task UUID: {genConfig[0]['taskUUID']}")
|
||||
|
||||
# Add steps and CFGScale only if enabled
|
||||
if useSteps == "enable":
|
||||
# Add steps, CFGScale, seed, and scheduler only if enabled
|
||||
if useSteps:
|
||||
genConfig[0]["steps"] = steps
|
||||
if useCFGScale == "enable":
|
||||
if useCFGScale:
|
||||
genConfig[0]["CFGScale"] = cfgScale
|
||||
if useSeed:
|
||||
genConfig[0]["seed"] = seed
|
||||
if useScheduler:
|
||||
genConfig[0]["scheduler"] = scheduler
|
||||
|
||||
if (negativePrompt is not None and negativePrompt != ""):
|
||||
genConfig[0]["negativePrompt"] = negativePrompt
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
from .utils import runwareUtils as rwUtils
|
||||
|
||||
|
||||
class RunwareOpenAIProviderSettings:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"quality": (["auto", "high", "medium", "low"], {
|
||||
"default": "auto",
|
||||
"tooltip": "Quality setting for OpenAI DALL-E models.",
|
||||
}),
|
||||
"useBackground": (["enable", "disabled"], {
|
||||
"default": "disabled",
|
||||
"tooltip": "Enable to include background parameter in API request.",
|
||||
}),
|
||||
"background": (["transparent", "opaque"], {
|
||||
"default": "opaque",
|
||||
"tooltip": "Background setting for OpenAI image generation. Only used when 'Use Background' is enabled.",
|
||||
}),
|
||||
"useStyle": (["enable", "disabled"], {
|
||||
"default": "disabled",
|
||||
"tooltip": "Enable to include style parameter in API request.",
|
||||
}),
|
||||
"style": (["vivid", "natural"], {
|
||||
"default": "vivid",
|
||||
"tooltip": "Style setting for OpenAI DALL-E models. Only used when 'Use Style' is enabled.",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
DESCRIPTION = "Configure OpenAI-specific settings for image generation with quality, background, and style options."
|
||||
FUNCTION = "create_openai_settings"
|
||||
RETURN_TYPES = ("RUNWAREPROVIDERSETTINGS",)
|
||||
RETURN_NAMES = ("Provider Settings",)
|
||||
CATEGORY = "Runware"
|
||||
|
||||
def create_openai_settings(self, **kwargs):
|
||||
quality = kwargs.get("quality", "auto")
|
||||
useBackground = kwargs.get("useBackground", "disabled")
|
||||
background = kwargs.get("background", "opaque")
|
||||
useStyle = kwargs.get("useStyle", "disabled")
|
||||
style = kwargs.get("style", "vivid")
|
||||
|
||||
# Create OpenAI settings dictionary
|
||||
openai_settings = {
|
||||
"quality": quality,
|
||||
}
|
||||
|
||||
# Add background only if enabled
|
||||
if useBackground == "enable":
|
||||
openai_settings["background"] = background
|
||||
|
||||
# Add style only if enabled
|
||||
if useStyle == "enable":
|
||||
openai_settings["style"] = style
|
||||
|
||||
print(f"[OpenAI Provider Settings] Created settings: {openai_settings}")
|
||||
return (openai_settings,)
|
||||
|
||||
|
||||
# Node class mappings for ComfyUI registration
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareOpenAIProviderSettings": RunwareOpenAIProviderSettings,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareOpenAIProviderSettings": "Runware OpenAI Provider Settings",
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
from .utils import runwareUtils as rwUtils
|
||||
|
||||
|
||||
class RunwarePixverseProviderSettings:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"effect": (["none", "boom drop", "zoom in", "zoom out", "pan left", "pan right", "tilt up", "tilt down"], {
|
||||
"default": "none",
|
||||
"tooltip": "Camera effect for Pixverse videos.",
|
||||
}),
|
||||
"cameraMovement": (["none", "static", "dynamic", "smooth"], {
|
||||
"default": "none",
|
||||
"tooltip": "Camera movement style for Pixverse videos.",
|
||||
}),
|
||||
"style": (["anime", "realistic", "cinematic", "artistic", "vintage", "modern"], {
|
||||
"default": "realistic",
|
||||
"tooltip": "Visual style for Pixverse videos.",
|
||||
}),
|
||||
"motionMode": (["normal", "slow", "fast", "smooth", "dynamic"], {
|
||||
"default": "normal",
|
||||
"tooltip": "Motion mode for Pixverse videos.",
|
||||
}),
|
||||
"soundEffectSwitch": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": "Enable or disable sound effects for Pixverse videos.",
|
||||
"label_on": "Enabled",
|
||||
"label_off": "Disabled",
|
||||
}),
|
||||
"soundEffectContent": ("STRING", {
|
||||
"multiline": True,
|
||||
"placeholder": "Sound effect description or content",
|
||||
"tooltip": "Sound effect content for Pixverse videos.",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
DESCRIPTION = "Configure Pixverse-specific settings for video generation with effect, style, motion, and sound options."
|
||||
FUNCTION = "create_pixverse_settings"
|
||||
RETURN_TYPES = ("RUNWAREPROVIDERSETTINGS",)
|
||||
RETURN_NAMES = ("Provider Settings",)
|
||||
CATEGORY = "Runware"
|
||||
|
||||
def create_pixverse_settings(self, **kwargs):
|
||||
effect = kwargs.get("effect", "none")
|
||||
cameraMovement = kwargs.get("cameraMovement", "none")
|
||||
style = kwargs.get("style", "realistic")
|
||||
motionMode = kwargs.get("motionMode", "normal")
|
||||
soundEffectSwitch = kwargs.get("soundEffectSwitch", False)
|
||||
soundEffectContent = kwargs.get("soundEffectContent", "")
|
||||
|
||||
# Create Pixverse settings dictionary
|
||||
pixverse_settings = {
|
||||
"effect": effect,
|
||||
"cameraMovement": cameraMovement,
|
||||
"style": style,
|
||||
"motionMode": motionMode,
|
||||
"soundEffectSwitch": soundEffectSwitch,
|
||||
}
|
||||
|
||||
# Only add soundEffectContent if it's not empty
|
||||
if soundEffectContent and soundEffectContent.strip():
|
||||
pixverse_settings["soundEffectContent"] = soundEffectContent
|
||||
|
||||
# Remove "none" values to keep the settings clean
|
||||
pixverse_settings = {k: v for k, v in pixverse_settings.items() if v != "none" and v is not None}
|
||||
|
||||
print(f"[Pixverse Provider Settings] Created settings: {pixverse_settings}")
|
||||
return (pixverse_settings,)
|
||||
|
||||
|
||||
# Node class mappings for ComfyUI registration
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwarePixverseProviderSettings": RunwarePixverseProviderSettings,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwarePixverseProviderSettings": "Runware Pixverse Provider Settings",
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
from .utils import runwareUtils as rwUtils
|
||||
|
||||
|
||||
class RunwareProviderSettings:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"customSettings": ("DICT", {
|
||||
"tooltip": "Custom provider settings as a dictionary. Add any provider-specific parameters here.",
|
||||
"default": {},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
DESCRIPTION = "Configure custom provider-specific settings for video and image generation. Add any provider parameters as a dictionary."
|
||||
FUNCTION = "create_provider_settings"
|
||||
RETURN_TYPES = ("RUNWAREPROVIDERSETTINGS",)
|
||||
RETURN_NAMES = ("Provider Settings",)
|
||||
CATEGORY = "Runware"
|
||||
|
||||
def create_provider_settings(self, **kwargs):
|
||||
custom_settings = kwargs.get("customSettings", {})
|
||||
|
||||
print(f"[Provider Settings] Custom settings: {custom_settings}")
|
||||
return (custom_settings,)
|
||||
|
||||
|
||||
# Node class mappings for ComfyUI registration
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareProviderSettings": RunwareProviderSettings,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareProviderSettings": "Runware Provider Settings",
|
||||
}
|
||||
@@ -480,7 +480,7 @@ class VideoObject:
|
||||
def save_to(self, filename, **kwargs):
|
||||
"""Save video to file by downloading from URL with retry logic"""
|
||||
max_retries = 10
|
||||
retry_delays = [2, 5, 10, 15, 20] # Longer delays for video server issues
|
||||
retry_delays = [2, 5, 10, 15, 20] # Longer delays for retries with larger videos
|
||||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
|
||||
+24
-10
@@ -128,16 +128,16 @@ class txt2vid:
|
||||
"min": 1,
|
||||
"max": 30,
|
||||
}),
|
||||
"useFps": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include fps parameter in API request. Disable if your model doesn't support fps.",
|
||||
"default": True,
|
||||
}),
|
||||
"fps": ("INT", {
|
||||
"tooltip": "Frames per second for the generated video. Only used when 'Use FPS' is enabled.",
|
||||
"default": 24,
|
||||
"min": 8,
|
||||
"max": 60,
|
||||
}),
|
||||
"useFps": (["enable", "disabled"], {
|
||||
"tooltip": "Enable to include fps parameter in API request. Disable if your model doesn't support fps.",
|
||||
"default": "enable",
|
||||
}),
|
||||
"outputFormat": (["mp4", "webm", "mov"], {
|
||||
"default": "mp4",
|
||||
"tooltip": "Choose the output video format.",
|
||||
@@ -162,8 +162,8 @@ class txt2vid:
|
||||
"referenceImages": ("RUNWAREREFERENCEIMAGES", {
|
||||
"tooltip": "Connect a Runware Reference Images node to provide reference images for the subject. These reference images help the AI maintain identity consistency during the video generation process.",
|
||||
}),
|
||||
"providerSettings": ("DICT", {
|
||||
"tooltip": "Provider-specific settings for video generation.",
|
||||
"providerSettings": ("RUNWAREPROVIDERSETTINGS", {
|
||||
"tooltip": "Connect a Runware Provider Settings node to configure provider-specific parameters.",
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -198,7 +198,7 @@ class txt2vid:
|
||||
customHeight = kwargs.get("height", 480)
|
||||
duration = kwargs.get("duration", 5)
|
||||
fps = kwargs.get("fps", 24)
|
||||
useFps = kwargs.get("useFps", "enable")
|
||||
useFps = kwargs.get("useFps", True)
|
||||
outputFormat = kwargs.get("outputFormat", "mp4")
|
||||
batchSize = kwargs.get("batchSize", 1)
|
||||
seed = kwargs.get("seed", 1)
|
||||
@@ -235,7 +235,7 @@ class txt2vid:
|
||||
]
|
||||
|
||||
# Add fps parameter only if enabled
|
||||
if useFps == "enable":
|
||||
if useFps:
|
||||
genConfig[0]["fps"] = fps
|
||||
|
||||
# Add duration parameter - unified for all models
|
||||
@@ -261,8 +261,22 @@ class txt2vid:
|
||||
if referenceImages is not None and len(referenceImages) > 0:
|
||||
genConfig[0]["referenceImages"] = referenceImages
|
||||
print(f"[Debugging] Reference images array: {referenceImages}")
|
||||
if (providerSettings is not None):
|
||||
genConfig[0]["providerSettings"] = providerSettings
|
||||
# Handle providerSettings - extract provider name from model and merge with custom settings
|
||||
if providerSettings is not None:
|
||||
# Extract provider name from model (e.g., "pixverse:1@1" -> "pixverse")
|
||||
provider_name = model.split(":")[0] if ":" in model else model
|
||||
|
||||
# If providerSettings is a dictionary, create the correct API format
|
||||
if isinstance(providerSettings, dict):
|
||||
# Create the providerSettings object with provider name as key
|
||||
final_provider_settings = {
|
||||
provider_name: providerSettings
|
||||
}
|
||||
genConfig[0]["providerSettings"] = final_provider_settings
|
||||
print(f"[Debugging] Provider settings: {final_provider_settings}")
|
||||
else:
|
||||
# If it's just a string, use it directly
|
||||
genConfig[0]["providerSettings"] = providerSettings
|
||||
|
||||
if (multiInferenceMode):
|
||||
return (None, genConfig)
|
||||
|
||||
Reference in New Issue
Block a user