Added support for HeyGen Avatar
This commit is contained in:
@@ -125,12 +125,8 @@ class txt2vid:
|
||||
"referenceVideos": ("RUNWAREREFERENCEVIDEOS", {
|
||||
"tooltip": "Connect reference video files for video generation.",
|
||||
}),
|
||||
"speechVoice": ("STRING", {
|
||||
"tooltip": "Voice for speech synthesis. Specify the voice to use for text-to-speech generation.",
|
||||
}),
|
||||
"speechText": ("STRING", {
|
||||
"multiline": True,
|
||||
"tooltip": "Text for speech synthesis. The text that will be converted to speech using the specified voice.",
|
||||
"speech": ("RUNWAREVIDEOINFERENCESPEECHINPUT", {
|
||||
"tooltip": "Connect a Runware Video Inference Speech Input node to set voice and text for speech synthesis.",
|
||||
}),
|
||||
"inputs": ("RUNWAREVIDEOINFERENCEINPUTS", {
|
||||
"tooltip": "Connect a Runware Video Inference Inputs node to provide custom inputs like image, audio, mask, and parameters for OmniHuman 1.5 and other video models.",
|
||||
@@ -178,8 +174,7 @@ class txt2vid:
|
||||
referenceImages = kwargs.get("referenceImages", None)
|
||||
inputAudios = kwargs.get("inputAudios", None)
|
||||
referenceVideos = kwargs.get("referenceVideos", None)
|
||||
speechVoice = kwargs.get("speechVoice", None)
|
||||
speechText = kwargs.get("speechText", None)
|
||||
speech = kwargs.get("speech", None)
|
||||
inputs = kwargs.get("inputs", None)
|
||||
safetyInputs = kwargs.get("safetyInputs", None)
|
||||
videoAdvancedFeatureInputs = kwargs.get("videoAdvancedFeatureInputs", None)
|
||||
@@ -300,14 +295,11 @@ class txt2vid:
|
||||
genConfig[0]["referenceVideos"] = referenceVideos
|
||||
print(f"[Debugging] Reference videos: {rwUtils.sanitize_for_logging(genConfig[0].get('referenceVideos', []))}")
|
||||
|
||||
# Add speech parameters if both voice and text are provided
|
||||
if speechVoice and speechVoice.strip() != "" and speechText and speechText.strip() != "":
|
||||
genConfig[0]["speech"] = {
|
||||
"voice": speechVoice.strip(),
|
||||
"text": speechText.strip()
|
||||
}
|
||||
print(f"[Debugging] Speech parameters: voice='{speechVoice.strip()}', text='{speechText.strip()[:50]}...'")
|
||||
|
||||
# Add speech parameters if provided from Runware Video Inference Speech Input node
|
||||
if speech is not None and isinstance(speech, dict) and speech:
|
||||
genConfig[0]["speech"] = speech
|
||||
print(f"[Debugging] Speech parameters: {rwUtils.sanitize_for_logging(speech)}")
|
||||
|
||||
# Handle inputs - merge custom inputs from Video Inference Inputs node
|
||||
if inputs is not None:
|
||||
# Merge inputs from video inference inputs node
|
||||
|
||||
@@ -13,6 +13,10 @@ class videoInferenceInputs:
|
||||
"Image": ("IMAGE", {
|
||||
"tooltip": "Portrait image for video generation. This will be the main subject that will speak and move in the generated video."
|
||||
}),
|
||||
"Avatar": ("STRING", {
|
||||
"default": "",
|
||||
"tooltip": "HeyGen avatar ID for a photo avatar or video avatar. Mutually exclusive with image_url and image_asset_id.",
|
||||
}),
|
||||
"Frame Images": ("RUNWAREVIDEOINPUTSFRAMEIMAGES", {
|
||||
"tooltip": "Connect the Runware Video Inputs Frame node to provide timeline-constrained frame images."
|
||||
}),
|
||||
@@ -34,6 +38,9 @@ class videoInferenceInputs:
|
||||
"Frame": ("IMAGE", {
|
||||
"tooltip": "Frame image for video generation. Connect a Load Image node to provide the frame image."
|
||||
}),
|
||||
"Background": ("IMAGE", {
|
||||
"tooltip": "Background image for video generation. Connect a Load Image node to provide the background.",
|
||||
}),
|
||||
"References": ("RUNWAREVIDEOINPUTSREFERENCEIMAGES", {
|
||||
"tooltip": "Connect the Video Inputs References node to provide reference images."
|
||||
}),
|
||||
@@ -71,15 +78,20 @@ class videoInferenceInputs:
|
||||
video = kwargs.get("Video", None)
|
||||
mask = kwargs.get("Mask", None)
|
||||
frame = kwargs.get("Frame", None)
|
||||
background = kwargs.get("Background", None)
|
||||
frameImages = kwargs.get("Frame Images", None)
|
||||
references = kwargs.get("References", None)
|
||||
referenceVideos = kwargs.get("Reference Videos", None)
|
||||
referenceVoices = kwargs.get("Reference Voices", None)
|
||||
draftId = kwargs.get("draftId", "")
|
||||
videoId = kwargs.get("videoId", "")
|
||||
avatar = kwargs.get("Avatar", "")
|
||||
|
||||
inputs = {}
|
||||
|
||||
if avatar is not None and avatar.strip() != "":
|
||||
inputs["avatar"] = avatar.strip()
|
||||
|
||||
if image is not None:
|
||||
inputs["image"] = rwUtils.convertTensor2IMG(image)
|
||||
|
||||
@@ -112,6 +124,9 @@ class videoInferenceInputs:
|
||||
if frame is not None:
|
||||
inputs["frame"] = rwUtils.convertTensor2IMG(frame)
|
||||
|
||||
if background is not None:
|
||||
inputs["background"] = rwUtils.convertTensor2IMG(background)
|
||||
|
||||
if frameImages is not None and len(frameImages) > 0:
|
||||
inputs["frameImages"] = frameImages
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
"""
|
||||
Runware Video Inference Speech Input Node.
|
||||
Provides voice and text for speech synthesis; connect to Runware Video Inference speech input.
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, Tuple
|
||||
|
||||
|
||||
class RunwareVideoInferenceSpeechInput:
|
||||
"""Runware Video Inference Speech Input Node"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
"useVoice": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include voice in speech synthesis.",
|
||||
"default": False,
|
||||
}),
|
||||
"voice": ("STRING", {
|
||||
"tooltip": "Voice ID for text-to-speech or speech-to-speech. Required when text script is provided. Only used when 'Use Voice' is enabled.",
|
||||
"default": "",
|
||||
}),
|
||||
"useText": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include text in speech synthesis.",
|
||||
"default": False,
|
||||
}),
|
||||
"text": ("STRING", {
|
||||
"multiline": True,
|
||||
"tooltip": "Text script for the avatar to speak. Requires voice. Mutually exclusive with audio-driven input. Only used when 'Use Text' is enabled.",
|
||||
"default": "",
|
||||
}),
|
||||
"useSpeed": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set voice playback speed multiplier.",
|
||||
"default": False,
|
||||
}),
|
||||
"speed": ("FLOAT", {
|
||||
"tooltip": "Voice playback speed multiplier (0.5 - 1.5). Only used when 'Use Speed' is enabled.",
|
||||
"default": 1.0,
|
||||
"min": 0.5,
|
||||
"max": 1.5,
|
||||
"step": 0.05,
|
||||
}),
|
||||
"usePitch": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set voice pitch adjustment in semitones.",
|
||||
"default": False,
|
||||
}),
|
||||
"pitch": ("FLOAT", {
|
||||
"tooltip": "Voice pitch adjustment in semitones (-50 to 50). Only used when 'Use Pitch' is enabled.",
|
||||
"default": 0.0,
|
||||
"min": -50.0,
|
||||
"max": 50.0,
|
||||
"step": 0.5,
|
||||
}),
|
||||
"useLanguage": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set locale or accent hint for multilingual voices.",
|
||||
"default": False,
|
||||
}),
|
||||
"language": ("STRING", {
|
||||
"tooltip": "Locale or accent hint for multilingual voices, e.g. en-US. Only used when 'Use Language' is enabled.",
|
||||
"default": "",
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES: Tuple[str] = ("RUNWAREVIDEOINFERENCESPEECHINPUT",)
|
||||
RETURN_NAMES = ("speech",)
|
||||
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."
|
||||
)
|
||||
|
||||
def createSpeech(self, **kwargs) -> tuple:
|
||||
"""Build speech dict for genConfig[0]['speech']."""
|
||||
|
||||
speech: Dict[str, Any] = {}
|
||||
if kwargs.get("useVoice"):
|
||||
speech["voice"] = kwargs.get("voice")
|
||||
if kwargs.get("useText"):
|
||||
speech["text"] = kwargs.get("text")
|
||||
if kwargs.get("useSpeed"):
|
||||
speech["speed"] = float(kwargs.get("speed", 1.0))
|
||||
if kwargs.get("usePitch"):
|
||||
speech["pitch"] = float(kwargs.get("pitch", 0.0))
|
||||
if kwargs.get("useLanguage"):
|
||||
lang = (kwargs.get("language") or "").strip()
|
||||
if lang:
|
||||
speech["language"] = lang
|
||||
|
||||
return (speech or None,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareVideoInferenceSpeechInput": RunwareVideoInferenceSpeechInput,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareVideoInferenceSpeechInput": "Runware Video Inference Speech Input",
|
||||
}
|
||||
@@ -109,6 +109,9 @@ class videoModelSearch:
|
||||
"creatify:aurora@fast (Creatify Aurora Avatar Model API (720p))",
|
||||
"creatify:aurora@0 (Creatify Aurora Avatar Model API (720p))",
|
||||
],
|
||||
"HeyGen": [
|
||||
"heygen:avatar@4 (HeyGen Avatar IV)",
|
||||
],
|
||||
"Hunyuan": [
|
||||
"runware:hunyuanvideo@1.5 (HunyuanVideo-1.5)",
|
||||
],
|
||||
@@ -248,6 +251,9 @@ class videoModelSearch:
|
||||
|
||||
# Pruna Models (720p)
|
||||
"prunaai:p-video@0": {"width": 1280, "height": 720},
|
||||
|
||||
# HeyGen Models (Model ID: heygen-avatar-iv)
|
||||
"heygen:avatar@4": {"width": 1280, "height": 720},
|
||||
}
|
||||
|
||||
# Model resolutions mapping
|
||||
@@ -372,6 +378,9 @@ class videoModelSearch:
|
||||
|
||||
# Pruna Models
|
||||
"prunaai:p-video@0": "720p",
|
||||
|
||||
# HeyGen Models
|
||||
"heygen:avatar@4": "720p",
|
||||
}
|
||||
|
||||
MODEL_ARCHITECTURES = [
|
||||
@@ -391,6 +400,7 @@ class videoModelSearch:
|
||||
"Sync",
|
||||
"Bria",
|
||||
"Creatify",
|
||||
"HeyGen",
|
||||
"Hunyuan",
|
||||
"Kandinsky",
|
||||
"xAI",
|
||||
|
||||
@@ -44,6 +44,32 @@ class RunwareVideoSettings:
|
||||
"label_on": "Enabled",
|
||||
"label_off": "Disabled",
|
||||
}),
|
||||
"useBackgroundColor": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set background color. Required when background.type = color.",
|
||||
"default": False,
|
||||
}),
|
||||
"backgroundColor": ("STRING", {
|
||||
"tooltip": "Hex color code (e.g. #ff0000). Required when background.type = color. Only used when 'Use Background Color' is enabled.",
|
||||
"default": "",
|
||||
}),
|
||||
"useRemoveBackground": ("BOOLEAN", {
|
||||
"tooltip": "Enable to remove the avatar background. Video avatars must be trained with matting enabled.",
|
||||
"default": False,
|
||||
}),
|
||||
"removeBackground": ("BOOLEAN", {
|
||||
"tooltip": "Remove the avatar background. Only used when 'Use Remove Background' is enabled.",
|
||||
"default": False,
|
||||
"label_on": "Enabled",
|
||||
"label_off": "Disabled",
|
||||
}),
|
||||
"useExpressiveness": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set avatar expressiveness level. Applies to photo avatars only.",
|
||||
"default": False,
|
||||
}),
|
||||
"expressiveness": (["low", "medium", "high"], {
|
||||
"tooltip": "Avatar expressiveness level. Applies to photo avatars only. Only used when 'Use Expressiveness' is enabled.",
|
||||
"default": "low",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +87,12 @@ class RunwareVideoSettings:
|
||||
audio = kwargs.get("audio", True)
|
||||
use_prompt_upsampling = kwargs.get("usePromptUpsampling", True)
|
||||
prompt_upsampling = kwargs.get("promptUpsampling", True)
|
||||
use_background_color = kwargs.get("useBackgroundColor", False)
|
||||
background_color = (kwargs.get("backgroundColor") or "").strip()
|
||||
use_remove_background = kwargs.get("useRemoveBackground", False)
|
||||
remove_background = kwargs.get("removeBackground", False)
|
||||
use_expressiveness = kwargs.get("useExpressiveness", False)
|
||||
expressiveness = kwargs.get("expressiveness", "low")
|
||||
|
||||
settings: Dict[str, Any] = {}
|
||||
|
||||
@@ -70,6 +102,12 @@ class RunwareVideoSettings:
|
||||
settings["audio"] = bool(audio)
|
||||
if use_prompt_upsampling:
|
||||
settings["promptUpsampling"] = bool(prompt_upsampling)
|
||||
if use_background_color and background_color:
|
||||
settings["backgroundColor"] = background_color
|
||||
if use_remove_background:
|
||||
settings["removeBackground"] = bool(remove_background)
|
||||
if use_expressiveness:
|
||||
settings["expressiveness"] = expressiveness
|
||||
|
||||
return (settings,)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user