Added support for multiple images as RefImages
This commit is contained in:
@@ -98,6 +98,7 @@ from .modules.vectorize import vectorize
|
||||
from .modules.videoBgRemoval import videoBgRemoval
|
||||
from .modules.videoUpscaler import videoUpscaler
|
||||
from .modules.videoInputsReferences import videoInputsReferences
|
||||
from .modules.videoInputsReferenceImagesMultipleImagesConnector import RunwareVideoInputsReferenceImagesMultipleImagesConnector
|
||||
from .modules.videoInputsFrame import RunwareVideoInputsFrameImages
|
||||
from .modules.safetyInputs import safetyInputs
|
||||
from .modules.settings import RunwareSettings
|
||||
@@ -229,6 +230,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"Runware Video Background Removal": videoBgRemoval,
|
||||
"Runware Video Upscaler": videoUpscaler,
|
||||
"Runware Video Inference Inputs Reference Images": videoInputsReferences,
|
||||
"Runware Video Inference Inputs Reference Images Multiple Images Connector": RunwareVideoInputsReferenceImagesMultipleImagesConnector,
|
||||
"Runware Video Inputs Frame Images": RunwareVideoInputsFrameImages,
|
||||
"Runware Safety Inputs": safetyInputs,
|
||||
"Runware Settings": RunwareSettings,
|
||||
@@ -268,6 +270,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"Runware Video Inference Inputs Reference Videos": "Runware Video Inference Inputs Reference Videos",
|
||||
"Runware Reference Audios": "Runware Video Inference Inputs Reference Audios",
|
||||
"Runware Video Inference Inputs Reference Audios": "Runware Video Inference Inputs Reference Audios",
|
||||
"Runware Video Inference Inputs Reference Images Multiple Images Connector": "Runware Video Inference Inputs Reference Images Multiple Images Connector",
|
||||
}
|
||||
|
||||
WEB_DIRECTORY = "./clientlibs"
|
||||
|
||||
@@ -112,6 +112,7 @@ const RUNWARE_NODE_TYPES = {
|
||||
REFERENCEVOICES_LEGACY: "Runware Reference Voices",
|
||||
REFERENCEAUDIOS: "Runware Video Inference Inputs Reference Audios",
|
||||
VIDEOINPUTSREFERENCES_LEGACY: "Runware Video Inputs References",
|
||||
VIDEOINPUTSREFERENCEMULTIIMAGES: "Runware Video Inference Inputs Reference Images Multiple Images Connector",
|
||||
VIDEOINFERENCEINPUTS: "Runware Video Inference Inputs",
|
||||
VIDEOINFERENCEELEMENTS: "Runware Video Inference Elements",
|
||||
VIDEOINFERENCEELEMENTSCOMBINE: "Runware Video Inference Elements Combine",
|
||||
@@ -434,6 +435,10 @@ const RUNWARE_NODE_PROPS = {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.VIDEOINPUTSREFERENCEMULTIIMAGES]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
},
|
||||
[RUNWARE_NODE_TYPES.VIDEOINFERENCEELEMENTS]: {
|
||||
bgColor: DEFAULT_BGCOLOR,
|
||||
colorModeOnly: true,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
from typing import List
|
||||
from .utils import runwareUtils as rwUtils
|
||||
|
||||
|
||||
class RunwareVideoInputsReferenceImagesMultipleImagesConnector:
|
||||
"""Collect up to 4 images for one referenceImages entry."""
|
||||
|
||||
MAX_IMAGES = 4
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
optionalInputs = {}
|
||||
for i in range(1, cls.MAX_IMAGES + 1):
|
||||
optionalInputs[f"Image{i}"] = ("IMAGE", {
|
||||
"tooltip": f"Optional image {i} for this reference group.",
|
||||
})
|
||||
return {
|
||||
"required": {},
|
||||
"optional": optionalInputs,
|
||||
}
|
||||
|
||||
DESCRIPTION = (
|
||||
"Collect up to 4 images for one referenceImages item. "
|
||||
"Connect this output to Images1/Images2/... on Runware Video Inference Inputs Reference Images."
|
||||
)
|
||||
FUNCTION = "createImages"
|
||||
RETURN_TYPES = ("RUNWAREVIDEOINPUTSREFERENCEMULTIIMAGES",)
|
||||
RETURN_NAMES = ("Images",)
|
||||
CATEGORY = "Runware"
|
||||
|
||||
def createImages(self, **kwargs) -> tuple[List[str]]:
|
||||
images: List[str] = []
|
||||
for i in range(1, self.MAX_IMAGES + 1):
|
||||
image = kwargs.get(f"Image{i}")
|
||||
if image is not None:
|
||||
images.append(rwUtils.convertTensor2IMG(image))
|
||||
return (images,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareVideoInputsReferenceImagesMultipleImagesConnector": RunwareVideoInputsReferenceImagesMultipleImagesConnector,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareVideoInputsReferenceImagesMultipleImagesConnector": "Runware Video Inference Inputs Reference Images Multiple Images Connector",
|
||||
}
|
||||
@@ -14,18 +14,21 @@ class videoInputsReferences:
|
||||
for i in range(1, cls.MAX_REFERENCES + 1):
|
||||
ordinal = rwUtils.getOrdinal(i)
|
||||
optionalInputs[f"Image{i}"] = ("IMAGE", {
|
||||
"tooltip": f"{ordinal.capitalize()} reference image (primary image for this reference entry).",
|
||||
"tooltip": f"{ordinal.capitalize()} single reference image (mutually exclusive with Images{i}).",
|
||||
})
|
||||
optionalInputs[f"Images{i}"] = ("RUNWAREVIDEOINPUTSREFERENCEMULTIIMAGES", {
|
||||
"tooltip": f"{ordinal.capitalize()} reference image group from the Multiple Images Connector (mutually exclusive with Image{i}).",
|
||||
})
|
||||
optionalInputs[f"Tag{i}"] = ("STRING", {
|
||||
"tooltip": f"Optional tag for the {ordinal} reference (e.g., @image{i}, @Actor-1).",
|
||||
"default": "",
|
||||
})
|
||||
optionalInputs[f"Type{i}"] = ("STRING", {
|
||||
"tooltip": f"Type for the {ordinal} reference (e.g., grid or image).",
|
||||
"tooltip": f"Type for the {ordinal} reference (e.g., image or grid). Leave empty to omit.",
|
||||
"default": "",
|
||||
})
|
||||
optionalInputs[f"Audio{i}"] = ("STRING", {
|
||||
"tooltip": f"Optional audio URL/mediaUUID for the {ordinal} reference (supported for type=image).",
|
||||
"tooltip": f"Optional audio URL/mediaUUID for the {ordinal} reference.",
|
||||
"default": "",
|
||||
})
|
||||
|
||||
@@ -35,8 +38,8 @@ class videoInputsReferences:
|
||||
}
|
||||
|
||||
DESCRIPTION = (
|
||||
"Configure multiple reference image entries for video inference inputs, "
|
||||
"with optional tag, type, images list, and audio per entry."
|
||||
"Configure multiple reference image entries for video inference inputs. "
|
||||
"For each slot, provide either ImageN (single image) or ImagesN (connector output), not both."
|
||||
)
|
||||
FUNCTION = "createReferences"
|
||||
RETURN_TYPES = ("RUNWAREVIDEOINPUTSREFERENCEIMAGES",)
|
||||
@@ -45,43 +48,48 @@ class videoInputsReferences:
|
||||
|
||||
def createReferences(self, **kwargs) -> tuple[List[Any]]:
|
||||
"""Create list of reference entries from provided parameters."""
|
||||
references = []
|
||||
references: List[Any] = []
|
||||
|
||||
for i in range(1, self.MAX_REFERENCES + 1):
|
||||
imageKey = f"Image{i}"
|
||||
imagesKey = f"Images{i}"
|
||||
tagKey = f"Tag{i}"
|
||||
typeKey = f"Type{i}"
|
||||
audioKey = f"Audio{i}"
|
||||
|
||||
image = kwargs.get(imageKey)
|
||||
images = kwargs.get(imagesKey)
|
||||
refTag = (kwargs.get(tagKey) or "").strip()
|
||||
refType = (kwargs.get(typeKey) or "").strip()
|
||||
refType = kwargs.get(typeKey, "")
|
||||
refAudio = (kwargs.get(audioKey) or "").strip()
|
||||
|
||||
has_image = image is not None
|
||||
has_images = isinstance(images, list) and len(images) > 0
|
||||
if has_image and has_images:
|
||||
raise ValueError(
|
||||
f"Reference {i}: use either {imageKey} or {imagesKey}, not both."
|
||||
)
|
||||
|
||||
if image is not None:
|
||||
reference = self._createReference(image, refTag, refType, refAudio)
|
||||
if has_image or has_images:
|
||||
reference = self._createReference(image, images, refTag, refType, refAudio)
|
||||
references.append(reference)
|
||||
|
||||
return (references,)
|
||||
|
||||
def _createReference(self, image, refTag: str, refType: str, refAudio: str):
|
||||
"""
|
||||
Backward compatible behavior:
|
||||
- If no extra metadata is provided, return legacy string entry.
|
||||
- If tag/type/images/audio are provided, return object entry.
|
||||
"""
|
||||
imageUrl = rwUtils.convertTensor2IMG(image)
|
||||
images = [imageUrl]
|
||||
def _createReference(self, image, images, refTag: str, refType: str, refAudio: str):
|
||||
"""Create reference entry."""
|
||||
entry: Dict[str, Any] = {}
|
||||
if image is not None:
|
||||
entry["image"] = rwUtils.convertTensor2IMG(image)
|
||||
elif isinstance(images, list) and len(images) > 0:
|
||||
entry["images"] = images
|
||||
else:
|
||||
return entry
|
||||
|
||||
has_extended_fields = bool(refTag or refType or refAudio or len(images) > 1)
|
||||
if not has_extended_fields:
|
||||
return imageUrl
|
||||
|
||||
entry: Dict[str, Any] = {"images": images}
|
||||
if refTag:
|
||||
entry["tag"] = refTag
|
||||
if refType:
|
||||
entry["type"] = refType
|
||||
if isinstance(refType, str) and refType.strip():
|
||||
entry["type"] = refType.strip()
|
||||
if refAudio:
|
||||
entry["audio"] = refAudio
|
||||
return entry
|
||||
|
||||
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