Update Seedream 5 sizing behavior

This commit is contained in:
Alexander Tujicov
2026-07-09 22:23:11 +03:00
parent 7f46a2c4fe
commit d8df1a7635
2 changed files with 112 additions and 25 deletions
+11 -4
View File
@@ -21,6 +21,7 @@ A Custom Node that integrates [Fal.ai's](https://fal.ai) powerful image editing
| **Grok Imagine Edit** | `grok_imagine_edit` | xAI image edit model, up to 3 input images. |
| **Seedream 4.5** | `seedream_4.5` | ByteDance's model. Optimized for high-res editing. |
| **Seedream 5 Pro Edit** | `seedream_5` | ByteDance Seedream 5.0 Pro region-precise editing. |
| **Seedream 5 Lite Edit** | `seedream_5_lite` | ByteDance Seedream 5.0 Lite editing. |
| **Qwen Edit Plus** | `qwen_edit_plus` | Powerful instruction-based editing with guidance control. |
| **Flux 2 (Standard, Pro, Flex)** | `flux_2_edit` | (BFL) High-fidelity editing capabilities. |
| **Flux 2 Klein 9B Edit** | `flux_2_klein_9b_edit` | Fast FLUX.2 Klein 9B image editing model. |
@@ -85,15 +86,21 @@ Different models have different requirements implemented in the node:
4. **Seedream 5 Pro Edit (`seedream_5`)**:
* Supports up to **10 input images**.
* Uses `auto_2K` sizing unless custom width and height are provided.
* Custom total pixels must be between **1024x1024** and **2048x2048**.
* If `aspect_ratio` is not `auto`, the selected aspect ratio is prioritized and converted to Seedream's `image_size`.
* If `aspect_ratio` is `auto`, the selected `resolution` is mapped to Seedream's automatic size presets.
* Pro supports `auto_1K` and `auto_2K`; `4K` falls back to Pro's highest automatic preset.
5. **Nano Banana / Pro / 2**:
5. **Seedream 5 Lite Edit (`seedream_5_lite`)**:
* Supports up to **10 input images**.
* Uses the same aspect-ratio-first behavior as Seedream 5 Pro.
* Supports Lite automatic presets up to `auto_4K`.
6. **Nano Banana / Pro / 2**:
* These models rely on `aspect_ratio` and `resolution` settings rather than custom width/height integers.
* `nano_banana_2` supports `0.5K`, `1K`, `2K`, and `4K` resolution presets.
* `nano_banana_2` also supports extended aspect ratios: `4:1`, `1:4`, `8:1`, and `1:8`.
6. **Grok Imagine Edit (`grok_imagine_edit`)**:
7. **Grok Imagine Edit (`grok_imagine_edit`)**:
* Supports up to **3 input images**.
* Uses up to **4 output images**.
+101 -21
View File
@@ -1,12 +1,95 @@
import torch
import requests
import base64
import numpy as np
from io import BytesIO
from PIL import Image
# Helper function to convert ComfyUI tensor (B=1, H, W, C) to PIL Image (RGB)
def tensor2pil(image_tensor):
import numpy as np
from io import BytesIO
from PIL import Image
SEEDREAM_5_AUTO_IMAGE_SIZE_BY_RESOLUTION = {
"seedream_5": {
"0.5K": "auto_1K",
"1K": "auto_1K",
"2K": "auto_2K",
"4K": "auto_2K",
},
"seedream_5_pro": {
"0.5K": "auto_1K",
"1K": "auto_1K",
"2K": "auto_2K",
"4K": "auto_2K",
},
"seedream_5_lite": {
"0.5K": "auto_2K",
"1K": "auto_2K",
"2K": "auto_2K",
"4K": "auto_4K",
},
}
SEEDREAM_5_RESOLUTION_PIXELS = {
"seedream_5": {
"0.5K": 1024 * 1024,
"1K": 1024 * 1024,
"2K": 2048 * 2048,
"4K": 2048 * 2048,
},
"seedream_5_pro": {
"0.5K": 1024 * 1024,
"1K": 1024 * 1024,
"2K": 2048 * 2048,
"4K": 2048 * 2048,
},
"seedream_5_lite": {
"0.5K": 2560 * 1440,
"1K": 2560 * 1440,
"2K": 2048 * 2048,
"4K": 4096 * 4096,
},
}
def _round_to_multiple(value, multiple=8):
return max(multiple, int(round(value / multiple)) * multiple)
def seedream_5_image_size(aspect_ratio, resolution, model="seedream_5"):
auto_sizes = SEEDREAM_5_AUTO_IMAGE_SIZE_BY_RESOLUTION.get(
model,
SEEDREAM_5_AUTO_IMAGE_SIZE_BY_RESOLUTION["seedream_5"],
)
resolution_pixels = SEEDREAM_5_RESOLUTION_PIXELS.get(
model,
SEEDREAM_5_RESOLUTION_PIXELS["seedream_5"],
)
if aspect_ratio == "auto":
return auto_sizes.get(resolution, auto_sizes["2K"])
width_ratio, height_ratio = [int(part) for part in aspect_ratio.split(":", 1)]
ratio = width_ratio / height_ratio
target_pixels = resolution_pixels.get(resolution, resolution_pixels["2K"])
width = (target_pixels * ratio) ** 0.5
height = target_pixels / width
max_dimension = 4096
if width > max_dimension:
scale = max_dimension / width
width *= scale
height *= scale
if height > max_dimension:
scale = max_dimension / height
width *= scale
height *= scale
return {
"width": _round_to_multiple(width),
"height": _round_to_multiple(height),
}
# Helper function to convert ComfyUI tensor (B=1, H, W, C) to PIL Image (RGB)
def tensor2pil(image_tensor):
if image_tensor is None or image_tensor.shape[0] == 0:
return None
i = 255. * image_tensor[0].cpu().numpy() # (H, W, C)
@@ -52,7 +135,7 @@ class NanoSeedEdit:
return {
"required": {
"prompt": ("STRING", {"default": "Edit the image according to this prompt.", "multiline": True}),
"model": (["nano_banana", "nano_banana_pro", "nano_banana_2", "gpt_image_2_edit", "grok_imagine_edit", "seedream_4.5", "seedream_5", "qwen_edit_plus", "flux_2_edit", "flux_2_pro", "flux_2_flex", "flux_2_klein_9b_edit"],),
"model": (["nano_banana", "nano_banana_pro", "nano_banana_2", "gpt_image_2_edit", "grok_imagine_edit", "seedream_4.5", "seedream_5", "seedream_5_lite", "qwen_edit_plus", "flux_2_edit", "flux_2_pro", "flux_2_flex", "flux_2_klein_9b_edit"],),
"fal_key": ("STRING", {"default": "your_fal_key_here"}),
},
"optional": {
@@ -123,8 +206,8 @@ class NanoSeedEdit:
img_data_uris.append(img_data_uri)
# Enforce limits (Updated: Removed Flux 2 single image limit)
if model == "seedream_4.5" and len(img_data_uris) + num_images > 15:
raise ValueError("Seedream 4.5: Total inputs + outputs must <=15.")
if model in ["seedream_4.5", "seedream_5", "seedream_5_pro", "seedream_5_lite"] and len(img_data_uris) + num_images > 15:
raise ValueError("Seedream: Total inputs + outputs must <=15.")
# Model-specific payloads
if model == "nano_banana":
@@ -207,26 +290,23 @@ class NanoSeedEdit:
if not (3686400 <= area <= 16777216):
raise ValueError(f"Seedream 4.5: Image area must be 3,686,400-16,777,216px. Got {area}.")
payload["image_size"] = {"width": width, "height": height}
elif model == "seedream_5":
url = "https://fal.run/bytedance/seedream/v5/pro/edit"
elif model in ["seedream_5", "seedream_5_pro", "seedream_5_lite"]:
if model in ["seedream_5", "seedream_5_pro"]:
url = "https://fal.run/bytedance/seedream/v5/pro/edit"
else:
url = "https://fal.run/fal-ai/bytedance/seedream/v5/lite/edit"
payload = {
"prompt": prompt,
"image_urls": img_data_uris[:10],
"image_size": seedream_5_image_size(aspect_ratio, resolution, model),
"num_images": min(num_images, 6),
"output_format": "png",
"enable_safety_checker": False,
"sync_mode": True,
}
if custom_size:
area = width * height
aspect = width / height
if not (1048576 <= area <= 4194304):
raise ValueError(f"Seedream 5: Image area must be 1,048,576-4,194,304px. Got {area}.")
if not (1 / 16 <= aspect <= 16):
raise ValueError(f"Seedream 5: Aspect ratio must be between 1:16 and 16:1. Got {width}:{height}.")
payload["image_size"] = {"width": width, "height": height}
if model in ["seedream_5", "seedream_5_pro"]:
payload["output_format"] = "png"
else:
payload["image_size"] = "auto_2K"
payload["max_images"] = 1
elif model == "qwen_edit_plus":
url = "https://fal.run/fal-ai/qwen-image-edit-plus"
payload = {