Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ This node pack focuses on **image / video / edit** — see the full **[node cata
| Node | Model |
|------|-------|
| AtlasCloud InfiniteTalk Audio-to-Video | atlascloud/infinitetalk |
| AtlasCloud Sync Lipsync v3 | sync/lipsync-v3 |
| AtlasCloud VEED Lipsync | veed/lipsync |

### Text-to-Image (T2I)

Expand Down Expand Up @@ -354,6 +356,7 @@ This node pack focuses on **image / video / edit** — see the full **[node cata
| AtlasCloud Nano Banana 2 Text-to-Image Developer | google/nano-banana-2/text-to-image-developer |
| AtlasCloud Nano Banana 2 Lite Text-to-Image | google/nano-banana-2-lite/text-to-image |
| AtlasCloud Nano Banana 2 Lite Text-to-Image Developer | google/nano-banana-2-lite/text-to-image-developer |
| AtlasCloud HiDream O1 1.5 Text-to-Image | hidream-o1-1.5/text-to-image |
| AtlasCloud Nano Banana Pro Text-to-Image Ultra | google/nano-banana-pro/text-to-image-ultra |
| AtlasCloud Nano Banana Pro Text-to-Image | google/nano-banana-pro/text-to-image |
| AtlasCloud Nano Banana Pro Text-to-Image Developer | google/nano-banana-pro/text-to-image-developer |
Expand Down Expand Up @@ -414,6 +417,7 @@ This node pack focuses on **image / video / edit** — see the full **[node cata
| AtlasCloud Nano Banana 2 Edit Developer | google/nano-banana-2/edit-developer |
| AtlasCloud Nano Banana 2 Lite Edit | google/nano-banana-2-lite/edit |
| AtlasCloud Nano Banana 2 Lite Edit Developer | google/nano-banana-2-lite/edit-developer |
| AtlasCloud HiDream O1 1.5 Edit | hidream-o1-1.5/edit |
| AtlasCloud Nano Banana 2 Reference-to-Image | google/nano-banana-2/reference-to-image |
| AtlasCloud Nano Banana 2 Reference-to-Image Developer | google/nano-banana-2/reference-to-image-developer |
| AtlasCloud Seedream V5.0 Lite Edit | bytedance/seedream-v5.0-lite/edit |
Expand Down
87 changes: 87 additions & 0 deletions src/atlascloud_comfyui/nodes/image/hidream_o1_15_edit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from __future__ import annotations

from typing import Any, Dict, List, Tuple

from ..auth.atlas_client_node import AtlasClientHandle

_IMAGE_SIZES = [
"square_hd",
"square",
"portrait_3_4",
"portrait_9_16",
"landscape_4_3",
"landscape_16_9",
]


class AtlasHiDreamO115Edit:
CATEGORY = "AtlasCloud/Image"
FUNCTION = "run"
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("image_url", "prediction_id")

@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"atlas_client": ("ATLAS_CLIENT",),
"image": ("STRING", {"default": "", "tooltip": "Input image URL(s) or base64 to edit, ONE PER LINE"}),
"prompt": ("STRING", {"multiline": True, "tooltip": "Text prompt for editing (max 2500 chars)"}),
"image_size": (_IMAGE_SIZES, {"default": "landscape_4_3", "tooltip": "Output image size preset"}),
"num_inference_steps": ("INT", {"default": 50, "min": 1, "max": 100, "tooltip": "Denoising steps"}),
"guidance_scale": ("FLOAT", {"default": 5.0, "min": 1.0, "max": 20.0, "tooltip": "Guidance scale"}),
"output_format": (["png", "jpeg", "webp"], {"default": "png", "tooltip": "Output format"}),
},
"optional": {
"poll_interval_sec": ("FLOAT", {"default": 2.0, "min": 0.5, "max": 10.0, "tooltip": "Polling interval (seconds)"}),
"timeout_sec": ("INT", {"default": 300, "min": 30, "max": 7200, "tooltip": "Timeout (seconds)"}),
},
}

def run(
self,
atlas_client: AtlasClientHandle,
image: str,
prompt: str,
image_size: str,
num_inference_steps: int,
guidance_scale: float,
output_format: str,
poll_interval_sec: float = 2.0,
timeout_sec: int = 300,
) -> Tuple[str, str]:
client = atlas_client.client

p = (prompt or "").strip()
if not p:
raise RuntimeError("prompt is required")

image = (image or "").strip()
if not image:
raise RuntimeError("image is required (URL or base64)")

# Split on newlines, NOT commas: base64 data URLs contain a comma.
refs: List[str] = [u.strip() for u in image.splitlines() if u.strip()]

payload: Dict[str, Any] = {
"model": "hidream-o1-1.5/edit",
"prompt": p,
"reference_image_urls": refs,
"image_size": image_size,
"num_inference_steps": int(num_inference_steps),
"guidance_scale": float(guidance_scale),
"output_format": output_format,
}

prediction_id = client.generate_image(payload)
result = client.poll_prediction(
prediction_id,
poll_interval_sec=poll_interval_sec,
timeout_sec=float(timeout_sec),
)

outputs = (result.get("data") or {}).get("outputs") or []
if not outputs:
raise RuntimeError(f"No outputs returned for prediction {prediction_id}: {result}")

return (outputs[0], prediction_id)
83 changes: 83 additions & 0 deletions src/atlascloud_comfyui/nodes/image/hidream_o1_15_t2i.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from __future__ import annotations

from typing import Any, Dict, List, Tuple

from ..auth.atlas_client_node import AtlasClientHandle

_IMAGE_SIZES = [
"square_hd",
"square",
"portrait_3_4",
"portrait_9_16",
"landscape_4_3",
"landscape_16_9",
]


class AtlasHiDreamO115TextToImage:
CATEGORY = "AtlasCloud/Image"
FUNCTION = "run"
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("image_url", "prediction_id")

@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"atlas_client": ("ATLAS_CLIENT",),
"prompt": ("STRING", {"multiline": True, "tooltip": "Text prompt (max 2500 chars)"}),
"image_size": (_IMAGE_SIZES, {"default": "landscape_4_3", "tooltip": "Output image size preset"}),
"num_inference_steps": ("INT", {"default": 50, "min": 1, "max": 100, "tooltip": "Denoising steps"}),
"guidance_scale": ("FLOAT", {"default": 5.0, "min": 1.0, "max": 20.0, "tooltip": "Guidance scale"}),
"output_format": (["png", "jpeg", "webp"], {"default": "png", "tooltip": "Output format"}),
},
"optional": {
"reference_image_urls": ("STRING", {"multiline": True, "default": "", "tooltip": "Optional reference image URLs for subject-driven personalization, ONE PER LINE"}),
"poll_interval_sec": ("FLOAT", {"default": 2.0, "min": 0.5, "max": 10.0, "tooltip": "Polling interval (seconds)"}),
"timeout_sec": ("INT", {"default": 300, "min": 30, "max": 7200, "tooltip": "Timeout (seconds)"}),
},
}

