Compare commits

..

2 Commits

4 changed files with 12 additions and 51 deletions

View File

@ -206,7 +206,7 @@ class BeebleSwitchXVideoEdit(IO.ComfyNode):
return IO.Schema(
node_id="BeebleSwitchXVideoEdit",
display_name="Beeble SwitchX Video Edit",
category="video/partner/Beeble",
category="api node/video/Beeble",
description=(
"Edit a video with Beeble SwitchX. Switches anything in the scene (background, "
"lighting, costume) while preserving the original subject's pixels and motion. "
@ -302,7 +302,7 @@ class BeebleSwitchXImageEdit(IO.ComfyNode):
return IO.Schema(
node_id="BeebleSwitchXImageEdit",
display_name="Beeble SwitchX Image Edit",
category="image/partner/Beeble",
category="api node/image/Beeble",
description=(
"Edit a single image with Beeble SwitchX. Switches anything in the scene "
"(background, lighting, costume) while preserving the original subject's pixels. "

View File

@ -44,7 +44,6 @@ from comfy_api_nodes.util import (
ApiEndpoint,
download_url_to_image_tensor,
download_url_to_video_output,
downscale_image_tensor_by_max_side,
downscale_video_to_max_pixels,
get_number_of_images,
image_tensor_pair_to_batch,
@ -123,14 +122,6 @@ def _validate_ref_video_pixels(video: Input.Video, model_id: str, resolution: st
)
def _prepare_seedance_image(image: Input.Image) -> Input.Image:
"""Auto-downscale a Seedance image input to the per-side limits, then validate it."""
validate_image_aspect_ratio(image, (2, 5), (5, 2), strict=False) # 0.4 to 2.5
image = downscale_image_tensor_by_max_side(image, max_side=6000)
validate_image_dimensions(image, min_width=300, min_height=300, max_width=6000, max_height=6000)
return image
async def _resolve_reference_assets(
cls: type[IO.ComfyNode],
asset_ids: list[str],
@ -1790,11 +1781,6 @@ class ByteDance2FirstLastFrameNode(IO.ComfyNode):
if last_frame is not None and last_frame_asset_id:
raise ValueError("Provide only one of last_frame or last_frame_asset_id, not both.")
if first_frame is not None:
first_frame = _prepare_seedance_image(first_frame)
if last_frame is not None:
last_frame = _prepare_seedance_image(last_frame)
asset_ids_to_resolve = [a for a in (first_frame_asset_id, last_frame_asset_id) if a]
image_assets: dict[str, str] = {}
if asset_ids_to_resolve:
@ -1901,7 +1887,7 @@ def _seedance2_reference_inputs(resolutions: list[str], default_ratio: str = "16
),
IO.Boolean.Input(
"auto_downscale",
default=True,
default=False,
optional=True,
tooltip="Automatically downscale reference videos that exceed the model's pixel budget "
"for the selected resolution. Aspect ratio is preserved; videos already within limits are untouched.",
@ -2069,9 +2055,6 @@ class ByteDance2ReferenceNode(IO.ComfyNode):
f"(audios={len(reference_audios)}, audio assets={len(reference_audio_assets)}). Maximum is 3."
)
for key in reference_images:
reference_images[key] = _prepare_seedance_image(reference_images[key])
model_id = SEEDANCE_MODELS[model["model"]]
has_video_input = total_videos > 0

View File

@ -157,7 +157,7 @@ class LoadImageTextDataSetFromFolderNode(io.ComfyNode):
return io.NodeOutput(output_tensor, captions)
def save_images_to_folder(image_list, output_dir, prefix="image", overwrite=True):
def save_images_to_folder(image_list, output_dir, prefix="image"):
"""Utility function to save a list of image tensors to disk.
Args:
@ -197,11 +197,7 @@ def save_images_to_folder(image_list, output_dir, prefix="image", overwrite=True
raise ValueError(f"Expected torch.Tensor, got {type(img_tensor)}")
# Save image
if overwrite:
filename = f"{prefix}_{idx:05d}.png"
else:
_, _, counter, _, resolved_prefix = folder_paths.get_save_image_path(prefix, output_dir)
filename = f"{resolved_prefix}_{counter:05}_{idx:05d}.png"
filename = f"{prefix}_{idx:05d}.png"
filepath = os.path.join(output_dir, filename)
img.save(filepath)
saved_files.append(filename)
@ -234,26 +230,19 @@ class SaveImageDataSetToFolderNode(io.ComfyNode):
tooltip="Prefix for saved image filenames.",
advanced=True,
),
io.Combo.Input(
"mode",
default="overwrite",
options=["overwrite", "increment"],
tooltip="Whether to overwrite existing files or increment filenames to avoid overwriting."
),
],
outputs=[],
is_deprecated=True, # This node is redundant and superseded by existing Save Image nodes where the target folder can be specified in the filename_prefix
)
@classmethod
def execute(cls, images, folder_name, filename_prefix, mode):
def execute(cls, images, folder_name, filename_prefix):
# Extract scalar values
folder_name = folder_name[0]
filename_prefix = filename_prefix[0]
mode = mode[0]
output_dir = os.path.join(folder_paths.get_output_directory(), folder_name)
saved_files = save_images_to_folder(images, output_dir, filename_prefix, mode=='overwrite')
saved_files = save_images_to_folder(images, output_dir, filename_prefix)
logging.info(f"Saved {len(saved_files)} images to {output_dir}.")
return io.NodeOutput()
@ -289,25 +278,18 @@ class SaveImageTextDataSetToFolderNode(io.ComfyNode):
tooltip="Prefix for saved image filenames.",
advanced=True,
),
io.Combo.Input(
"mode",
default="overwrite",
options=["overwrite", "increment"],
tooltip="Whether to overwrite existing files or increment filenames to avoid overwriting."
),
],
outputs=[],
)
@classmethod
def execute(cls, images, folder_name, filename_prefix, mode, texts=None):
def execute(cls, images, folder_name, filename_prefix, texts=None):
# Extract scalar values
folder_name = folder_name[0]
filename_prefix = filename_prefix[0]
mode = mode[0]
output_dir = os.path.join(folder_paths.get_output_directory(), folder_name)
saved_files = save_images_to_folder(images, output_dir, filename_prefix, mode=='overwrite')
saved_files = save_images_to_folder(images, output_dir, filename_prefix)
# Save captions
if texts:

View File

@ -34,7 +34,7 @@ class Load3D(IO.ComfyNode):
essentials_category="Basics",
is_experimental=True,
inputs=[
IO.Combo.Input("model_file", options=["none"] + sorted(files), upload=IO.UploadType.model),
IO.Combo.Input("model_file", options=sorted(files), upload=IO.UploadType.model),
IO.Load3D.Input("image"),
IO.Int.Input("width", default=1024, min=1, max=4096, step=1),
IO.Int.Input("height", default=1024, min=1, max=4096, step=1),
@ -68,12 +68,8 @@ class Load3D(IO.ComfyNode):
video = InputImpl.VideoFromFile(recording_video_path)
file_3d = None
mesh_path = ""
if model_file and model_file != "none":
file_3d = Types.File3D(folder_paths.get_annotated_filepath(model_file))
mesh_path = model_file
return IO.NodeOutput(output_image, output_mask, mesh_path, normal_image, image['camera_info'], video, file_3d)
file_3d = Types.File3D(folder_paths.get_annotated_filepath(model_file))
return IO.NodeOutput(output_image, output_mask, model_file, normal_image, image['camera_info'], video, file_3d)
process = execute # TODO: remove