mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-02-21 10:45:31 +08:00
Compare commits
3 Commits
add-codera
...
feat/strin
| Author | SHA1 | Date | |
|---|---|---|---|
| a917a8dad7 | |||
| 1e86c1bcb2 | |||
| b254cecd03 |
@ -322,11 +322,14 @@ class String(ComfyTypeIO):
|
||||
'''String input.'''
|
||||
def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None,
|
||||
multiline=False, placeholder: str=None, default: str=None, dynamic_prompts: bool=None,
|
||||
min_length: int=None, max_length: int=None,
|
||||
socketless: bool=None, force_input: bool=None, extra_dict=None, raw_link: bool=None, advanced: bool=None):
|
||||
super().__init__(id, display_name, optional, tooltip, lazy, default, socketless, None, force_input, extra_dict, raw_link, advanced)
|
||||
self.multiline = multiline
|
||||
self.placeholder = placeholder
|
||||
self.dynamic_prompts = dynamic_prompts
|
||||
self.min_length = min_length
|
||||
self.max_length = max_length
|
||||
self.default: str
|
||||
|
||||
def as_dict(self):
|
||||
@ -334,6 +337,8 @@ class String(ComfyTypeIO):
|
||||
"multiline": self.multiline,
|
||||
"placeholder": self.placeholder,
|
||||
"dynamicPrompts": self.dynamic_prompts,
|
||||
"minLength": self.min_length,
|
||||
"maxLength": self.max_length,
|
||||
})
|
||||
|
||||
@comfytype(io_type="COMBO")
|
||||
|
||||
@ -23,7 +23,6 @@ from comfy_api_nodes.util import (
|
||||
upload_3d_model_to_comfyapi,
|
||||
upload_image_to_comfyapi,
|
||||
validate_image_dimensions,
|
||||
validate_string,
|
||||
)
|
||||
|
||||
|
||||
@ -61,7 +60,7 @@ class TencentTextToModelNode(IO.ComfyNode):
|
||||
options=["3.0", "3.1"],
|
||||
tooltip="The LowPoly option is unavailable for the `3.1` model.",
|
||||
),
|
||||
IO.String.Input("prompt", multiline=True, default="", tooltip="Supports up to 1024 characters."),
|
||||
IO.String.Input("prompt", multiline=True, default="", min_length=1, max_length=1024),
|
||||
IO.Int.Input("face_count", default=500000, min=40000, max=1500000),
|
||||
IO.DynamicCombo.Input(
|
||||
"generate_type",
|
||||
@ -123,7 +122,6 @@ class TencentTextToModelNode(IO.ComfyNode):
|
||||
seed: int,
|
||||
) -> IO.NodeOutput:
|
||||
_ = seed
|
||||
validate_string(prompt, field_name="prompt", min_length=1, max_length=1024)
|
||||
if model == "3.1" and generate_type["generate_type"].lower() == "lowpoly":
|
||||
raise ValueError("The LowPoly option is currently unavailable for the 3.1 model.")
|
||||
response = await sync_op(
|
||||
@ -417,7 +415,9 @@ class Tencent3DTextureEditNode(IO.ComfyNode):
|
||||
"prompt",
|
||||
multiline=True,
|
||||
default="",
|
||||
tooltip="Describes texture editing. Supports up to 1024 UTF-8 characters.",
|
||||
min_length=1,
|
||||
max_length=1024,
|
||||
tooltip="Describes texture editing.",
|
||||
),
|
||||
IO.Int.Input(
|
||||
"seed",
|
||||
@ -456,7 +456,6 @@ class Tencent3DTextureEditNode(IO.ComfyNode):
|
||||
file_format = model_3d.format.lower()
|
||||
if file_format != "fbx":
|
||||
raise ValueError(f"Unsupported file format: '{file_format}'. Only FBX format is supported.")
|
||||
validate_string(prompt, field_name="prompt", min_length=1, max_length=1024)
|
||||
model_url = await upload_3d_model_to_comfyapi(cls, model_3d, file_format)
|
||||
response = await sync_op(
|
||||
cls,
|
||||
|
||||
@ -91,7 +91,8 @@ def _generate_storyboard_inputs(count: int) -> list:
|
||||
f"storyboard_{i}_prompt",
|
||||
multiline=True,
|
||||
default="",
|
||||
tooltip=f"Prompt for storyboard segment {i}. Max 512 characters.",
|
||||
max_length=512,
|
||||
tooltip=f"Prompt for storyboard segment {i}.",
|
||||
),
|
||||
IO.Int.Input(
|
||||
f"storyboard_{i}_duration",
|
||||
@ -309,19 +310,6 @@ def is_valid_image_response(response: KlingVirtualTryOnResponse) -> bool:
|
||||
)
|
||||
|
||||
|
||||
def validate_prompts(prompt: str, negative_prompt: str, max_length: int) -> bool:
|
||||
"""Verifies that the positive prompt is not empty and that neither promt is too long."""
|
||||
if not prompt:
|
||||
raise ValueError("Positive prompt is empty")
|
||||
if len(prompt) > max_length:
|
||||
raise ValueError(f"Positive prompt is too long: {len(prompt)} characters")
|
||||
if negative_prompt and len(negative_prompt) > max_length:
|
||||
raise ValueError(
|
||||
f"Negative prompt is too long: {len(negative_prompt)} characters"
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def validate_task_creation_response(response) -> None:
|
||||
"""Validates that the Kling task creation request was successful."""
|
||||
if not is_valid_task_creation_response(response):
|
||||
@ -424,7 +412,6 @@ async def execute_text2video(
|
||||
aspect_ratio: str,
|
||||
camera_control: KlingCameraControl | None = None,
|
||||
) -> IO.NodeOutput:
|
||||
validate_prompts(prompt, negative_prompt, MAX_PROMPT_LENGTH_T2V)
|
||||
task_creation_response = await sync_op(
|
||||
cls,
|
||||
ApiEndpoint(path=PATH_TEXT_TO_VIDEO, method="POST"),
|
||||
@ -470,7 +457,6 @@ async def execute_image2video(
|
||||
camera_control: KlingCameraControl | None = None,
|
||||
end_frame: torch.Tensor | None = None,
|
||||
) -> IO.NodeOutput:
|
||||
validate_prompts(prompt, negative_prompt, MAX_PROMPT_LENGTH_I2V)
|
||||
validate_input_image(start_frame)
|
||||
|
||||
if camera_control is not None:
|
||||
@ -580,8 +566,6 @@ async def execute_lipsync(
|
||||
voice_speed: float | None = None,
|
||||
voice_id: str | None = None,
|
||||
) -> IO.NodeOutput:
|
||||
if text:
|
||||
validate_string(text, field_name="Text", max_length=MAX_PROMPT_LENGTH_LIP_SYNC)
|
||||
validate_video_dimensions(video, 720, 1920)
|
||||
validate_video_duration(video, 2, 10)
|
||||
|
||||
@ -763,8 +747,8 @@ class KlingTextToVideoNode(IO.ComfyNode):
|
||||
category="api node/video/Kling",
|
||||
description="Kling Text to Video Node",
|
||||
inputs=[
|
||||
IO.String.Input("prompt", multiline=True, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, tooltip="Negative text prompt"),
|
||||
IO.String.Input("prompt", multiline=True, min_length=1, max_length=2500, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, max_length=2500, tooltip="Negative text prompt"),
|
||||
IO.Float.Input("cfg_scale", default=1.0, min=0.0, max=1.0),
|
||||
IO.Combo.Input(
|
||||
"aspect_ratio",
|
||||
@ -1352,6 +1336,8 @@ class OmniProVideoToVideoNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
min_length=1,
|
||||
max_length=2500,
|
||||
tooltip="A text prompt describing the video content. "
|
||||
"This can include both positive and negative descriptions.",
|
||||
),
|
||||
@ -1413,7 +1399,6 @@ class OmniProVideoToVideoNode(IO.ComfyNode):
|
||||
) -> IO.NodeOutput:
|
||||
_ = seed
|
||||
prompt = normalize_omni_prompt_references(prompt)
|
||||
validate_string(prompt, min_length=1, max_length=2500)
|
||||
validate_video_duration(reference_video, min_duration=3.0, max_duration=10.05)
|
||||
validate_video_dimensions(reference_video, min_width=720, min_height=720, max_width=2160, max_height=2160)
|
||||
image_list: list[OmniParamImage] = []
|
||||
@ -1463,6 +1448,8 @@ class OmniProEditVideoNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
min_length=1,
|
||||
max_length=2500,
|
||||
tooltip="A text prompt describing the video content. "
|
||||
"This can include both positive and negative descriptions.",
|
||||
),
|
||||
@ -1520,7 +1507,6 @@ class OmniProEditVideoNode(IO.ComfyNode):
|
||||
) -> IO.NodeOutput:
|
||||
_ = seed
|
||||
prompt = normalize_omni_prompt_references(prompt)
|
||||
validate_string(prompt, min_length=1, max_length=2500)
|
||||
validate_video_duration(video, min_duration=3.0, max_duration=10.05)
|
||||
validate_video_dimensions(video, min_width=720, min_height=720, max_width=2160, max_height=2160)
|
||||
image_list: list[OmniParamImage] = []
|
||||
@ -1570,6 +1556,8 @@ class OmniProImageNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
min_length=1,
|
||||
max_length=2500,
|
||||
tooltip="A text prompt describing the image content. "
|
||||
"This can include both positive and negative descriptions.",
|
||||
),
|
||||
@ -1638,7 +1626,6 @@ class OmniProImageNode(IO.ComfyNode):
|
||||
if model_name == "kling-image-o1" and resolution == "4K":
|
||||
raise ValueError("4K resolution is not supported for kling-image-o1 model.")
|
||||
prompt = normalize_omni_prompt_references(prompt)
|
||||
validate_string(prompt, min_length=1, max_length=2500)
|
||||
image_list: list[OmniImageParamImage] = []
|
||||
if reference_images is not None:
|
||||
if get_number_of_images(reference_images) > 10:
|
||||
@ -1694,8 +1681,8 @@ class KlingCameraControlT2VNode(IO.ComfyNode):
|
||||
category="api node/video/Kling",
|
||||
description="Transform text into cinematic videos with professional camera movements that simulate real-world cinematography. Control virtual camera actions including zoom, rotation, pan, tilt, and first-person view, while maintaining focus on your original text.",
|
||||
inputs=[
|
||||
IO.String.Input("prompt", multiline=True, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, tooltip="Negative text prompt"),
|
||||
IO.String.Input("prompt", multiline=True, min_length=1, max_length=2500, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, max_length=2500, tooltip="Negative text prompt"),
|
||||
IO.Float.Input("cfg_scale", default=0.75, min=0.0, max=1.0),
|
||||
IO.Combo.Input(
|
||||
"aspect_ratio",
|
||||
@ -1756,8 +1743,8 @@ class KlingImage2VideoNode(IO.ComfyNode):
|
||||
category="api node/video/Kling",
|
||||
inputs=[
|
||||
IO.Image.Input("start_frame", tooltip="The reference image used to generate the video."),
|
||||
IO.String.Input("prompt", multiline=True, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, tooltip="Negative text prompt"),
|
||||
IO.String.Input("prompt", multiline=True, min_length=1, max_length=500, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, max_length=500, tooltip="Negative text prompt"),
|
||||
IO.Combo.Input(
|
||||
"model_name",
|
||||
options=KlingVideoGenModelName,
|
||||
@ -1859,8 +1846,8 @@ class KlingCameraControlI2VNode(IO.ComfyNode):
|
||||
"start_frame",
|
||||
tooltip="Reference Image - URL or Base64 encoded string, cannot exceed 10MB, resolution not less than 300*300px, aspect ratio between 1:2.5 ~ 2.5:1. Base64 should not include data:image prefix.",
|
||||
),
|
||||
IO.String.Input("prompt", multiline=True, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, tooltip="Negative text prompt"),
|
||||
IO.String.Input("prompt", multiline=True, min_length=1, max_length=500, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, max_length=500, tooltip="Negative text prompt"),
|
||||
IO.Float.Input("cfg_scale", default=0.75, min=0.0, max=1.0),
|
||||
IO.Combo.Input(
|
||||
"aspect_ratio",
|
||||
@ -1934,8 +1921,8 @@ class KlingStartEndFrameNode(IO.ComfyNode):
|
||||
"end_frame",
|
||||
tooltip="Reference Image - End frame control. URL or Base64 encoded string, cannot exceed 10MB, resolution not less than 300*300px. Base64 should not include data:image prefix.",
|
||||
),
|
||||
IO.String.Input("prompt", multiline=True, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, tooltip="Negative text prompt"),
|
||||
IO.String.Input("prompt", multiline=True, min_length=1, max_length=500, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, max_length=500, tooltip="Negative text prompt"),
|
||||
IO.Float.Input("cfg_scale", default=0.5, min=0.0, max=1.0),
|
||||
IO.Combo.Input("aspect_ratio", options=["16:9", "9:16", "1:1"]),
|
||||
IO.Combo.Input(
|
||||
@ -2023,11 +2010,14 @@ class KlingVideoExtendNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
min_length=1,
|
||||
max_length=2500,
|
||||
tooltip="Positive text prompt for guiding the video extension",
|
||||
),
|
||||
IO.String.Input(
|
||||
"negative_prompt",
|
||||
multiline=True,
|
||||
max_length=2500,
|
||||
tooltip="Negative text prompt for elements to avoid in the extended video",
|
||||
),
|
||||
IO.Float.Input("cfg_scale", default=0.5, min=0.0, max=1.0),
|
||||
@ -2061,7 +2051,6 @@ class KlingVideoExtendNode(IO.ComfyNode):
|
||||
cfg_scale: float,
|
||||
video_id: str,
|
||||
) -> IO.NodeOutput:
|
||||
validate_prompts(prompt, negative_prompt, MAX_PROMPT_LENGTH_T2V)
|
||||
task_creation_response = await sync_op(
|
||||
cls,
|
||||
ApiEndpoint(path=PATH_VIDEO_EXTEND, method="POST"),
|
||||
@ -2320,7 +2309,8 @@ class KlingLipSyncTextToVideoNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"text",
|
||||
multiline=True,
|
||||
tooltip="Text Content for Lip-Sync Video Generation. Required when mode is text2video. Maximum length is 120 characters.",
|
||||
max_length=120,
|
||||
tooltip="Text Content for Lip-Sync Video Generation. Required when mode is text2video.",
|
||||
),
|
||||
IO.Combo.Input(
|
||||
"voice",
|
||||
@ -2451,8 +2441,8 @@ class KlingImageGenerationNode(IO.ComfyNode):
|
||||
category="api node/image/Kling",
|
||||
description="Kling Image Generation Node. Generate an image from a text prompt with an optional reference image.",
|
||||
inputs=[
|
||||
IO.String.Input("prompt", multiline=True, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, tooltip="Negative text prompt"),
|
||||
IO.String.Input("prompt", multiline=True, min_length=1, max_length=500, tooltip="Positive text prompt"),
|
||||
IO.String.Input("negative_prompt", multiline=True, max_length=500, tooltip="Negative text prompt"),
|
||||
IO.Combo.Input(
|
||||
"image_type",
|
||||
options=[i.value for i in KlingImageGenImageReferenceType],
|
||||
@ -2543,8 +2533,6 @@ class KlingImageGenerationNode(IO.ComfyNode):
|
||||
seed: int = 0,
|
||||
) -> IO.NodeOutput:
|
||||
_ = seed
|
||||
validate_string(prompt, field_name="prompt", min_length=1, max_length=MAX_PROMPT_LENGTH_IMAGE_GEN)
|
||||
validate_string(negative_prompt, field_name="negative_prompt", max_length=MAX_PROMPT_LENGTH_IMAGE_GEN)
|
||||
task_creation_response = await sync_op(
|
||||
cls,
|
||||
ApiEndpoint(path=PATH_IMAGE_GENERATIONS, method="POST"),
|
||||
@ -2588,7 +2576,7 @@ class TextToVideoWithAudio(IO.ComfyNode):
|
||||
category="api node/video/Kling",
|
||||
inputs=[
|
||||
IO.Combo.Input("model_name", options=["kling-v2-6"]),
|
||||
IO.String.Input("prompt", multiline=True, tooltip="Positive text prompt."),
|
||||
IO.String.Input("prompt", multiline=True, min_length=1, max_length=2500, tooltip="Positive text prompt."),
|
||||
IO.Combo.Input("mode", options=["pro"]),
|
||||
IO.Combo.Input("aspect_ratio", options=["16:9", "9:16", "1:1"]),
|
||||
IO.Combo.Input("duration", options=[5, 10]),
|
||||
@ -2619,7 +2607,6 @@ class TextToVideoWithAudio(IO.ComfyNode):
|
||||
duration: int,
|
||||
generate_audio: bool,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, min_length=1, max_length=2500)
|
||||
response = await sync_op(
|
||||
cls,
|
||||
ApiEndpoint(path="/proxy/kling/v1/videos/text2video", method="POST"),
|
||||
@ -2657,7 +2644,7 @@ class ImageToVideoWithAudio(IO.ComfyNode):
|
||||
inputs=[
|
||||
IO.Combo.Input("model_name", options=["kling-v2-6"]),
|
||||
IO.Image.Input("start_frame"),
|
||||
IO.String.Input("prompt", multiline=True, tooltip="Positive text prompt."),
|
||||
IO.String.Input("prompt", multiline=True, min_length=1, max_length=2500, tooltip="Positive text prompt."),
|
||||
IO.Combo.Input("mode", options=["pro"]),
|
||||
IO.Combo.Input("duration", options=[5, 10]),
|
||||
IO.Boolean.Input("generate_audio", default=True, advanced=True),
|
||||
@ -2687,7 +2674,6 @@ class ImageToVideoWithAudio(IO.ComfyNode):
|
||||
duration: int,
|
||||
generate_audio: bool,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, min_length=1, max_length=2500)
|
||||
validate_image_dimensions(start_frame, min_width=300, min_height=300)
|
||||
validate_image_aspect_ratio(start_frame, (1, 2.5), (2.5, 1))
|
||||
response = await sync_op(
|
||||
@ -2725,7 +2711,7 @@ class MotionControl(IO.ComfyNode):
|
||||
display_name="Kling Motion Control",
|
||||
category="api node/video/Kling",
|
||||
inputs=[
|
||||
IO.String.Input("prompt", multiline=True),
|
||||
IO.String.Input("prompt", multiline=True, max_length=2500),
|
||||
IO.Image.Input("reference_image"),
|
||||
IO.Video.Input(
|
||||
"reference_video",
|
||||
@ -2776,7 +2762,6 @@ class MotionControl(IO.ComfyNode):
|
||||
character_orientation: str,
|
||||
mode: str,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, max_length=2500)
|
||||
validate_image_dimensions(reference_image, min_width=340, min_height=340)
|
||||
validate_image_aspect_ratio(reference_image, (1, 2.5), (2.5, 1))
|
||||
if character_orientation == "image":
|
||||
@ -3034,7 +3019,7 @@ class KlingFirstLastFrameNode(IO.ComfyNode):
|
||||
category="api node/video/Kling",
|
||||
description="Generate videos with Kling V3 using first and last frames.",
|
||||
inputs=[
|
||||
IO.String.Input("prompt", multiline=True, default=""),
|
||||
IO.String.Input("prompt", multiline=True, default="", min_length=1, max_length=2500),
|
||||
IO.Int.Input(
|
||||
"duration",
|
||||
default=5,
|
||||
@ -3105,7 +3090,6 @@ class KlingFirstLastFrameNode(IO.ComfyNode):
|
||||
seed: int,
|
||||
) -> IO.NodeOutput:
|
||||
_ = seed
|
||||
validate_string(prompt, min_length=1, max_length=2500)
|
||||
validate_image_dimensions(first_frame, min_width=300, min_height=300)
|
||||
validate_image_aspect_ratio(first_frame, (1, 2.5), (2.5, 1))
|
||||
validate_image_dimensions(end_frame, min_width=300, min_height=300)
|
||||
|
||||
@ -36,7 +36,7 @@ class MeshyTextToModelNode(IO.ComfyNode):
|
||||
category="api node/3d/Meshy",
|
||||
inputs=[
|
||||
IO.Combo.Input("model", options=["latest"]),
|
||||
IO.String.Input("prompt", multiline=True, default=""),
|
||||
IO.String.Input("prompt", multiline=True, default="", min_length=1, max_length=600),
|
||||
IO.Combo.Input("style", options=["realistic", "sculpture"]),
|
||||
IO.DynamicCombo.Input(
|
||||
"should_remesh",
|
||||
@ -105,7 +105,6 @@ class MeshyTextToModelNode(IO.ComfyNode):
|
||||
pose_mode: str,
|
||||
seed: int,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, field_name="prompt", min_length=1, max_length=600)
|
||||
response = await sync_op(
|
||||
cls,
|
||||
ApiEndpoint(path="/proxy/meshy/openapi/v2/text-to-3d", method="POST"),
|
||||
@ -162,8 +161,9 @@ class MeshyRefineNode(IO.ComfyNode):
|
||||
"texture_prompt",
|
||||
default="",
|
||||
multiline=True,
|
||||
max_length=600,
|
||||
tooltip="Provide a text prompt to guide the texturing process. "
|
||||
"Maximum 600 characters. Cannot be used at the same time as 'texture_image'.",
|
||||
"Cannot be used at the same time as 'texture_image'.",
|
||||
),
|
||||
IO.Image.Input(
|
||||
"texture_image",
|
||||
@ -201,8 +201,6 @@ class MeshyRefineNode(IO.ComfyNode):
|
||||
if texture_prompt and texture_image is not None:
|
||||
raise ValueError("texture_prompt and texture_image cannot be used at the same time")
|
||||
texture_image_url = None
|
||||
if texture_prompt:
|
||||
validate_string(texture_prompt, field_name="texture_prompt", max_length=600)
|
||||
if texture_image is not None:
|
||||
texture_image_url = (await upload_images_to_comfyapi(cls, texture_image, wait_label="Uploading texture"))[0]
|
||||
response = await sync_op(
|
||||
@ -281,8 +279,9 @@ class MeshyImageToModelNode(IO.ComfyNode):
|
||||
"texture_prompt",
|
||||
default="",
|
||||
multiline=True,
|
||||
max_length=600,
|
||||
tooltip="Provide a text prompt to guide the texturing process. "
|
||||
"Maximum 600 characters. Cannot be used at the same time as 'texture_image'.",
|
||||
"Cannot be used at the same time as 'texture_image'.",
|
||||
),
|
||||
IO.Image.Input(
|
||||
"texture_image",
|
||||
@ -449,8 +448,9 @@ class MeshyMultiImageToModelNode(IO.ComfyNode):
|
||||
"texture_prompt",
|
||||
default="",
|
||||
multiline=True,
|
||||
max_length=600,
|
||||
tooltip="Provide a text prompt to guide the texturing process. "
|
||||
"Maximum 600 characters. Cannot be used at the same time as 'texture_image'.",
|
||||
"Cannot be used at the same time as 'texture_image'.",
|
||||
),
|
||||
IO.Image.Input(
|
||||
"texture_image",
|
||||
@ -739,8 +739,9 @@ class MeshyTextureNode(IO.ComfyNode):
|
||||
"text_style_prompt",
|
||||
default="",
|
||||
multiline=True,
|
||||
tooltip="Describe your desired texture style of the object using text. Maximum 600 characters."
|
||||
"Maximum 600 characters. Cannot be used at the same time as 'image_style'.",
|
||||
max_length=600,
|
||||
tooltip="Describe your desired texture style of the object using text. "
|
||||
"Cannot be used at the same time as 'image_style'.",
|
||||
),
|
||||
IO.Image.Input(
|
||||
"image_style",
|
||||
|
||||
@ -30,7 +30,6 @@ from comfy_api_nodes.util import (
|
||||
resize_mask_to_image,
|
||||
sync_op,
|
||||
tensor_to_bytesio,
|
||||
validate_string,
|
||||
)
|
||||
from comfy_extras.nodes_images import SVG
|
||||
|
||||
@ -403,7 +402,14 @@ class RecraftTextToImageNode(IO.ComfyNode):
|
||||
category="api node/image/Recraft",
|
||||
description="Generates images synchronously based on prompt and resolution.",
|
||||
inputs=[
|
||||
IO.String.Input("prompt", multiline=True, default="", tooltip="Prompt for the image generation."),
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
default="",
|
||||
min_length=1,
|
||||
max_length=1000,
|
||||
tooltip="Prompt for the image generation.",
|
||||
),
|
||||
IO.Combo.Input(
|
||||
"size",
|
||||
options=[res.value for res in RecraftImageSize],
|
||||
@ -466,7 +472,6 @@ class RecraftTextToImageNode(IO.ComfyNode):
|
||||
negative_prompt: str = None,
|
||||
recraft_controls: RecraftControls = None,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, strip_whitespace=False, min_length=1, max_length=1000)
|
||||
default_style = RecraftStyle(RecraftStyleV3.realistic_image)
|
||||
if recraft_style is None:
|
||||
recraft_style = default_style
|
||||
@ -516,7 +521,9 @@ class RecraftImageToImageNode(IO.ComfyNode):
|
||||
description="Modify image based on prompt and strength.",
|
||||
inputs=[
|
||||
IO.Image.Input("image"),
|
||||
IO.String.Input("prompt", multiline=True, default="", tooltip="Prompt for the image generation."),
|
||||
IO.String.Input(
|
||||
"prompt", multiline=True, default="", max_length=1000, tooltip="Prompt for the image generation."
|
||||
),
|
||||
IO.Int.Input(
|
||||
"n",
|
||||
default=1,
|
||||
@ -583,7 +590,6 @@ class RecraftImageToImageNode(IO.ComfyNode):
|
||||
negative_prompt: str = None,
|
||||
recraft_controls: RecraftControls = None,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, strip_whitespace=False, max_length=1000)
|
||||
default_style = RecraftStyle(RecraftStyleV3.realistic_image)
|
||||
if recraft_style is None:
|
||||
recraft_style = default_style
|
||||
@ -635,7 +641,9 @@ class RecraftImageInpaintingNode(IO.ComfyNode):
|
||||
inputs=[
|
||||
IO.Image.Input("image"),
|
||||
IO.Mask.Input("mask"),
|
||||
IO.String.Input("prompt", multiline=True, default="", tooltip="Prompt for the image generation."),
|
||||
IO.String.Input(
|
||||
"prompt", multiline=True, default="", max_length=1000, tooltip="Prompt for the image generation."
|
||||
),
|
||||
IO.Int.Input(
|
||||
"n",
|
||||
default=1,
|
||||
@ -687,7 +695,6 @@ class RecraftImageInpaintingNode(IO.ComfyNode):
|
||||
recraft_style: RecraftStyle = None,
|
||||
negative_prompt: str = None,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, strip_whitespace=False, max_length=1000)
|
||||
default_style = RecraftStyle(RecraftStyleV3.realistic_image)
|
||||
if recraft_style is None:
|
||||
recraft_style = default_style
|
||||
@ -735,7 +742,9 @@ class RecraftTextToVectorNode(IO.ComfyNode):
|
||||
category="api node/image/Recraft",
|
||||
description="Generates SVG synchronously based on prompt and resolution.",
|
||||
inputs=[
|
||||
IO.String.Input("prompt", default="", tooltip="Prompt for the image generation.", multiline=True),
|
||||
IO.String.Input(
|
||||
"prompt", default="", max_length=1000, tooltip="Prompt for the image generation.", multiline=True
|
||||
),
|
||||
IO.Combo.Input("substyle", options=get_v3_substyles(RecraftStyleV3.vector_illustration)),
|
||||
IO.Combo.Input(
|
||||
"size",
|
||||
@ -792,7 +801,6 @@ class RecraftTextToVectorNode(IO.ComfyNode):
|
||||
negative_prompt: str = None,
|
||||
recraft_controls: RecraftControls = None,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, strip_whitespace=False, max_length=1000)
|
||||
# create RecraftStyle so strings will be formatted properly (i.e. "None" will become None)
|
||||
recraft_style = RecraftStyle(RecraftStyleV3.vector_illustration, substyle=substyle)
|
||||
|
||||
@ -1091,7 +1099,9 @@ class RecraftV4TextToImageNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
tooltip="Prompt for the image generation. Maximum 10,000 characters.",
|
||||
min_length=1,
|
||||
max_length=10000,
|
||||
tooltip="Prompt for the image generation.",
|
||||
),
|
||||
IO.String.Input(
|
||||
"negative_prompt",
|
||||
@ -1178,7 +1188,6 @@ class RecraftV4TextToImageNode(IO.ComfyNode):
|
||||
seed: int,
|
||||
recraft_controls: RecraftControls | None = None,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, strip_whitespace=False, min_length=1, max_length=10000)
|
||||
response = await sync_op(
|
||||
cls,
|
||||
ApiEndpoint(path="/proxy/recraft/image_generation", method="POST"),
|
||||
@ -1215,7 +1224,9 @@ class RecraftV4TextToVectorNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
tooltip="Prompt for the image generation. Maximum 10,000 characters.",
|
||||
min_length=1,
|
||||
max_length=10000,
|
||||
tooltip="Prompt for the image generation.",
|
||||
),
|
||||
IO.String.Input(
|
||||
"negative_prompt",
|
||||
@ -1302,7 +1313,6 @@ class RecraftV4TextToVectorNode(IO.ComfyNode):
|
||||
seed: int,
|
||||
recraft_controls: RecraftControls | None = None,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, strip_whitespace=False, min_length=1, max_length=10000)
|
||||
response = await sync_op(
|
||||
cls,
|
||||
ApiEndpoint(path="/proxy/recraft/image_generation", method="POST"),
|
||||
|
||||
@ -499,7 +499,9 @@ class Vidu2TextToVideoNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
tooltip="A textual description for video generation, with a maximum length of 2000 characters.",
|
||||
min_length=1,
|
||||
max_length=2000,
|
||||
tooltip="A textual description for video generation.",
|
||||
),
|
||||
IO.Int.Input(
|
||||
"duration",
|
||||
@ -560,7 +562,6 @@ class Vidu2TextToVideoNode(IO.ComfyNode):
|
||||
resolution: str,
|
||||
background_music: bool,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, min_length=1, max_length=2000)
|
||||
results = await execute_task(
|
||||
cls,
|
||||
VIDU_TEXT_TO_VIDEO,
|
||||
@ -596,7 +597,8 @@ class Vidu2ImageToVideoNode(IO.ComfyNode):
|
||||
"prompt",
|
||||
multiline=True,
|
||||
default="",
|
||||
tooltip="An optional text prompt for video generation (max 2000 characters).",
|
||||
max_length=2000,
|
||||
tooltip="An optional text prompt for video generation.",
|
||||
),
|
||||
IO.Int.Input(
|
||||
"duration",
|
||||
@ -685,7 +687,6 @@ class Vidu2ImageToVideoNode(IO.ComfyNode):
|
||||
if get_number_of_images(image) > 1:
|
||||
raise ValueError("Only one input image is allowed.")
|
||||
validate_image_aspect_ratio(image, (1, 4), (4, 1))
|
||||
validate_string(prompt, max_length=2000)
|
||||
results = await execute_task(
|
||||
cls,
|
||||
VIDU_IMAGE_TO_VIDEO,
|
||||
@ -731,6 +732,8 @@ class Vidu2ReferenceVideoNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
min_length=1,
|
||||
max_length=2000,
|
||||
tooltip="When enabled, the video will include generated speech and background music "
|
||||
"based on the prompt.",
|
||||
),
|
||||
@ -802,7 +805,6 @@ class Vidu2ReferenceVideoNode(IO.ComfyNode):
|
||||
resolution: str,
|
||||
movement_amplitude: str,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, min_length=1, max_length=2000)
|
||||
total_images = 0
|
||||
for i in subjects:
|
||||
if get_number_of_images(subjects[i]) > 3:
|
||||
@ -858,7 +860,8 @@ class Vidu2StartEndToVideoNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
tooltip="Prompt description (max 2000 characters).",
|
||||
max_length=2000,
|
||||
tooltip="Prompt description.",
|
||||
),
|
||||
IO.Int.Input(
|
||||
"duration",
|
||||
@ -940,7 +943,6 @@ class Vidu2StartEndToVideoNode(IO.ComfyNode):
|
||||
resolution: str,
|
||||
movement_amplitude: str,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, max_length=2000)
|
||||
if get_number_of_images(first_frame) > 1:
|
||||
raise ValueError("Only one input image is allowed for `first_frame`.")
|
||||
if get_number_of_images(end_frame) > 1:
|
||||
@ -1024,7 +1026,8 @@ class ViduExtendVideoNode(IO.ComfyNode):
|
||||
"prompt",
|
||||
multiline=True,
|
||||
default="",
|
||||
tooltip="An optional text prompt for the extended video (max 2000 characters).",
|
||||
max_length=2000,
|
||||
tooltip="An optional text prompt for the extended video.",
|
||||
),
|
||||
IO.Int.Input(
|
||||
"seed",
|
||||
@ -1078,7 +1081,6 @@ class ViduExtendVideoNode(IO.ComfyNode):
|
||||
seed: int,
|
||||
end_frame: Input.Image | None = None,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, max_length=2000)
|
||||
validate_video_duration(video, min_duration=4, max_duration=55)
|
||||
image_url = None
|
||||
if end_frame is not None:
|
||||
@ -1357,7 +1359,9 @@ class Vidu3TextToVideoNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
tooltip="A textual description for video generation, with a maximum length of 2000 characters.",
|
||||
min_length=1,
|
||||
max_length=2000,
|
||||
tooltip="A textual description for video generation.",
|
||||
),
|
||||
IO.Int.Input(
|
||||
"seed",
|
||||
@ -1405,7 +1409,6 @@ class Vidu3TextToVideoNode(IO.ComfyNode):
|
||||
prompt: str,
|
||||
seed: int,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, min_length=1, max_length=2000)
|
||||
results = await execute_task(
|
||||
cls,
|
||||
VIDU_TEXT_TO_VIDEO,
|
||||
@ -1497,7 +1500,8 @@ class Vidu3ImageToVideoNode(IO.ComfyNode):
|
||||
"prompt",
|
||||
multiline=True,
|
||||
default="",
|
||||
tooltip="An optional text prompt for video generation (max 2000 characters).",
|
||||
max_length=2000,
|
||||
tooltip="An optional text prompt for video generation.",
|
||||
),
|
||||
IO.Int.Input(
|
||||
"seed",
|
||||
@ -1547,7 +1551,6 @@ class Vidu3ImageToVideoNode(IO.ComfyNode):
|
||||
seed: int,
|
||||
) -> IO.NodeOutput:
|
||||
validate_image_aspect_ratio(image, (1, 4), (4, 1))
|
||||
validate_string(prompt, max_length=2000)
|
||||
results = await execute_task(
|
||||
cls,
|
||||
VIDU_IMAGE_TO_VIDEO,
|
||||
@ -1636,7 +1639,8 @@ class Vidu3StartEndToVideoNode(IO.ComfyNode):
|
||||
IO.String.Input(
|
||||
"prompt",
|
||||
multiline=True,
|
||||
tooltip="Prompt description (max 2000 characters).",
|
||||
max_length=2000,
|
||||
tooltip="Prompt description.",
|
||||
),
|
||||
IO.Int.Input(
|
||||
"seed",
|
||||
@ -1686,7 +1690,6 @@ class Vidu3StartEndToVideoNode(IO.ComfyNode):
|
||||
prompt: str,
|
||||
seed: int,
|
||||
) -> IO.NodeOutput:
|
||||
validate_string(prompt, max_length=2000)
|
||||
validate_images_aspect_ratio_closeness(first_frame, end_frame, min_rel=0.8, max_rel=1.25, strict=False)
|
||||
payload = TaskCreationRequest(
|
||||
model=model["model"],
|
||||
|
||||
28
execution.py
28
execution.py
@ -944,6 +944,34 @@ async def validate_inputs(prompt_id, prompt, item, validated):
|
||||
errors.append(error)
|
||||
continue
|
||||
|
||||
if input_type == "STRING":
|
||||
if "minLength" in extra_info and len(val.strip()) < extra_info["minLength"]:
|
||||
error = {
|
||||
"type": "value_shorter_than_min_length",
|
||||
"message": "Value length {} shorter than min length of {}".format(len(val.strip()), extra_info["minLength"]),
|
||||
"details": f"{x}",
|
||||
"extra_info": {
|
||||
"input_name": x,
|
||||
"input_config": info,
|
||||
"received_value": val,
|
||||
}
|
||||
}
|
||||
errors.append(error)
|
||||
continue
|
||||
if "maxLength" in extra_info and len(val) > extra_info["maxLength"]:
|
||||
error = {
|
||||
"type": "value_longer_than_max_length",
|
||||
"message": "Value length {} longer than max length of {}".format(len(val), extra_info["maxLength"]),
|
||||
"details": f"{x}",
|
||||
"extra_info": {
|
||||
"input_name": x,
|
||||
"input_config": info,
|
||||
"received_value": val,
|
||||
}
|
||||
}
|
||||
errors.append(error)
|
||||
continue
|
||||
|
||||
if isinstance(input_type, list) or input_type == io.Combo.io_type:
|
||||
if input_type == io.Combo.io_type:
|
||||
combo_options = extra_info.get("options", [])
|
||||
|
||||
Reference in New Issue
Block a user