def run(
self,
atlas_client: AtlasClientHandle,
prompt: str,
image_size: str,
num_inference_steps: int,
guidance_scale: float,
output_format: str,
reference_image_urls: str = "",
poll_interval_sec: float = 2.0,
timeout_sec: int = 300,
) -> Tuple[str, str]:
client = atlas_client.client

p = (prompt or "").strip()
if not p:
raise RuntimeError("prompt is required")

payload: Dict[str, Any] = {
"model": "hidream-o1-1.5/text-to-image",
"prompt": p,
"image_size": image_size,
"num_inference_steps": int(num_inference_steps),
"guidance_scale": float(guidance_scale),
"output_format": output_format,
}

refs: List[str] = [u.strip() for u in (reference_image_urls or "").splitlines() if u.strip()]
if refs:
payload["reference_image_urls"] = refs

prediction_id = client.generate_image(payload)
result = client.poll_prediction(
prediction_id,
poll_interval_sec=poll_interval_sec,
timeout_sec=float(timeout_sec),
)

outputs = (result.get("data") or {}).get("outputs") or []
if not outputs:
raise RuntimeError(f"No outputs returned for prediction {prediction_id}: {result}")

return (outputs[0], prediction_id)
65 changes: 65 additions & 0 deletions src/atlascloud_comfyui/nodes/video/sync_lipsync_v3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from __future__ import annotations

