diff --git a/modules/videoInferenceInputs.py b/modules/videoInferenceInputs.py index 7072eb3..9cd271e 100644 --- a/modules/videoInferenceInputs.py +++ b/modules/videoInferenceInputs.py @@ -11,11 +11,11 @@ class videoInferenceInputs: "required": {}, "optional": { "Image": ("IMAGE", { - "tooltip": "Portrait image for video generation. This will be the main subject that will speak and move in the generated video." + "tooltip": "Portrait image for video generation (main subject that will speak and move). Mutually exclusive with Avatar: when Avatar is set, Image is ignored." }), "Avatar": ("STRING", { "default": "", - "tooltip": "HeyGen avatar ID for a photo avatar or video avatar. Mutually exclusive with image_url and image_asset_id.", + "tooltip": "HeyGen avatar ID for a photo or video avatar. Mutually exclusive with Image: when set, Image is ignored; use one or the other.", }), "Frame Images": ("RUNWAREVIDEOINPUTSFRAMEIMAGES", { "tooltip": "Connect the Runware Video Inputs Frame node to provide timeline-constrained frame images." @@ -63,7 +63,10 @@ class videoInferenceInputs: } } - DESCRIPTION = "Configure custom inputs for Runware Video Inference with OmniHuman 1.5 support, including image, audio, video, and mask inputs." + DESCRIPTION = ( + "Configure custom inputs for Runware Video Inference (image, audio, video, mask, avatar, etc.). " + "Avatar and Image are mutually exclusive: if Avatar is set, Image is ignored; provide only one." + ) FUNCTION = "createInputs" RETURN_TYPES = ("RUNWAREVIDEOINFERENCEINPUTS",) RETURN_NAMES = ("Video Inference Inputs",) @@ -89,10 +92,10 @@ class videoInferenceInputs: inputs = {} - if avatar is not None and avatar.strip() != "": + has_avatar = avatar is not None and avatar.strip() != "" + if has_avatar: inputs["avatar"] = avatar.strip() - - if image is not None: + if image is not None and not has_avatar: inputs["image"] = rwUtils.convertTensor2IMG(image) # Handle audio: can be either a string (legacy), a single dict, or a list of audio inputs diff --git a/modules/videoInferenceSpeechInput.py b/modules/videoInferenceSpeechInput.py index 6895e49..c716cfa 100644 --- a/modules/videoInferenceSpeechInput.py +++ b/modules/videoInferenceSpeechInput.py @@ -69,18 +69,23 @@ class RunwareVideoInferenceSpeechInput: FUNCTION = "createSpeech" CATEGORY = "Runware" DESCRIPTION = ( - "Configure speech synthesis for Runware Video Inference (voice and text). " - "Connect to Runware Video Inference speech input. Both voice and text must be set for speech to be included." + "Configure speech synthesis for Runware Video Inference. Connect to Runware Video Inference speech input. " + "Speech is only sent when both voice and text are enabled and non-empty; otherwise the node outputs nothing. " + "Optional fields (speed, pitch, language) are added only when their toggles are on." ) def createSpeech(self, **kwargs) -> tuple: - """Build speech dict for genConfig[0]['speech'].""" - + """Build speech dict for genConfig[0]['speech']. Only include non-empty values; return None unless both voice and text are present.""" speech: Dict[str, Any] = {} - if kwargs.get("useVoice"): - speech["voice"] = kwargs.get("voice") - if kwargs.get("useText"): - speech["text"] = kwargs.get("text") + + voice = (kwargs.get("voice") or "").strip() + if kwargs.get("useVoice") and voice: + speech["voice"] = voice + + text = (kwargs.get("text") or "").strip() + if kwargs.get("useText") and text: + speech["text"] = text + if kwargs.get("useSpeed"): speech["speed"] = float(kwargs.get("speed", 1.0)) if kwargs.get("usePitch"): @@ -90,7 +95,9 @@ class RunwareVideoInferenceSpeechInput: if lang: speech["language"] = lang - return (speech or None,) + if "voice" not in speech or "text" not in speech: + return (None,) + return (speech,) NODE_CLASS_MAPPINGS = {