arkennemasis fal · Flux Kontext LoRA Inpaint · $0.035/image
Mask plus instruction, from one reference
- image
- reference_image
- mask
- images
- image_paths
- timings
- has_nsfw_concepts
- seed
- prompt
- info
Most inpaint nodes give you a mask and a prompt. This one gives you a mask, a prompt, and a second reference image - so "paint over the plain shirt and make it this jacket from this photo" is one call rather than an img2img chain you assembled by hand.
It's the Kontext LoRA endpoint's inpainting mode, at $0.035 per megapixel - about three and a half cents at a square megapixel.
The three inputs that matter
image - required. The picture being inpainted. Up to 14142px per side by fal's documented limits.
mask - required, and it's a real ComfyUI MASK, not a URL. Paint it in the mask editor or wire a segmentation node into it. The pack uploads it as a PNG sized to match your first image, so proportions are handled for you - but only if the mask actually belongs to the image you connected.
reference_image - required, and this is the interesting one. It's the source for what goes into the masked area. Want the jacket from photo B on the person in photo A? A goes in image, the mask covers the torso, B goes in reference_image, and the prompt says "replace the shirt with this jacket". That's the difference between this node and every plain inpaint endpoint: the reference gives the model a real thing to copy rather than a description to imagine.
strength defaults to 0.88 - the tooltip repeats the family's definition, higher values are better for this model. Same warning as everywhere else in this pack: 0.88 is aggressive, and if you're patching a detail you'll want it lower. The usual bands apply - 0.3–0.6 for a change inside the mask with the surroundings intact, 0.6–0.8 for a substantial replacement, 0.85+ for effectively generating a new thing in the hole.
loras is the JSON field for extra Kontext LoRAs, merged together, and it takes URLs fal can fetch - not files from your local ComfyUI folder. Empty leaves it out.
The rest
prompt is the instruction for the masked region, and unlike the sibling Kontext editing nodes there's no resolution_mode field here - nothing to pick, nothing to match. acceleration at none, num_inference_steps 30, guidance_scale 2.5 (Flux guidance - not CFG; this is guidance-distilled so cranking it burns the image rather than increasing adherence), seed -1, num_images, enable_safety_checker on, output_format png.
Outputs
images and image_paths (files land in output/fal/fal-ai_flux-kontext-lora_inpaint/), plus timings, has_nsfw_concepts, seed, prompt, and info - request id, cost estimate, saved files, fal's full answer.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Hishamahmer/comfyui-arkennemasis
Restart ComfyUI, or use ComfyUI-Manager → Install via Git URL. The pack's requirements.txt declares a single dependency, httpx, and it exists for the pack's Codex nodes; the fal provider runs on Python's standard library. No weights download, no VRAM used.
FAL_KEY=your-key-from-fal.ai/dashboard/keys
goes in the .env next to run_nvidia_gpu.bat in the portable build (or your ComfyUI folder). There's no key field on this node, deliberately - a key in a widget gets written into every workflow you export.
The honest expectation-setting
The mask here is a guide, not a contract. The endpoint generates a frame with your mask directing where the ink goes, so pixels outside it come back close, not identical. If you need provably untouched regions, the only way is the local route: generate, then composite the masked region back over your original in ComfyUI. That's the one thing masks give you that no round trip to an API can.
That caveat aside, mask-plus-reference is genuinely useful, and it's a combination the instruction-editing models can't do. "Change the jacket" works from a sentence - but the sentence can't hand the model a photograph of the specific jacket. Adding a second reference is exactly where mask-based editing still earns its keep: the jacket's cut, stitching and colour come from real pixels.
There's a second reason to keep this in the toolkit. Whole-frame editing drifts the rest of the picture a little on each pass, and it compounds if you chain edits. Doing the change inside a mask, with a reference, keeps each edit local.
Cost and the two toggles
$0.035/MP - 1024×1024 ≈ 3.5¢, a 2048-wide landscape ≈ 14¢, with the node's price badge tracking num_images. max_cost_usd (default $20, 0 removes the cap) refuses the run before upload when the estimate crosses it.
reuse_identical_run defaults on and compares the settings and the bytes of everything you connected - image, mask and reference. Re-queuing an unchanged job returns the file you already paid for instead of billing again. That's a gift while you're wiring the graph and a puzzle the first time you queue a re-run expecting a different roll. max_concurrent (default 1) keeps paid fal calls serialised across the run; raise it (up to 32) when you deliberately want several going at once, and note that once any fal node in the run fails, the ones still waiting never start.
When it misbehaves
The replacement ignored my reference. Check the mask covers enough of the target area - a mask that clips the shoulders tells the model not to touch them. Raise strength if the original is bleeding through.
A visible seam at the mask edge. Lower strength, and feather the mask. Hard-edged masks plus high denoise is how you get a patch that looks pasted on.
A small masked area came out mushy. Resolution, not the model: the whole frame shares the generation budget, so a 60-pixel region inside a 1024px image has almost nothing to spend. Crop, render big, paste back.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | The URL of the image to be inpainted. | |
| prompt | STRING | The prompt for the image to image task. | |
| num_inference_steps | INT | 3010–50 | The number of inference steps to perform. |
| seed | INT | -1-1–2147483647 | The same seed and the same prompt given to the same version of the model will output the same image every time. -1 leaves it to the model. |
| guidance_scale | FLOAT | 2.500–20 | The CFG (Classifier Free Guidance) scale is a measure of how close you want the model to stick to your prompt when looking for a related image to show you. |
| num_images | INT | 11–4 | The number of images to generate. |
| enable_safety_checker | BOOLEAN | true | If set to true, the safety checker will be enabled. Disabling it requires account authorization; unauthorized requests are always checked, and images flagged as unsafe are returned as black images. |
| output_format | COMBO | png | The format of the generated image. |
| loras | STRING | The LoRAs to use for the image generation. You can use any number of LoRAs and they will be merged together to generate the final image. JSON. Empty leaves it out. | |
| acceleration | COMBO | none | The speed of the generation. The higher the speed, the faster the generation. |
| reference_image | IMAGE | The URL of the reference image for inpainting. | |
| mask | MASK | The URL of the mask for inpainting. | |
| strength | FLOAT | 0.880.01–1 | The strength of the initial image. Higher strength values are better for this model. |
| max_cost_usdopt | FLOAT | 20.00–100000 | Safety cap. If the estimated cost of this run is above this many US dollars the node stops BEFORE sending anything to fal. 0 = no cap. |
| reuse_identical_runopt | BOOLEAN | true | If these exact inputs (the settings AND the same pictures/clips/audio) were already paid for and the files are still in output/fal, return them instead of paying again - also after a ComfyUI restart. Turn off for a fresh take with the same settings. |
| extra_jsonopt | STRING | Advanced: a JSON object merged into the request last, for any fal field this node has no box for. Example: {"seed": 7}. Leave empty normally. | |
| max_concurrentopt | INT | 11–32 | How many paid fal calls may run at the same time in one run, across every fal node. 1 (default) = one after another. This node starts its paid part only while fewer than this many fal calls are running. Once any fal node fails, the ones still waiting are not started, so nothing more is billed. |
Outputs (7)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| image_paths | STRING | — |
| timings | STRING | — |
| has_nsfw_concepts | STRING | — |
| seed | INT | — |
| prompt | STRING | — |
| info | STRING | JSON: request id, cost estimate, saved files and fal's full answer. |