from typing import Any, Dict, Tuple

from ..auth.atlas_client_node import AtlasClientHandle


class AtlasSyncLipsyncV3:
CATEGORY = "AtlasCloud/Video"
FUNCTION = "run"
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("video_url", "prediction_id")

@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"atlas_client": ("ATLAS_CLIENT",),
"video": ("STRING", {"default": "", "tooltip": "Input video URL/base64 whose lips will be re-synced (mp4/mov/webm)"}),
"audio": ("STRING", {"default": "", "tooltip": "Driving audio URL/base64 to sync lips to (wav/mp3/m4a)"}),
"sync_mode": (
["cut_off", "loop", "bounce", "silence", "remap"],
{"default": "cut_off", "tooltip": "How to handle video/audio duration mismatch"},
),
},
"optional": {
"poll_interval_sec": ("FLOAT", {"default": 2.0, "min": 0.5, "max": 10.0, "tooltip": "Polling interval (seconds)"}),
"timeout_sec": ("INT", {"default": 900, "min": 30, "max": 7200, "tooltip": "Timeout (seconds)"}),
},
}

def run(
self,
atlas_client: AtlasClientHandle,
video: str,
audio: str,
sync_mode: str,
poll_interval_sec: float = 2.0,
timeout_sec: int = 900,
) -> Tuple[str, str]:
video = (video or "").strip()
if not video:
raise RuntimeError("video is required (URL or base64)")

audio = (audio or "").strip()
if not audio:
raise RuntimeError("audio is required (URL or base64)")

client = atlas_client.client

payload: Dict[str, Any] = {
"model": "sync/lipsync-v3",
"video_url": video,
"audio_url": audio,
"sync_mode": sync_mode,
}

prediction_id = client.generate_video(payload)
result = client.poll_prediction(prediction_id, poll_interval_sec=poll_interval_sec, timeout_sec=float(timeout_sec))

outputs = (result.get("data") or {}).get("outputs") or []
if not outputs:
raise RuntimeError(f"No outputs returned for prediction {prediction_id}: {result}")

return (outputs[0], prediction_id)
59 changes: 59 additions & 0 deletions src/atlascloud_comfyui/nodes/video/veed_lipsync.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from __future__ import annotations

from typing import Any, Dict, Tuple

from ..auth.atlas_client_node import AtlasClientHandle


class AtlasVeedLipsync:
CATEGORY = "AtlasCloud/Video"
FUNCTION = "run"
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("video_url", "prediction_id")

@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"atlas_client": ("ATLAS_CLIENT",),
"video": ("STRING", {"default": "", "tooltip": "Input talking-head video URL/base64 to re-lipsync (mp4/mov/webm)"}),
"audio": ("STRING", {"default": "", "tooltip": "Driving audio URL/base64 (wav/mp3/m4a)"}),
},
"optional": {
"poll_interval_sec": ("FLOAT", {"default": 2.0, "min": 0.5, "max": 10.0, "tooltip": "Polling interval (seconds)"}),
"timeout_sec": ("INT", {"default": 900, "min": 30, "max": 7200, "tooltip": "Timeout (seconds)"}),
},
}

def run(
self,
atlas_client: AtlasClientHandle,
video: str,
audio: str,
poll_interval_sec: float = 2.0,
timeout_sec: int = 900,
) -> Tuple[str, str]:
video = (video or "").strip()
if not video:
raise RuntimeError("video is required (URL or base64)")

