Product Placement (Flux.2 Klein)
Drop in up to 3 product shots and a reference composition, and this workflow places your products into the scene with accurate label text, packaging detail, and lighting that matches the reference. Fully open source stack: Qwen3-VL reads your inputs and writes the edit prompt, Flux.2 Klein 9B handles the multi-image composite, and LTX-2.3 animates the final placement into a product spot. Batch concatenation and auto-scaling keep inputs sharp at any resolution. Runs on Comfy Cloud out of the box, or locally on your own hardware. No closed APIs.
About
This ComfyUI workflow automates realistic product placement using an open-source stack. You provide up to three product shots plus a reference composition, and the graph places the products into the scene with text-aware detail and lighting that follows the reference. A Qwen3-VL stage inspects your inputs and writes a context-rich edit prompt, Flux.2 Klein 9B performs the multi-image composite, and LTX-2.3 turns the final still into a short, polished product spot. Core utility nodes like LoadImage, PreviewImage, PreviewAny, BatchImagesNode, StringConcatenate, and SaveVideo make it easy to iterate and export.
Technically, the product and reference images are loaded, batched, and auto-scaled so Flux.2 Klein receives sharp, consistent inputs regardless of your source resolution. The prompt is assembled by Qwen3-VL (guided via StringConcatenate) and passed into the Flux.2 sampler to condition placement, label fidelity, and scene lighting.
After the composite is approved in PreviewImage/PreviewAny, LTX-2.3 generates a short motion segment from the final placement and SaveVideo writes the result to disk. The custom inference nodes (461b058e-342d-497e-aac1-a5fb6551e33a, fdd45ff8-8dff-43e8-b2c0-2d26053388b8, 6dbca6ef-ca4b-4af8-a99b-b834745f3a9b, 5c2c98c8-2e8f-47ca-9403-686e35a5ef94, 04e3b3b1-a711-485c-be05-f59f9507bd4e, ffacbfba-7659-45df-a3b8-7560f4800088) encapsulate the model runners and scaling/conditioning logic so you can run fully locally or on Comfy Cloud—no closed APIs.
What you provide
- Reading the workflow
Runs in ComfyUI. This workflow can't run on this page. Open it in Comfy Cloud with everything loaded, or download it for your own ComfyUI.
Try in CloudTry an example
Inside the workflow
A read-only preview of the node graph. Open it in Comfy Cloud or download it to edit the nodes.
Loading the graph
Open full-size workflow preview- Author
- Julien Durand | MJM
Requires custom nodes
- Reading the workflow
Use this workflow from code
Generated from the workflow graph and inputs when possible; stored examples are shown otherwise. Review credentials and endpoints before running code, which may incur charges.
What you need
- Runs on
- Comfy Cloud
- Key
- COMFY_API_KEY
Needs a paid Cloud plan and credits.
# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"1": {
"class_type": "LoadImage",
"inputs": {
"image": "product_1_product_placement.png"
},
"_meta": {
"title": "Load Image"
}
},
"2": {
"class_type": "LoadImage",
"inputs": {
"image": "560d57478ab8e80911888d2761ec1e84256eb5b8d773aa46a0beb40c0d5c74f9.png"
},
"_meta": {
"title": "Load Image"
}
},
"3": {
"class_type": "LoadImage",
"inputs": {
"image": "product_3_product_placement.png"
},
"_meta": {
"title": "Load Image"
}
},
"5": {
"class_type": "LoadImage",
"inputs": {
"image": "reference_image_product_placement.png"
},
"_meta": {
"title": "Load Image (Composition)"
}
},
"7": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"203:65",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"11": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"327:218",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"326": {
"class_type": "SaveVideo",
"inputs": {
"filename_prefix": "video/LTX_2.3_i2v",
"format": "auto",
"format.codec": "auto",
"video": [
"325:310",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"353": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"355:352",
1
]
},
"_meta": {
"title": "Preview as Text"
}
},
"354": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"355:351",
1
]
},
"_meta": {
"title": "Preview as Text"
}
},
"369": {
"class_type": "StringConcatenate",
"inputs": {
"delimiter": "",
"string_a": [
"373:372",
0
],
"string_b": [
"379:378",
0
]
},
"_meta": {
"title": "Concatenate Text"
}
},
"370": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"369",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"374": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"373:372",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"376": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"1",
0
],
"images.image1": [
"2",
0
],
"images.image2": [
"3",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"380": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"379:378",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"203:100": {
"class_type": "GetImageSize",
"inputs": {
"image": [
"203:80",
0
]
},
"_meta": {
"title": "Get Image Size"
}
},
"203:122": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"203:67",
0
],
"latent": [
"203:123",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"203:123": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"203:80",
0
],
"vae": [
"203:202",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"203:124": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"203:74",
0
],
"latent": [
"203:123",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"203:202": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "full_encoder_small_decoder.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"203:328": {
"class_type": "ImageScaleToTotalPixels",
"inputs": {
"image": [
"2",
0
],
"megapixels": 1,
"resolution_steps": 1,
"upscale_method": "lanczos"
},
"_meta": {
"title": "Scale Image to Total Pixels"
}
},
"203:329": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"203:122",
0
],
"latent": [
"203:330",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"203:330": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"203:328",
0
],
"vae": [
"203:202",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"203:331": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"203:124",
0
],
"latent": [
"203:330",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"203:332": {
"class_type": "ImageScaleToTotalPixels",
"inputs": {
"image": [
"3",
0
],
"megapixels": 1,
"resolution_steps": 1,
"upscale_method": "lanczos"
},
"_meta": {
"title": "Scale Image to Total Pixels"
}
},
"203:333": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"203:329",
0
],
"latent": [
"203:334",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"203:334": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"203:332",
0
],
"vae": [
"203:202",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"203:335": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"203:331",
0
],
"latent": [
"203:334",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"203:336": {
"class_type": "ImageScaleToTotalPixels",
"inputs": {
"image": [
"5",
0
],
"megapixels": 1,
"resolution_steps": 1,
"upscale_method": "lanczos"
},
"_meta": {
"title": "Scale Image to Total Pixels"
}
},
"203:337": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"203:333",
0
],
"latent": [
"203:338",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"203:338": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"203:336",
0
],
"vae": [
"203:202",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"203:339": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"203:335",
0
],
"latent": [
"203:338",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"203:61": {
"class_type": "KSamplerSelect",
"inputs": {
"sampler_name": "euler"
},
"_meta": {
"title": "KSamplerSelect"
}
},
"203:62": {
"class_type": "Flux2Scheduler",
"inputs": {
"height": [
"203:100",
1
],
"steps": 20,
"width": [
"203:100",
0
]
},
"_meta": {
"title": "Flux2Scheduler"
}
},
"203:63": {
"class_type": "CFGGuider",
"inputs": {
"cfg": 5,
"model": [
"203:70",
0
],
"negative": [
"203:337",
0
],
"positive": [
"203:339",
0
]
},
"_meta": {
"title": "CFG Guider"
}
},
"203:64": {
"class_type": "SamplerCustomAdvanced",
"inputs": {
"guider": [
"203:63",
0
],
"latent_image": [
"203:66",
0
],
"noise": [
"203:73",
0
],
"sampler": [
"203:61",
0
],
"sigmas": [
"203:62",
0
]
},
"_meta": {
"title": "SamplerCustomAdvanced"
}
},
"203:65": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"203:64",
0
],
"vae": [
"203:202",
0
]
},
"_meta": {
"title": "VAE Decode"
}
},
"203:66": {
"class_type": "EmptyFlux2LatentImage",
"inputs": {
"batch_size": 1,
"height": [
"203:100",
1
],
"width": [
"203:100",
0
]
},
"_meta": {
"title": "Empty Flux 2 Latent"
}
},
"203:67": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"203:71",
0
],
"text": ""
},
"_meta": {
"title": "CLIP Text Encode (Negative Prompt)"
}
},
"203:70": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "flux-2-klein-base-9b-fp8.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"203:71": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen_3_8b_fp8mixed.safetensors",
"device": "default",
"type": "flux2"
},
"_meta": {
"title": "Load CLIP"
}
},
"203:73": {
"class_type": "RandomNoise",
"inputs": {
"noise_seed": 1037480697784329
},
"_meta": {
"title": "RandomNoise"
}
},
"203:74": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"203:71",
0
],
"text": [
"369",
0
]
},
"_meta": {
"title": "CLIP Text Encode (Positive Prompt)"
}
},
"203:80": {
"class_type": "ImageScaleToTotalPixels",
"inputs": {
"image": [
"1",
0
],
"megapixels": 1,
"resolution_steps": 1,
"upscale_method": "lanczos"
},
"_meta": {
"title": "Scale Image to Total Pixels"
}
},
"325:276": {
"class_type": "RandomNoise",
"inputs": {
"noise_seed": 42
},
"_meta": {
"title": "RandomNoise"
}
},
"325:277": {
"class_type": "RandomNoise",
"inputs": {
"noise_seed": 305513163395821
},
"_meta": {
"title": "RandomNoise"
}
},
"325:278": {
"class_type": "LTXVConcatAVLatent",
"inputs": {
"audio_latent": [
"325:307",
1
],
"video_latent": [
"325:288",
0
]
},
"_meta": {
"title": "Concat AV Latent"
}
},
"325:279": {
"class_type": "LTXVAudioVAELoader",
"inputs": {
"ckpt_name": "ltx-2.3-22b-distilled-fp8.safetensors"
},
"_meta": {
"title": "Load LTXV Audio VAE"
}
},
"325:280": {
"class_type": "KSamplerSelect",
"inputs": {
"sampler_name": "euler_cfg_pp"
},
"_meta": {
"title": "KSamplerSelect"
}
},
"325:281": {
"class_type": "ManualSigmas",
"inputs": {
"sigmas": "0.85, 0.7250, 0.4219, 0.0"
},
"_meta": {
"title": "ManualSigmas"
}
},
"325:282": {
"class_type": "CFGGuider",
"inputs": {
"cfg": 1,
"model": [
"325:285",
0
],
"negative": [
"325:284",
1
],
"positive": [
"325:284",
0
]
},
"_meta": {
"title": "CFG Guider"
}
},
"325:283": {
"class_type": "SamplerCustomAdvanced",
"inputs": {
"guider": [
"325:314",
0
],
"latent_image": [
"325:318",
0
],
"noise": [
"325:277",
0
],
"sampler": [
"325:291",
0
],
"sigmas": [
"325:306",
0
]
},
"_meta": {
"title": "SamplerCustomAdvanced"
}
},
"325:284": {
"class_type": "LTXVCropGuides",
"inputs": {
"latent": [
"325:307",
0
],
"negative": [
"325:304",
1
],
"positive": [
"325:304",
0
]
},
"_meta": {
"title": "LTXVCropGuides"
}
},
"325:285": {
"class_type": "LoraLoaderModelOnly",
"inputs": {
"lora_name": "ltx-2.3-22b-distilled-lora-384-1.1.safetensors",
"model": [
"325:316",
0
],
"strength_model": 0.5
},
"_meta": {
"title": "Load LoRA"
}
},
"325:286": {
"class_type": "ResizeImagesByLongerEdge",
"inputs": {
"images": [
"325:290",
0
],
"longer_edge": 1536
},
"_meta": {
"title": "Resize Images by Longer Edge (DEPRECATED)"
}
},
"325:287": {
"class_type": "LTXVLatentUpsampler",
"inputs": {
"samples": [
"325:307",
0
],
"upscale_model": [
"325:311",
0
],
"vae": [
"325:316",
2
]
},
"_meta": {
"title": "LTXVLatentUpsampler"
}
},
"325:288": {
"class_type": "LTXVImgToVideoInplace",
"inputs": {
"bypass": [
"325:302",
0
],
"image": [
"325:289",
0
],
"latent": [
"325:287",
0
],
"strength": 1,
"vae": [
"325:316",
2
]
},
"_meta": {
"title": "LTXVImgToVideoInplace"
}
},
"325:289": {
"class_type": "LTXVPreprocess",
"inputs": {
"image": [
"325:286",
0
],
"img_compression": 18
},
"_meta": {
"title": "LTXV Preprocess"
}
},
"325:290": {
"class_type": "ResizeImageMaskNode",
"inputs": {
"input": [
"203:65",
0
],
"resize_type": "scale dimensions",
"resize_type.crop": "center",
"resize_type.height": [
"325:299",
0
],
"resize_type.width": [
"325:312",
0
],
"scale_method": "lanczos"
},
"_meta": {
"title": "Resize Image/Mask"
}
},
"325:291": {
"class_type": "KSamplerSelect",
"inputs": {
"sampler_name": "euler_ancestral_cfg_pp"
},
"_meta": {
"title": "KSamplerSelect"
}
},
"325:292": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "a/2",
"values.a": [
"325:312",
0
]
},
"_meta": {
"title": "Math Expression"
}
},
"325:294": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "a/2",
"values.a": [
"325:299",
0
]
},
"_meta": {
"title": "Math Expression"
}
},
"325:295": {
"class_type": "EmptyLTXVLatentVideo",
"inputs": {
"batch_size": 1,
"height": [
"325:294",
1
],
"length": [
"325:323",
1
],
"width": [
"325:292",
1
]
},
"_meta": {
"title": "Empty LTXV Latent Video"
}
},
"325:296": {
"class_type": "LTXVImgToVideoInplace",
"inputs": {
"bypass": [
"325:302",
0
],
"image": [
"325:289",
0
],
"latent": [
"325:295",
0
],
"strength": 0.7,
"vae": [
"325:316",
2
]
},
"_meta": {
"title": "LTXVImgToVideoInplace"
}
},
"325:297": {
"class_type": "LTXVAudioVAEDecode",
"inputs": {
"audio_vae": [
"325:279",
0
],
"samples": [
"325:309",
1
]
},
"_meta": {
"title": "LTXV Audio VAE Decode"
}
},
"325:298": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "a",
"values.a": [
"325:300",
0
]
},
"_meta": {
"title": "Math Expression"
}
},
"325:299": {
"class_type": "PrimitiveInt",
"inputs": {
"value": [
"355:352",
1
]
},
"_meta": {
"title": "Height"
}
},
"325:300": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 25
},
"_meta": {
"title": "Frame Rate"
}
},
"325:301": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 5
},
"_meta": {
"title": "Duration"
}
},
"325:302": {
"class_type": "PrimitiveBoolean",
"inputs": {
"value": False
},
"_meta": {
"title": "Switch to Text to Video?"
}
},
"325:303": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"325:317",
0
],
"text": [
"325:319",
0
]
},
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"325:304": {
"class_type": "LTXVConditioning",
"inputs": {
"frame_rate": [
"325:298",
0
],
"negative": [
"325:313",
0
],
"positive": [
"325:303",
0
]
},
"_meta": {
"title": "LTXVConditioning"
}
},
"325:305": {
"class_type": "LTXVEmptyLatentAudio",
"inputs": {
"audio_vae": [
"325:279",
0
],
"batch_size": 1,
"frame_rate": [
"325:298",
1
],
"frames_number": [
"325:323",
1
]
},
"_meta": {
"title": "Empty LTXV Latent Audio"
}
},
"325:306": {
"class_type": "ManualSigmas",
"inputs": {
"sigmas": "1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0"
},
"_meta": {
"title": "ManualSigmas"
}
},
"325:307": {
"class_type": "LTXVSeparateAVLatent",
"inputs": {
"av_latent": [
"325:283",
0
]
},
"_meta": {
"title": "Separate AV Latent"
}
},
"325:308": {
"class_type": "SamplerCustomAdvanced",
"inputs": {
"guider": [
"325:282",
0
],
"latent_image": [
"325:278",
0
],
"noise": [
"325:276",
0
],
"sampler": [
"325:280",
0
],
"sigmas": [
"325:281",
0
]
},
"_meta": {
"title": "SamplerCustomAdvanced"
}
},
"325:309": {
"class_type": "LTXVSeparateAVLatent",
"inputs": {
"av_latent": [
"325:308",
0
]
},
"_meta": {
"title": "Separate AV Latent"
}
},
"325:310": {
"class_type": "CreateVideo",
"inputs": {
"audio": [
"325:297",
0
],
"bit_depth": 8,
"codec": "none",
"color_space": "sRGB",
"fps": [
"325:298",
0
],
"images": [
"325:315",
0
]
},
"_meta": {
"title": "Create Video"
}
},
"325:311": {
"class_type": "LatentUpscaleModelLoader",
"inputs": {
"model_name": "ltx-2.3-spatial-upscaler-x2-1.1.safetensors"
},
"_meta": {
"title": "Load Latent Upscale Model"
}
},
"325:312": {
"class_type": "PrimitiveInt",
"inputs": {
"value": [
"355:351",
1
]
},
"_meta": {
"title": "Width"
}
},
"325:313": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"325:317",
0
],
"text": "pc game, console game, video game, cartoon, childish, ugly"
},
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"325:314": {
"class_type": "CFGGuider",
"inputs": {
"cfg": 1,
"model": [
"325:285",
0
],
"negative": [
"325:304",
1
],
"positive": [
"325:304",
0
]
},
"_meta": {
"title": "CFG Guider"
}
},
"325:315": {
"class_type": "VAEDecodeTiled",
"inputs": {
"overlap": 64,
"samples": [
"325:309",
0
],
"temporal_overlap": 4,
"temporal_size": 4096,
"tile_size": 768,
"vae": [
"325:316",
2
]
},
"_meta": {
"title": "VAE Decode (Tiled)"
}
},
"325:316": {
"class_type": "CheckpointLoaderSimple",
"inputs": {
"ckpt_name": "ltx-2.3-22b-distilled-fp8.safetensors"
},
"_meta": {
"title": "Load Checkpoint"
}
},
"325:317": {
"class_type": "LTXAVTextEncoderLoader",
"inputs": {
"ckpt_name": "ltx-2.3-22b-distilled-fp8.safetensors",
"device": "default",
"text_encoder": "gemma_3_12B_it_fp4_mixed.safetensors"
},
"_meta": {
"title": "Load LTXV Audio Text Encoder"
}
},
"325:318": {
"class_type": "LTXVConcatAVLatent",
"inputs": {
"audio_latent": [
"325:305",
0
],
"video_latent": [
"325:296",
0
]
},
"_meta": {
"title": "Concat AV Latent"
}
},
"325:319": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": [
"327:218",
0
]
},
"_meta": {
"title": "Prompt"
}
},
"325:323": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "a * b + 1",
"values.a": [
"325:301",
0
],
"values.b": [
"325:300",
0
]
},
"_meta": {
"title": "Math Expression (length)"
}
},
"327:217": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3vl_8b_nvfp4.safetensors",
"device": "default",
"type": "ideogram4"
},
"_meta": {
"title": "Load CLIP"
}
},
"327:218": {
"class_type": "TextGenerate",
"inputs": {
"clip": [
"327:217",
0
],
"image": [
"203:65",
0
],
"max_length": 512,
"mtp": "auto",
"prompt": "Write a prompt to create a realistic and dynamic motion for a video model based on this image\n\nGive me the prompt and nothing else",
"sampling_mode": "on",
"sampling_mode.min_p": 0.05,
"sampling_mode.presence_penalty": 0,
"sampling_mode.repetition_penalty": 1.05,
"sampling_mode.seed": 0,
"sampling_mode.temperature": 0.7,
"sampling_mode.top_k": 64,
"sampling_mode.top_p": 0.95,
"thinking": False,
"use_default_template": True
},
"_meta": {
"title": "Generate Text"
}
},
"355:350": {
"class_type": "GetImageSize",
"inputs": {
"image": [
"5",
0
]
},
"_meta": {
"title": "Get Image Size"
}
},
"355:351": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "720*(a/b < 0.75) + 1024*(a/b >= 0.75)*(a/b <= 4/3) + 1280*(a/b > 4/3)",
"values.a": [
"355:350",
0
],
"values.b": [
"355:350",
1
]
},
"_meta": {
"title": "Target WIDTH (use INT output, index 1)"
}
},
"355:352": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "1280*(a/b < 0.75) + 1024*(a/b >= 0.75)*(a/b <= 4/3) + 720*(a/b > 4/3)",
"values.a": [
"355:350",
0
],
"values.b": [
"355:350",
1
]
},
"_meta": {
"title": "Target HEIGHT (use INT output, index 1)"
}
},
"373:371": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3vl_8b_nvfp4.safetensors",
"device": "default",
"type": "ideogram4"
},
"_meta": {
"title": "Load CLIP"
}
},
"373:372": {
"class_type": "TextGenerate",
"inputs": {
"clip": [
"373:371",
0
],
"image": [
"5",
0
],
"max_length": 512,
"mtp": "auto",
"prompt": "You are writing the first half of an image editing prompt. Look at this\nphoto and describe the entire scene as a precise instruction, starting\nwith exactly: \"Create one full-frame photograph that fills the entire\ncanvas:\"A\n\nDescribe: the subject and pose (hand position, finger placement, how the\nitems are held or fanned), any accessories or jewelry, the background\nsurface and color, the lighting style, and the framing or crop.\n\nDo not describe the specific products being held. Refer to them only as\n\"three products\". They will be replaced.\n\nEnd with exactly this sentence: \"Replace the three products with the\nfollowing, each keeping its exact label text, colors and proportions:\"\n\nOutput only the prompt text. No commentary.",
"sampling_mode": "on",
"sampling_mode.min_p": 0.05,
"sampling_mode.presence_penalty": 0,
"sampling_mode.repetition_penalty": 1.05,
"sampling_mode.seed": 0,
"sampling_mode.temperature": 0.7,
"sampling_mode.top_k": 64,
"sampling_mode.top_p": 0.95,
"thinking": False,
"use_default_template": True
},
"_meta": {
"title": "Generate Text"
}
},
"379:377": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3vl_8b_nvfp4.safetensors",
"device": "default",
"type": "ideogram4"
},
"_meta": {
"title": "Load CLIP"
}
},
"379:378": {
"class_type": "TextGenerate",
"inputs": {
"clip": [
"379:377",
0
],
"image": [
"376",
0
],
"max_length": 512,
"mtp": "auto",
"prompt": "The input contains three product photos in order. Describe each one on its own line, in this exact format:\n\nProduct 1: shape, colors, material, and exact label text transcribed word for word.\nProduct 2: same format.\nProduct 3: same format.A\n\nOutput only these three lines. No introduction, no extra commentary.",
"sampling_mode": "on",
"sampling_mode.min_p": 0.05,
"sampling_mode.presence_penalty": 0,
"sampling_mode.repetition_penalty": 1.05,
"sampling_mode.seed": 0,
"sampling_mode.temperature": 0.7,
"sampling_mode.top_k": 64,
"sampling_mode.top_p": 0.95,
"thinking": False,
"use_default_template": True
},
"_meta": {
"title": "Generate Text"
}
}
})
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)Questions & answers
No. The workflow supports 1–3 products. Leave unused LoadImage nodes empty; the BatchImagesNode will process only the images you provide.
Use high-resolution product shots (ideally with clean, front-facing labels) and transparent PNGs if possible. Keep the reference image close to your target output resolution. If text or edges look soft, increase input resolution, refine the Qwen3-VL prompt via StringConcatenate, or reduce the final output size.
Yes. All stages run locally with open models (Qwen3-VL, Flux.2 Klein 9B, LTX-2.3) through the custom inference nodes (e.g., 461b058e…, fdd45ff8…, 6dbca6ef…, 5c2c98c8…, 04e3b3b1…, ffacbfba…). Ensure you have the model weights installed and paths set in the node settings.
Lower the working resolution, shorten the LTX-2.3 duration, or disable any unused image slots. You can also run the composite first at a smaller size, lock a good seed, then upscale for a final pass if your hardware allows.