|
@@ -83,7 +83,9 @@ const configSchema = {
|
|
|
"title": "Image Input (img2img / image-edit)",
|
|
"title": "Image Input (img2img / image-edit)",
|
|
|
"fields": [
|
|
"fields": [
|
|
|
"initImageBase64",
|
|
"initImageBase64",
|
|
|
- "strength"
|
|
|
|
|
|
|
+ "strength",
|
|
|
|
|
+ "ipAdapterImageBase64",
|
|
|
|
|
+ "ipAdapterStrength"
|
|
|
]
|
|
]
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
@@ -121,7 +123,9 @@ const configSchema = {
|
|
|
"moeBoundary",
|
|
"moeBoundary",
|
|
|
"endImageBase64",
|
|
"endImageBase64",
|
|
|
"controlFrames",
|
|
"controlFrames",
|
|
|
- "vaceStrength"
|
|
|
|
|
|
|
+ "vaceStrength",
|
|
|
|
|
+ "refAudios",
|
|
|
|
|
+ "refVideos"
|
|
|
]
|
|
]
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
@@ -215,6 +219,10 @@ const configSchema = {
|
|
|
vaeTiling: { title: "VAE Tiling", description: "Per-generation override of the model-load `vae_tiling`. Process VAE encode/decode in tiles to reduce peak VRAM. Recommended: Enable for ≥2048 px outputs. Otherwise leave to the load-time default. Leave empty for the architecture default.", type: "boolean" },
|
|
vaeTiling: { title: "VAE Tiling", description: "Per-generation override of the model-load `vae_tiling`. Process VAE encode/decode in tiles to reduce peak VRAM. Recommended: Enable for ≥2048 px outputs. Otherwise leave to the load-time default. Leave empty for the architecture default.", type: "boolean" },
|
|
|
videoFrames: { title: "Video Frames", description: "Number of frames to generate (Wan / video models). Recommended: 33 for Wan 2.x (5-second clip @ 16 fps). Leave empty for the architecture default.", type: "number" },
|
|
videoFrames: { title: "Video Frames", description: "Number of frames to generate (Wan / video models). Recommended: 33 for Wan 2.x (5-second clip @ 16 fps). Leave empty for the architecture default.", type: "number" },
|
|
|
width: { title: "Width (px)", description: "Output image width in pixels. Must be divisible by the model's patch size (typically 8 or 16). Architectures have native resolutions they were trained at — going far off them can degrade quality. Recommended: Match the architecture's training resolution: SD1.5=512, SDXL=1024, Flux/SD3/Z-Image=1024, Wan video=832. Leave empty for the architecture default.", type: "number" },
|
|
width: { title: "Width (px)", description: "Output image width in pixels. Must be divisible by the model's patch size (typically 8 or 16). Architectures have native resolutions they were trained at — going far off them can degrade quality. Recommended: Match the architecture's training resolution: SD1.5=512, SDXL=1024, Flux/SD3/Z-Image=1024, Wan video=832. Leave empty for the architecture default.", type: "number" },
|
|
|
|
|
+ ipAdapterImageBase64: { title: "IP-Adapter Image (base64)", description: "A reference image whose style and subject guide the result, as base64. Needs an IP-Adapter loaded alongside the model - see the Load Model node. Recommended: Take it from a Download or Fetch Output node rather than pasting one in. Leave empty for the architecture default.", type: "string" },
|
|
|
|
|
+ ipAdapterStrength: { title: "IP-Adapter Strength", description: "How strongly the reference image guides the result. Recommended: 1.0 is the upstream default. Lower it when the reference is overwhelming the prompt. Leave empty for the architecture default.", type: "number" },
|
|
|
|
|
+ refAudios: { title: "Reference Audios", description: "Reference audio as base64-encoded WAV, mono or stereo PCM (i16/i24/i32/f32). Recommended: For models that take audio guidance. Leave empty for the architecture default.", type: "array", items: {"type": "string"} },
|
|
|
|
|
+ refVideos: { title: "Reference Videos", description: "Reference videos. Each entry is an object with frames (base64 images), fps (default 24) and an optional audio_wav_base64. Recommended: Built by an earlier node rather than typed. Leave empty for the architecture default.", type: "array", items: {"type": "object"} },
|
|
|
title: { type: "string", title: "Job Title", description: "Optional label stored with the job, useful for finding it again in the queue" },
|
|
title: { type: "string", title: "Job Title", description: "Optional label stored with the job, useful for finding it again in the queue" },
|
|
|
extraOptions: { type: "object", title: "Extra Options", description: "Any other generation field passed straight through. Everything the server documents already has a setting above, so this is only needed for a field a newer server has gained" },
|
|
extraOptions: { type: "object", title: "Extra Options", description: "Any other generation field passed straight through. Everything the server documents already has a setting above, so this is only needed for a field a newer server has gained" },
|
|
|
timeout: { type: "number", title: "Timeout (ms)", description: "Applies to queueing the job, not to the render. The call returns as soon as the job is accepted", default: 30000 }
|
|
timeout: { type: "number", title: "Timeout (ms)", description: "Applies to queueing the job, not to the render. The call returns as soon as the job is accepted", default: 30000 }
|
|
@@ -376,7 +384,11 @@ const GENERATION_OPTIONS = [
|
|
|
{ setting: "vaeTileSizeY", server: "vae_tile_size_y" },
|
|
{ setting: "vaeTileSizeY", server: "vae_tile_size_y" },
|
|
|
{ setting: "vaeTiling", server: "vae_tiling" },
|
|
{ setting: "vaeTiling", server: "vae_tiling" },
|
|
|
{ setting: "videoFrames", server: "video_frames" },
|
|
{ setting: "videoFrames", server: "video_frames" },
|
|
|
- { setting: "width", server: "width" }
|
|
|
|
|
|
|
+ { setting: "width", server: "width" },
|
|
|
|
|
+ { setting: "ipAdapterImageBase64", server: "ip_adapter_image_base64" },
|
|
|
|
|
+ { setting: "ipAdapterStrength", server: "ip_adapter_strength" },
|
|
|
|
|
+ { setting: "refAudios", server: "ref_audios" },
|
|
|
|
|
+ { setting: "refVideos", server: "ref_videos" }
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
async function execute(config, input, context) {
|
|
async function execute(config, input, context) {
|
|
@@ -398,8 +410,22 @@ async function execute(config, input, context) {
|
|
|
const option = GENERATION_OPTIONS[i];
|
|
const option = GENERATION_OPTIONS[i];
|
|
|
const value = config[option.setting];
|
|
const value = config[option.setting];
|
|
|
if (Array.isArray(value)) {
|
|
if (Array.isArray(value)) {
|
|
|
- if (value.length > 0) {
|
|
|
|
|
- body[option.server] = value;
|
|
|
|
|
|
|
+ // A list setting is usually filled with one entry holding an
|
|
|
|
|
+ // expression for a whole list from an earlier node, which arrives
|
|
|
|
|
+ // as a list inside a list. Left alone, the inner list is sent as a
|
|
|
|
|
+ // single item and the server sees one nonsense value instead of
|
|
|
|
|
+ // several - the same way a batch of two images once became one file
|
|
|
|
|
+ // named "a.png,b.png".
|
|
|
|
|
+ let flat = [];
|
|
|
|
|
+ for (let j = 0; j < value.length; j++) {
|
|
|
|
|
+ if (Array.isArray(value[j])) {
|
|
|
|
|
+ flat = flat.concat(value[j]);
|
|
|
|
|
+ } else if (value[j] !== undefined && value[j] !== null && value[j] !== '') {
|
|
|
|
|
+ flat.push(value[j]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (flat.length > 0) {
|
|
|
|
|
+ body[option.server] = flat;
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
putIfSet(body, option.server, value);
|
|
putIfSet(body, option.server, value);
|