audio = (audio or "").strip()
if not audio:
raise RuntimeError("audio is required (URL or base64)")

client = atlas_client.client

payload: Dict[str, Any] = {
"model": "veed/lipsync",
"video_url": video,
"audio_url": audio,
}

prediction_id = client.generate_video(payload)
result = client.poll_prediction(prediction_id, poll_interval_sec=poll_interval_sec, timeout_sec=float(timeout_sec))

outputs = (result.get("data") or {}).get("outputs") or []
if not outputs:
raise RuntimeError(f"No outputs returned for prediction {prediction_id}: {result}")

return (outputs[0], prediction_id)
12 changes: 12 additions & 0 deletions src/atlascloud_comfyui/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@
from atlascloud_comfyui.nodes.image.nano_banana2_lite_t2i_dev import AtlasNanoBanana2LiteTextToImageDev
from atlascloud_comfyui.nodes.image.nano_banana2_lite_edit import AtlasNanoBanana2LiteEdit
from atlascloud_comfyui.nodes.image.nano_banana2_lite_edit_dev import AtlasNanoBanana2LiteEditDev
from atlascloud_comfyui.nodes.image.hidream_o1_15_t2i import AtlasHiDreamO115TextToImage
from atlascloud_comfyui.nodes.image.hidream_o1_15_edit import AtlasHiDreamO115Edit
from atlascloud_comfyui.nodes.video.sync_lipsync_v3 import AtlasSyncLipsyncV3
from atlascloud_comfyui.nodes.video.veed_lipsync import AtlasVeedLipsync
from atlascloud_comfyui.nodes.image.seedream_v50_lite_t2i import AtlasSeedreamV50LiteTextToImage
from atlascloud_comfyui.nodes.image.seedream_v50_lite_edit import AtlasSeedreamV50LiteEdit
from atlascloud_comfyui.nodes.image.seedream_v50_lite_sequential_t2i import AtlasSeedreamV50LiteSequentialTextToImage
Expand Down Expand Up @@ -495,6 +499,10 @@
"AtlasCloud Nano Banana 2 Lite Text-to-Image Developer": AtlasNanoBanana2LiteTextToImageDev,
"AtlasCloud Nano Banana 2 Lite Edit": AtlasNanoBanana2LiteEdit,
"AtlasCloud Nano Banana 2 Lite Edit Developer": AtlasNanoBanana2LiteEditDev,
"AtlasCloud HiDream O1 1.5 Text-to-Image": AtlasHiDreamO115TextToImage,
"AtlasCloud HiDream O1 1.5 Edit": AtlasHiDreamO115Edit,
"AtlasCloud Sync Lipsync v3": AtlasSyncLipsyncV3,
"AtlasCloud VEED Lipsync": AtlasVeedLipsync,
"AtlasCloud Seedream V5.0 Lite Text-to-Image": AtlasSeedreamV50LiteTextToImage,
"AtlasCloud Seedream V5.0 Lite Sequential Text-to-Image": AtlasSeedreamV50LiteSequentialTextToImage,
"AtlasCloud Seedream V5.0 Lite Edit": AtlasSeedreamV50LiteEdit,
Expand Down Expand Up @@ -1020,6 +1028,10 @@
"AtlasCloud FLUX.2 Pro Edit": "AtlasCloud FLUX.2 Pro Edit",
"AtlasCloud Grok Imagine Video Edit": "AtlasCloud Grok Imagine Video Edit",
"AtlasCloud Grok Imagine Video Extend": "AtlasCloud Grok Imagine Video Extend",
"AtlasCloud HiDream O1 1.5 Text-to-Image": "AtlasCloud HiDream O1 1.5 Text-to-Image",
"AtlasCloud HiDream O1 1.5 Edit": "AtlasCloud HiDream O1 1.5 Edit",
"AtlasCloud Sync Lipsync v3": "AtlasCloud Sync Lipsync v3",
"AtlasCloud VEED Lipsync": "AtlasCloud VEED Lipsync",
}


Expand Down
Loading
Loading