diff --git a/comfy_api/input/__init__.py b/comfy_api/input/__init__.py index 08e0eba11..68ff78270 100644 --- a/comfy_api/input/__init__.py +++ b/comfy_api/input/__init__.py @@ -1,2 +1,16 @@ # This file only exists for backwards compatibility. -from comfy_api.latest.input import * # noqa: F403 +from comfy_api.latest._input import ( + ImageInput, + AudioInput, + MaskInput, + LatentInput, + VideoInput, +) + +__all__ = [ + "ImageInput", + "AudioInput", + "MaskInput", + "LatentInput", + "VideoInput", +] diff --git a/comfy_api/input/basic_types.py b/comfy_api/input/basic_types.py index 12e0af4a2..5eadce86a 100644 --- a/comfy_api/input/basic_types.py +++ b/comfy_api/input/basic_types.py @@ -1,2 +1,14 @@ # This file only exists for backwards compatibility. -from comfy_api.latest.input.basic_types import * # noqa: F403 +from comfy_api.latest._input.basic_types import ( + ImageInput, + AudioInput, + MaskInput, + LatentInput, +) + +__all__ = [ + "ImageInput", + "AudioInput", + "MaskInput", + "LatentInput", +] diff --git a/comfy_api/input/video_types.py b/comfy_api/input/video_types.py index 089128e62..9ace78cbc 100644 --- a/comfy_api/input/video_types.py +++ b/comfy_api/input/video_types.py @@ -1,2 +1,6 @@ # This file only exists for backwards compatibility. -from comfy_api.latest.input.video_types import * # noqa: F403 +from comfy_api.latest._input.video_types import VideoInput + +__all__ = [ + "VideoInput", +] diff --git a/comfy_api/input_impl/__init__.py b/comfy_api/input_impl/__init__.py index 07cd7b344..b78ff0c08 100644 --- a/comfy_api/input_impl/__init__.py +++ b/comfy_api/input_impl/__init__.py @@ -1,2 +1,7 @@ # This file only exists for backwards compatibility. -from comfy_api.latest.input_impl import * # noqa: F403 +from comfy_api.latest._input_impl import VideoFromFile, VideoFromComponents + +__all__ = [ + "VideoFromFile", + "VideoFromComponents", +] diff --git a/comfy_api/input_impl/video_types.py b/comfy_api/input_impl/video_types.py index ac0a10124..bd2e56ad5 100644 --- a/comfy_api/input_impl/video_types.py +++ b/comfy_api/input_impl/video_types.py @@ -1,2 +1,2 @@ # This file only exists for backwards compatibility. -from comfy_api.latest.input_impl.video_types import * # noqa: F403 +from comfy_api.latest._input_impl.video_types import * # noqa: F403 diff --git a/comfy_api/latest/__init__.py b/comfy_api/latest/__init__.py index 8738196de..bcf09ffbf 100644 --- a/comfy_api/latest/__init__.py +++ b/comfy_api/latest/__init__.py @@ -4,9 +4,11 @@ from typing import Type, TYPE_CHECKING from comfy_api.internal import ComfyAPIBase from comfy_api.internal.singleton import ProxiedSingleton from comfy_api.internal.async_to_sync import create_sync_class -from comfy_api.latest.input import ImageInput +from comfy_api.latest._input import ImageInput, AudioInput, MaskInput, LatentInput, VideoInput +from comfy_api.latest._input_impl import VideoFromFile, VideoFromComponents +from comfy_api.latest._util import VideoCodec, VideoContainer, VideoComponents from comfy_execution.utils import get_executing_context -from comfy_execution.progress import get_progress_state +from comfy_execution.progress import get_progress_state, PreviewImageTuple from PIL import Image from comfy.cli_args import args import numpy as np @@ -40,35 +42,51 @@ class ComfyAPI_latest(ComfyAPIBase): raise ValueError("node_id must be provided if not in executing context") # Convert preview_image to PreviewImageTuple if needed - if preview_image is not None: + to_display: PreviewImageTuple | Image.Image | ImageInput | None = preview_image + if to_display is not None: # First convert to PIL Image if needed - if isinstance(preview_image, ImageInput): + if isinstance(to_display, ImageInput): # Convert ImageInput (torch.Tensor) to PIL Image # Handle tensor shape [B, H, W, C] -> get first image if batch - tensor = preview_image + tensor = to_display if len(tensor.shape) == 4: tensor = tensor[0] # Convert to numpy array and scale to 0-255 image_np = (tensor.cpu().numpy() * 255).astype(np.uint8) - preview_image = Image.fromarray(image_np) + to_display = Image.fromarray(image_np) - if isinstance(preview_image, Image.Image): + if isinstance(to_display, Image.Image): # Detect image format from PIL Image - image_format = preview_image.format if preview_image.format else "JPEG" + image_format = to_display.format if to_display.format else "JPEG" # Use None for preview_size if ignore_size_limit is True preview_size = None if ignore_size_limit else args.preview_size - preview_image = (image_format, preview_image, preview_size) + to_display = (image_format, to_display, preview_size) get_progress_state().update_progress( node_id=node_id, value=value, max_value=max_value, - image=preview_image, + image=to_display, ) execution: Execution +class Input: + Image = ImageInput + Audio = AudioInput + Mask = MaskInput + Latent = LatentInput + Video = VideoInput + +class InputImpl: + VideoFromFile = VideoFromFile + VideoFromComponents = VideoFromComponents + +class Types: + VideoCodec = VideoCodec + VideoContainer = VideoContainer + VideoComponents = VideoComponents ComfyAPI = ComfyAPI_latest diff --git a/comfy_api/latest/input/__init__.py b/comfy_api/latest/_input/__init__.py similarity index 100% rename from comfy_api/latest/input/__init__.py rename to comfy_api/latest/_input/__init__.py diff --git a/comfy_api/latest/input/basic_types.py b/comfy_api/latest/_input/basic_types.py similarity index 100% rename from comfy_api/latest/input/basic_types.py rename to comfy_api/latest/_input/basic_types.py diff --git a/comfy_api/latest/input/video_types.py b/comfy_api/latest/_input/video_types.py similarity index 100% rename from comfy_api/latest/input/video_types.py rename to comfy_api/latest/_input/video_types.py diff --git a/comfy_api/latest/input_impl/__init__.py b/comfy_api/latest/_input_impl/__init__.py similarity index 100% rename from comfy_api/latest/input_impl/__init__.py rename to comfy_api/latest/_input_impl/__init__.py diff --git a/comfy_api/latest/input_impl/video_types.py b/comfy_api/latest/_input_impl/video_types.py similarity index 98% rename from comfy_api/latest/input_impl/video_types.py rename to comfy_api/latest/_input_impl/video_types.py index 86aa6e008..2089307df 100644 --- a/comfy_api/latest/input_impl/video_types.py +++ b/comfy_api/latest/_input_impl/video_types.py @@ -3,13 +3,13 @@ from av.container import InputContainer from av.subtitles.stream import SubtitleStream from fractions import Fraction from typing import Optional -from comfy_api.latest.input import AudioInput, VideoInput +from comfy_api.latest._input import AudioInput, VideoInput import av import io import json import numpy as np import torch -from comfy_api.latest.util import VideoContainer, VideoCodec, VideoComponents +from comfy_api.latest._util import VideoContainer, VideoCodec, VideoComponents def container_to_output_format(container_format: str | None) -> str | None: diff --git a/comfy_api/latest/util/__init__.py b/comfy_api/latest/_util/__init__.py similarity index 100% rename from comfy_api/latest/util/__init__.py rename to comfy_api/latest/_util/__init__.py diff --git a/comfy_api/latest/util/video_types.py b/comfy_api/latest/_util/video_types.py similarity index 95% rename from comfy_api/latest/util/video_types.py rename to comfy_api/latest/_util/video_types.py index ceb937dc2..c3e3d8e3a 100644 --- a/comfy_api/latest/util/video_types.py +++ b/comfy_api/latest/_util/video_types.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from enum import Enum from fractions import Fraction from typing import Optional -from comfy_api.latest.input import ImageInput, AudioInput +from comfy_api.latest._input import ImageInput, AudioInput class VideoCodec(str, Enum): AUTO = "auto" diff --git a/comfy_api/util.py b/comfy_api/util.py index 7d342905d..1aa9606d2 100644 --- a/comfy_api/util.py +++ b/comfy_api/util.py @@ -1,2 +1,8 @@ # This file only exists for backwards compatibility. -from comfy_api.latest.util import * # noqa: F403 +from comfy_api.latest._util import VideoCodec, VideoContainer, VideoComponents + +__all__ = [ + "VideoCodec", + "VideoContainer", + "VideoComponents", +] diff --git a/comfy_api/util/__init__.py b/comfy_api/util/__init__.py index 7d342905d..4c8a89d1e 100644 --- a/comfy_api/util/__init__.py +++ b/comfy_api/util/__init__.py @@ -1,2 +1,8 @@ # This file only exists for backwards compatibility. -from comfy_api.latest.util import * # noqa: F403 +from comfy_api.latest._util import VideoContainer, VideoCodec, VideoComponents + +__all__ = [ + "VideoContainer", + "VideoCodec", + "VideoComponents", +] diff --git a/comfy_api/util/video_types.py b/comfy_api/util/video_types.py index 49fad6ff7..68c780d64 100644 --- a/comfy_api/util/video_types.py +++ b/comfy_api/util/video_types.py @@ -1,2 +1,12 @@ # This file only exists for backwards compatibility. -from comfy_api.latest.util.video_types import * # noqa: F403 +from comfy_api.latest._util.video_types import ( + VideoContainer, + VideoCodec, + VideoComponents, +) + +__all__ = [ + "VideoContainer", + "VideoCodec", + "VideoComponents", +] diff --git a/comfy_api/v0_0_1/__init__.py b/comfy_api/v0_0_1/__init__.py index 94750e966..ab6dc2b42 100644 --- a/comfy_api/v0_0_1/__init__.py +++ b/comfy_api/v0_0_1/__init__.py @@ -1,18 +1,34 @@ -from comfy_api.v0_0_2 import ComfyAPIAdapter_v0_0_2 +from comfy_api.v0_0_2 import ( + ComfyAPIAdapter_v0_0_2, + Input as Input_v0_0_2, + InputImpl as InputImpl_v0_0_2, + Types as Types_v0_0_2, +) from typing import Type, TYPE_CHECKING from comfy_api.internal.async_to_sync import create_sync_class + # This version only exists to serve as a template for future version adapters. # There is no reason anyone should ever use it. class ComfyAPIAdapter_v0_0_1(ComfyAPIAdapter_v0_0_2): VERSION = "0.0.1" STABLE = True +class Input(Input_v0_0_2): + pass + +class InputImpl(InputImpl_v0_0_2): + pass + +class Types(Types_v0_0_2): + pass + ComfyAPI = ComfyAPIAdapter_v0_0_1 # Create a synchronous version of the API if TYPE_CHECKING: - from comfy_api.v0_0_1.generated.ComfyAPISyncStub import ComfyAPISyncStub # type: ignore + from comfy_api.v0_0_1.generated.ComfyAPISyncStub import ComfyAPISyncStub # type: ignore + ComfyAPISync: Type[ComfyAPISyncStub] ComfyAPISync = create_sync_class(ComfyAPIAdapter_v0_0_1) diff --git a/comfy_api/v0_0_2/__init__.py b/comfy_api/v0_0_2/__init__.py index 90ca77e42..1b68bcc97 100644 --- a/comfy_api/v0_0_2/__init__.py +++ b/comfy_api/v0_0_2/__init__.py @@ -1,15 +1,35 @@ -from comfy_api.latest import ComfyAPI_latest +from comfy_api.latest import ( + ComfyAPI_latest, + Input as Input_latest, + InputImpl as InputImpl_latest, + Types as Types_latest, +) from typing import Type, TYPE_CHECKING from comfy_api.internal.async_to_sync import create_sync_class + class ComfyAPIAdapter_v0_0_2(ComfyAPI_latest): VERSION = "0.0.2" STABLE = False + +class Input(Input_latest): + pass + + +class InputImpl(InputImpl_latest): + pass + + +class Types(Types_latest): + pass + + ComfyAPI = ComfyAPIAdapter_v0_0_2 # Create a synchronous version of the API if TYPE_CHECKING: - from comfy_api.v0_0_2.generated.ComfyAPISyncStub import ComfyAPISyncStub # type: ignore + from comfy_api.v0_0_2.generated.ComfyAPISyncStub import ComfyAPISyncStub # type: ignore + ComfyAPISync: Type[ComfyAPISyncStub] ComfyAPISync = create_sync_class(ComfyAPIAdapter_v0_0_2) diff --git a/comfy_extras/nodes_video.py b/comfy_extras/nodes_video.py index 9f87a57ba..969f888b9 100644 --- a/comfy_extras/nodes_video.py +++ b/comfy_extras/nodes_video.py @@ -8,9 +8,7 @@ import json from typing import Optional, Literal from fractions import Fraction from comfy.comfy_types import IO, FileLocator, ComfyNodeABC -from comfy_api.latest.input import ImageInput, AudioInput, VideoInput -from comfy_api.latest.util import VideoContainer, VideoCodec, VideoComponents -from comfy_api.latest.input_impl import VideoFromFile, VideoFromComponents +from comfy_api.latest import Input, InputImpl, Types from comfy.cli_args import args class SaveWEBM: @@ -91,8 +89,8 @@ class SaveVideo(ComfyNodeABC): "required": { "video": (IO.VIDEO, {"tooltip": "The video to save."}), "filename_prefix": ("STRING", {"default": "video/ComfyUI", "tooltip": "The prefix for the file to save. This may include formatting information such as %date:yyyy-MM-dd% or %Empty Latent Image.width% to include values from nodes."}), - "format": (VideoContainer.as_input(), {"default": "auto", "tooltip": "The format to save the video as."}), - "codec": (VideoCodec.as_input(), {"default": "auto", "tooltip": "The codec to use for the video."}), + "format": (Types.VideoContainer.as_input(), {"default": "auto", "tooltip": "The format to save the video as."}), + "codec": (Types.VideoCodec.as_input(), {"default": "auto", "tooltip": "The codec to use for the video."}), }, "hidden": { "prompt": "PROMPT", @@ -108,7 +106,7 @@ class SaveVideo(ComfyNodeABC): CATEGORY = "image/video" DESCRIPTION = "Saves the input images to your ComfyUI output directory." - def save_video(self, video: VideoInput, filename_prefix, format, codec, prompt=None, extra_pnginfo=None): + def save_video(self, video: Input.Video, filename_prefix, format, codec, prompt=None, extra_pnginfo=None): filename_prefix += self.prefix_append width, height = video.get_dimensions() full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path( @@ -127,7 +125,7 @@ class SaveVideo(ComfyNodeABC): metadata["prompt"] = prompt if len(metadata) > 0: saved_metadata = metadata - file = f"{filename}_{counter:05}_.{VideoContainer.get_extension(format)}" + file = f"{filename}_{counter:05}_.{Types.VideoContainer.get_extension(format)}" video.save_to( os.path.join(full_output_folder, file), format=format, @@ -163,9 +161,9 @@ class CreateVideo(ComfyNodeABC): CATEGORY = "image/video" DESCRIPTION = "Create a video from images." - def create_video(self, images: ImageInput, fps: float, audio: Optional[AudioInput] = None): - return (VideoFromComponents( - VideoComponents( + def create_video(self, images: Input.Image, fps: float, audio: Optional[Input.Audio] = None): + return (InputImpl.VideoFromComponents( + Types.VideoComponents( images=images, audio=audio, frame_rate=Fraction(fps), @@ -187,7 +185,7 @@ class GetVideoComponents(ComfyNodeABC): CATEGORY = "image/video" DESCRIPTION = "Extracts all components from a video: frames, audio, and framerate." - def get_components(self, video: VideoInput): + def get_components(self, video: Input.Video): components = video.get_components() return (components.images, components.audio, float(components.frame_rate)) @@ -208,7 +206,7 @@ class LoadVideo(ComfyNodeABC): FUNCTION = "load_video" def load_video(self, file): video_path = folder_paths.get_annotated_filepath(file) - return (VideoFromFile(video_path),) + return (InputImpl.VideoFromFile(video_path),) @classmethod def IS_CHANGED(cls, file):