Overview

FUK (Framework for Unified Kreation) is a local-first AI rendering pipeline built for professionals. It provides a structured, stable environment for image and video generation that integrates cleanly into existing production pipelines. With direct integration with profesional applications in active development. Without telemetry, cloud dependencies, or workflows designed around consumer use cases.

FUK runs entirely on your hardware. Models, outputs, and project data stay on your machine.

Design Philosophy

Most AI generation tools are built around exploration, quick iterations, no project structure. FUK is built around production. Every output lives in a project/shot/version hierarchy. Every generation captures complete metadata. Nothing is ephemeral unless you want it to be.

The pipeline is intentionally minimal in its interface and maximal in its output. Controls are exposed where they matter. Defaults are sane. The housekeeping (spec compliance, versioning, metadata, handoff between tools) is automated so it never becomes your job. The goal isn’t to hide what’s under the hood. It’s to stop making you rebuild it every time you need a shot. Complexity isn’t sophistication, and the less time you spend in FUK, the more time you spend on the work.

What FUK Is Not

  • Not a cloud service — no API keys, no usage limits, no data leaving your machine
  • Not a consumer tool — designed for pipeline integration, not social sharing
  • Not a model trainer — FUK generates; training happens in dedicated tools
  • Not locked to one model family — new pipelines can be added via configuration

FUK is in active development. Core generation is stable. AOV outputs are functional but being refined. See the roadmap section on the main page for current focus areas.

Installation

▶ Video breakdown — coming soon

Planned: A simpler install is in the works. It will be a single fuk command built on uv, which manages Python and picks the right CUDA build of PyTorch for you, plus fuk doctor to point out exactly what's broken. Native Windows will work without WSL or admin rights.

Prerequisites

  • Python 3.10+
  • CUDA 11.8+ (NVIDIA) or compatible AMD drivers
  • Git
  • FFmpeg

Steps

  1. Clone the repository:
    git clone https://github.com/CastleGreyscale/FUK
  2. Install dependencies:
    pip install -e .
  3. Run setup:
    chmod +x setup.sh && ./setup.sh
  4. Set model root — edit config/defaults.json and set the model root directory to wherever your models live
  5. Launch FUK:
    ./start.sh
  6. Download models from Utilities → Models. See the Model Manager

For headless installs, ./download_models.sh still works. It downloads everything listed in config/models.json, so remove unwanted entries first.

If Model Downloads Are Slow

Models come from one of two hosts. DiffSynth defaults to ModelScope, which is often slow and prone to dropped connections outside China. Most models are also on HuggingFace, which is usually far faster. The Model Manager already prefers HuggingFace; for the script, set it explicitly:

DIFFSYNTH_DOWNLOAD_SOURCE=huggingface ./download_models.sh

A few repositories exist only on ModelScope — the PAI/* models and DiffSynth-Studio's converted Wan safetensors. The downloader falls back per component, so either choice completes; those specific files just come over the slower link.

Downloading by hand. If the terminal download crawls along at under 1MB/s or keeps failing, fetching the files through a web browser is a perfectly good alternative and is often dramatically faster. The only requirement is that files land where FUK expects them:

<models_root>/<model_id>/<pattern>

So models_t5_umt5-xxl-enc-bf16.safetensors from DiffSynth-Studio/Wan-Series-Converted-Safetensors belongs at:

<models_root>/DiffSynth-Studio/Wan-Series-Converted-Safetensors/models_t5_umt5-xxl-enc-bf16.safetensors

Watch for subdirectories. The Wan A14B models keep their weights in high_noise_model/ and low_noise_model/, each split across several shards — recreate those folders rather than flattening everything into one directory.

Re-run ./download_models.sh afterwards to check your work. Files already in the right place are detected and skipped, so a run that downloads nothing means the layout is correct.

First Launch

On first launch FUK will verify model paths and report any missing files. The server runs at http://localhost:8000 by default (easily changed if needed). If a model fails to load it will appear grayed out in the model selector — check the terminal output for the specific error.

See the GitHub README for the complete and up-to-date installation instructions, including Windows/WSL2 setup.

System Requirements

Tested Configuration

ComponentTested OnNotes
GPUNVIDIA RTX 4090 (24GB VRAM)8GB VRAM recommended minimum
CPUAMD ThreadripperModern multi-core
RAM256GB32GB recommended minimum
StorageM.2 NVMe SSDFast SSD strongly recommended for model loading
OSArch LinuxLinux primary; Windows via WSL2

VRAM Considerations

VRAM requirements scale with model size and output resolution. As a rough guide:

  • 8GB — base image generation at moderate resolutions; some models will not load
  • 12GB — comfortable for most image generation pipelines
  • 16GB+ — video generation, high-resolution image gen, AOV passes
  • 24GB — full pipeline with all features; recommended for production use

FUK will attempt to offload to system RAM when VRAM is insufficient, but generation will be significantly slower. The VRAM Management preset in each generation panel controls the offload strategy.

Disk Space

  • Base install: ~15GB
  • Models: 50GB–500GB+ depending on selection — see File Locations for where models are expected
  • Outputs: variable; EXR files with all AOV passes are substantially larger than standard image formats

Model and application install directories can be on separate drives. See the Windows Storage Doc for model location considerations on Windows.

Image Generation

▶ Video breakdown — coming soon

FUK's image generation pipeline supports Qwen Image models with full control over generation parameters. Outputs are organized by project / shot / version hierarchy and accompanied by full metadata sidecar files. Every generation is reproducible from its sidecar alone.

Supported Models

ModelNotes
Qwen ImageBase text-to-image pipeline
Qwen Image + ControlNetStructural conditioning via depth, pose, edge maps
Qwen Image + EliGenRegional prompt conditioning — see Regional Conditioning
Qwen Image 2512High-resolution variant
Qwen Image Edit 2511Image-to-image editing
Flux 2 DevImage-to-image editing
FLUX.2-klein 4BSmall, fast FLUX.2. Apache-2.0, so it is the commercially usable one of the family
Krea-2 RawText-to-image, 52 steps at CFG 4.5 — the quality option. Gated, non-Apache licence
Krea-2 TurboDistilled Krea-2, 8 steps at CFG 1.0 — roughly 6× faster. Shares Raw's text encoder and reuses the Qwen-Image VAE

Easily Added Models

FUK's pipeline architecture supports additional model families with minimal configuration. The following have been tested or are known to be compatible:

Generation Parameters

ParameterDescriptionNotes
Width / HeightOutput resolution in pixelsUse the Spec Tool for spec-compliant resolutions; dimensions snap to 16px alignment
StepsDenoising steps — higher step counts increase quality and generation time20–40 is typical; presets available
Guidance ScalePrompt adherence. Higher values follow the prompt more strictly but can reduce image qualityRange 1.0–10.0; 6–8 is a common starting point
Detail BiasSkips a slice of the high-noise composition phase and spends that compute on detail bands instead — yields grittier, more textured outputRange 0.85–1.00; default 0.90. See Detail Bias
SeedRandomness seed. A fixed seed with identical parameters produces identical outputSee Seed Control
SamplerDenoising schedule algorithm — affects quality/speed tradeoff and output character—
PromptText description of desired output—
Negative PromptElements to suppress in the output—
LoRAOne or more LoRA weights to blend into the base model, each with an independent multiplierSee Image Panel for per-LoRA controls
VRAM ManagementControls model offloading strategy when VRAM is limitedHigher offload = slower generation but lower VRAM floor

Detail Bias

The sampler runs a denoising schedule from high noise (sigma ≈ 1.0, where global composition is decided) down to clean (sigma ≈ 0, where fine texture and edges form). At Detail Bias 1.0 the full schedule runs. Below 1.0, the high-noise front is truncated and the same step count is repacked into a smaller, lower-noise window — so a larger share of compute lands in the texture-forming band.

The result is grittier surfaces, more visible micro-detail, and slightly less of the "diffusion smoothness" sheen. Composition becomes more conservative (the model has less room to wander globally), which makes this knob pair naturally with reference images and ControlNet conditioning where you didn't want global drift anyway.

The slider is clamped to 0.85–1.00; values below 0.85 strip too much of the composition phase and produce broken output. Try 0.85–0.90 for noticeable grit, 0.95 for a subtle bump.

Image Input & ControlNet

Edit and context models accept one or more reference images as conditioning input. Load a reference image via the Media Input component, select a preprocessor to extract a conditioning signal, and set the edit strength. See Preprocessors for available preprocessing modes.

OpenPose

▶ Video breakdown — coming soon

Skeletal pose conditioning — transfers body, hand, and facial keypoints from the reference while leaving appearance to the prompt. See OpenPose.

Canny

▶ Video breakdown — coming soon

Edge-map conditioning — locks silhouette and hard structural lines to the reference. See Canny Edge Detection.

Depth

▶ Video breakdown — coming soon

Depth-map conditioning — preserves spatial layout and volume without constraining edge detail. See Depth Estimation.

Inpainting

▶ Video breakdown — coming soon

Inpainting repaints one part of an existing picture and leaves the rest alone. You load the picture, paint a mask over the area to replace, and prompt for what should be there. Only the masked area is generated; everything outside it is the original image.

Supported Models

ModelNotes
FLUX.2-klein 4BMask resolves to 16px blocks. Apache-2.0
Flux 2 DevMask resolves to 16px blocks. Non-commercial — see Licensing
Qwen ImageMask resolves to 8px blocks
Qwen Image 2512Mask resolves to 8px blocks
Qwen Image Edit 2511Mask resolves to 8px blocks. Control images stay reference material — see the note below

Krea-2 and Qwen Image 2.1 cannot inpaint: their pipelines take no source image to blend against. The control-union and EliGen models are not enabled for it.

Workflow

  1. Select a model from the table above. An Inpaint Image slot appears in the Image Tools card.
  2. Load the picture to repaint. It sets the output size, rounded up to 16px, and takes priority over any control image for that.
  3. Click Paint Mask and paint over the area to replace, then Save Mask. Or load a mask file into the Mask slot instead — white is repainted, black is kept.
  4. Write the prompt and generate.

Loading a different inpaint image clears the mask, since a mask belongs to the picture it was painted on. Edit Mask reopens the current mask for more work, whether it was painted or loaded from a file.

Mask Painter

▶ Video breakdown — coming soon

The painter shows the image fitted to the window with the mask in red over it. Brush size is in image pixels, so it means the same thing at any window size. There is no zoom or pan.

ControlShortcutAction
BrushBPaint the mask
EraserERemove mask. X swaps between brush and eraser
Size[ / ]Brush size, from 2px up to half the image's long edge
UndoCtrl+ZSteps back through strokes and the three actions below, with no limit
Invert—Swaps the painted and unpainted areas
Fill—Masks the whole image
Clear—Removes the whole mask
CancelEscCloses without saving; asks first if there are unsaved changes

The app's own shortcuts are suspended while the painter is open. A saved mask is written to the project cache as mask_NNN/mask.png at the image's own resolution.

Settings

SettingDescriptionNotes
Mask FeatherWidth in pixels of the soft edge between the repainted area and the rest0–128, default 16. 0 gives a hard edge, which usually shows as a seam
Keep original pixels outside the maskPastes the source pixels back over everything outside the mask after generationOn by default. Turn it off only to see what the model returned for the whole frame
Detail BiasBelow 1.0 the masked area starts from a noised copy of the original rather than from pure noiseUse 1.0 to replace the content outright; lower values let the original's colour and layout carry through

How It Works, and Its Limits

The model inpaints in latent space: on every denoising step the area outside the mask is steered back to the source picture while the area inside it is generated. That has two consequences.

  • The mask is coarse to the model. It is reduced to the latent grid — 16px blocks on FLUX.2, 8px on Qwen — so a block the brush only clips is partly regenerated. Fine brushwork is not what decides the result; coverage and the feather are.
  • The whole picture passes through the model's decoder, so the untouched area comes back very slightly altered. Keep original pixels fixes that by compositing the source back using the mask at full resolution, which also puts the edge where you painted it rather than on a block boundary.

The latent saved alongside the image is the model's own output, from before that composite, so it will not match the PNG exactly outside the mask.

On Qwen Image Edit the inpaint image and the control images are separate inputs. To confine an edit to one region, load the same picture into both slots and mask the region: the control image tells the model what it is editing, and the mask stops the edit from touching anything else.

The inpaint image and mask are copied into the generation's folder, and dropping that generation from history onto the preview restores both, along with the feather and keep-original settings. A model gets the inpaint slot by listing inpaint under supports in models.json.

Batch Generation

FUK supports batch generation — queue multiple runs from the same settings in a single pass. Each result is saved as its own versioned output with its own metadata sidecar. Batch jobs run sequentially and can be monitored from the generation modal.

Video Generation

▶ Video breakdown — coming soon

FUK supports video generation from text prompts and image inputs using Wan pipelines. Output is organized under the same project / shot / version hierarchy as images. Generated video can be passed directly to Frame Interpolation to increase frame rate before delivery.

Supported Pipelines

PipelineInputNotes
Wan 2.2 I2V-A14BImage + text promptImage anchors the first frame; motion is synthesized toward the prompt
Wan 2.2 Fun ControlControl video + optional start/end imagesUses a reference video as a motion/structure guide. Also extends a clip past its frame — see Outpainting
FFLF (Wan 2.2 Fun-A14B-InP)Start image + end image + text promptInterpolates motion between two fixed frames; output lands on both. See FFLF
Wan AnimateImage + text promptAnimation-focused pipeline with enhanced character and object motion control
LTX-2.5First frame + text prompt22B audio-video at 48kHz — one denoise produces picture and a synchronized soundtrack. Function variants are LoRAs on one shared base rather than separate checkpoints, though upstream has published only one for 2.5 so far; see LTX-2.5 Function LoRAs
MiniMax-H3 FL2VAFirst and/or last frame + text promptJoint audio-video at 32kHz. Generates from a prompt alone, or interpolates between two fixed frames
MiniMax-H3 Ref2VAReference image / video / audio + text promptSame model family, conditioned on reference media the prompt addresses positionally as <Subject 1>, <Video 1>, <Audio 1>

LTX-2.5 Function LoRAs

LTX-2.5's variants are LoRAs on one shared 42GB base, not separate fused checkpoints, so a new function costs its LoRA rather than another full model. Today there is exactly one: Lightricks has not yet reissued for 2.5 the twelve that existed for LTX-2 — seven camera moves and five in-context controls — and those are 19B adapters that will not load on the 22B DiT, so they were removed with the model swap rather than left in the picker to fail.

Download from Utilities → Models: the LTX-2.5 row carries a Show optional LoRAs list where each one can be ticked and fetched on its own, with its size shown before you commit. They are optional — LTX-2.5 is complete and generates without any of them — so they never count toward the model's own download state. A headless download_models.py run fetches the set at the end instead. Either way the file lands in the shared model cache and is symlinked into <defined_loras_path>/ltx2/, so it costs its size once and appears in the LoRA picker immediately.

LoRASizeNotes
IC Pixel Spatial Upscaler0.33 GBRe-renders a low-resolution clip at 2x. Needs a driving clip in the In-Context Video slot; upstream pairs it with the distilled DiT at 8 steps and CFG 1.0

Alternative Models

Flux Video is coming soon. Support will be added to FUK upon release.

Generation Parameters

ParameterDescriptionNotes
Frame CountTotal number of frames to generateMust land on the selected model's frame lattice — Wan 4n+1, LTX-2.5 8n+1, MiniMax-H3 17n+5. Out-of-lattice values round up; longer sequences require significantly more VRAM
Scale FactorOutput resolution as a percentage of the input image dimensions100%, 75%, 50%, or 25%; dimensions round up to the model's latent grid — 16px for Wan, 32px for LTX-2.5 and MiniMax-H3 (64px for LTX-2.5 two-stage)
StepsDenoising steps20–40 typical; presets available. Model defaults are Wan 40, LTX-2.5 30, MiniMax-H3 50
Guidance ScalePrompt adherenceRange varies by model. 1.0 disables CFG entirely — along with the negative prompt — which is MiniMax-H3's shipped default
Sigma ShiftAdjusts the noise schedule — higher values shift more denoising toward early stepsWan: range 1.0–10.0, default 5.0. MiniMax-H3 calls it Flow Shift: range 1.0–20.0, default 12.0 (Turbo variants use 6.0), with a separate Audio Shift (default 3.0) for its audio branch. LTX-2.5 has no shift control — its schedule is derived from sequence length — so the field is hidden for it
DiT Switch BoundaryTimestep (×1000) where dual-DiT Wan 2.2 models hand off from the high-noise DiT (global composition) to the low-noise DiT (detail) — higher values give the high-noise expert more stepsRange 0.0–1.0; default 0.875; A14B (dual-DiT) models only
Two-Stage SamplingLTX-2.5 only. Denoises at half width and height, upscales the latent, then refines at full size for a fixed 3 steps at CFG 1.0 through the distilled LoRA — roughly 3x faster than one-stage at the same requested sizeOff by default. Not a free win: the refine pass changes the character of the picture, so A/B it against a one-stage run on the same seed before using it on a final. Forces the 64px latent grid. The mode that ran is recorded in the generation metadata as sampling_mode
Motion Bucket IDControls baseline motion amount in supported pipelinesOptional; leave blank to use model default
Denoising StrengthHow much the model deviates from the input image (img2vid modes)Range 0.0–1.0; lower values stay closer to the input
Sliding WindowSize and stride for sliding window video processingOptional; used to process sequences longer than the model's native context
SeedSeed for repeatabilitySee Seed Control
VRAM ManagementOffloading strategy for VRAM-limited hardware—

Per-Model Constraints

The three video families disagree on nearly every hard limit, so the sampling controls are model-driven rather than fixed. Each model declares a constraints block — the family block lives in defaults.json, and any model may override individual keys in models.json. The server applies it when snapping sizes and frame counts, and the Video tab reads the same block over /api/config/models to range, label, and hide its controls, so both sides validate identically. Adding a fourth video model is a config entry, not a UI change.

ModelFrame latticeMin framesLatent gridFPSShift controlDefault CFG
Wan4n+1516px24Sigma Shift, 1.0–10.0, default 5.04.0
LTX-2.58n+1932px (64px in two-stage)24None — schedule is derived from sequence length, so the control is hidden3.0
MiniMax-H317n+52232px24Flow Shift, 1.0–20.0, default 12.0, plus Audio Shift default 3.01.0 (CFG off)

Sizes and frame counts always round up onto the grid, matching what the pipelines enforce internally — a request never silently yields a smaller or shorter clip than asked. Rounding happens before conditioning media is loaded, so the first frame, keyframes and control video land on the same canvas the model actually runs at, and the generation history records the effective values rather than the requested ones. At 24fps the ~5-second point is 121 frames for Wan and LTX-2.5, 124 for MiniMax-H3.

Controls that a model has no use for are hidden rather than left inert: LTX-2.5 and MiniMax-H3 both drop DiT Switch Boundary, Sliding Window and TeaCache, and MiniMax-H3 additionally drops the LoRA stack, which its pipeline does not support. Values for a hidden control are not posted either, so the generation history never records a setting the model did not apply.

Control Video Conditioning

Control-capable pipelines accept a per-frame conditioning sequence instead of (or alongside) a still reference — the same signals used for image ControlNet, extracted across every frame. Generate the sequence in the Preprocess Panel and load it as the control video. Conditioning must be temporally stable: preprocess the whole range in one pass so the signal doesn't flicker between frames.

Canny

▶ Video breakdown — coming soon

Edge-map control video — holds silhouette and hard structural lines to the source footage across the sequence. See Canny Edge Detection.

Depth

▶ Video breakdown — coming soon

Depth control video — preserves camera move and spatial layout without locking edge detail. Normalize depth over the full range rather than per frame, or the sequence will pulse. See Depth Estimation.

OpenPose

▶ Video breakdown — coming soon

Skeletal pose control video — drives body, hand, and facial keypoints frame by frame while appearance comes from the reference image and prompt. See OpenPose.

FFLF — First Frame / Last Frame

▶ Video breakdown — coming soon

Give the model a start image and an end image and it generates the motion between them, landing exactly on both. Useful for bridging two locked storyboard frames or holding a specific in and out pose. Frame count sets how long the transition takes — the same move over more frames is slower and smoother.

Outpainting (Wan 2.2 VACE)

▶ Video breakdown — coming soon

Outpainting extends a clip past its own frame. The source is placed on a larger canvas, the model generates only the area around it, and the original footage is pasted back over the result. Use it to change a clip's aspect ratio without cropping, or to pull the camera back from a shot that was framed too tight.

It runs on the Wan 2.2 VACE model — the control-video pipeline listed above as Fun Control. Outpainting uses that pipeline's video input for the padded source, so a clip cannot be outpainted and used as a structure guide in the same run.

Workflow

  1. Select the Wan 2.2 VACE model and tick Outpaint. The control video slot becomes Source Video.
  2. Load the clip to extend.
  3. Choose an Output Aspect, a Source Scale, or both. At least one must leave room around the source.
  4. Position the source on the canvas if it should not be centred.
  5. Prompt for the whole scene, including what is already in the clip, and generate.

Controls

ControlDescriptionNotes
Output AspectAspect ratio of the new frameSame as source by default. The list is the configured aspect ratios plus 4:5 and 9:16
Source ScaleHow much of the fitted size the source keeps. At 1 it touches the canvas on its tight axis; lower values leave room on every side0.2–1.0, default 1
HorizontalWhere the source sits across the canvas0 = left, 0.5 = centred, 1 = right
VerticalWhere the source sits down the canvas0 = top, 0.5 = centred, 1 = bottom
Edge FeatherPixels over which the original footage fades into the generated area0–128, default 16. 0 gives a hard edge

The canvas is the smallest frame of the chosen aspect that contains the source, enlarged by 1 / Source Scale. It then goes through the Resolution setting and the model's 16px grid like any other source size, and the Resolution label shows the canvas it is working from. With Same as source and a scale of 1 there is nothing to generate; the panel warns Nothing to fill and Generate stays disabled.

What to Expect

  • The original area is the source, not a regeneration. The model returns the whole frame, with the kept region slightly altered by its decoder, so the placed source is composited back over it. If the canvas is smaller than the source needs, the source is scaled down to fit, and those scaled pixels are what is kept.
  • The feather is taken from inside the source edge. The blend gives up a sliver of original footage rather than showing generated pixels as if they were source. Edges that sit on the canvas border are not feathered, since there is nothing generated beyond them.
  • The source is snapped to an 8px grid so the mask edge lines up with the model's latent cells. That can leave it a few pixels off its true aspect.
  • A short source shortens the job. If the clip has fewer frames than the frame count, the run drops to the longest 4n+1 length the clip covers; frames past its end would be pure invention. A clip under 5 frames is refused.
  • A reference image is only a look guide. It can still be loaded, but the canvas, not the image, sets the output size.

The placement that ran is recorded in the generation metadata under outpaint: the source rectangle on the canvas, the source's native size, and the feather. A model offers the Outpaint option by listing vace_video_mask under supports in models.json.

Output Format

Video is saved as a PNG frame sequence plus a composited MP4 for preview. The frame sequence is the primary output — import it directly into Nuke, After Effects, DaVinci Resolve, or any compositing application. EXR passes are generated per-frame when AOV export is enabled via the Layers Panel.

Frame rate can be increased post-generation via FILM interpolation. See Frame Interpolation. Interpolation runs on the frame sequence, not the MP4.

Preprocessors

Preprocessors convert input images into conditioning signals that guide generation — giving precise control over pose, depth, structure, and edges in the output without fighting the model through prompt engineering alone. Preprocessing is done in the Preprocess Panel; the output is then used as a ControlNet conditioning input in the Image Panel.

Canny Edge Detection

Extracts hard edges and structural lines from an input image. Useful for preserving architectural forms, hard-surface geometry, or any scene with defined edges that should carry through to the output.

ParameterDescription
Low ThresholdMinimum gradient magnitude to consider as an edge — lower values detect more edges
High ThresholdMinimum gradient magnitude for a strong edge — edges below this but above low threshold are kept only if connected to a strong edge
Blur KernelPre-detection smoothing — reduces noise at the cost of fine edge detail
InvertFlips the edge map — white edges on black vs. black edges on white

OpenPose

Detects human body pose from an input image and extracts a skeleton map. Use this to replicate or constrain body positions across generations. Useful for character work where posture and gesture need to be consistent shot to shot.

ParameterDescription
BodyFull body keypoint detection — always enabled
HandsAdds wrist, palm, and finger keypoints
FaceAdds facial landmark keypoints

Depth Estimation

Generates a depth map from an input image using Depth Anything v3, encoding near-to-far distance as a greyscale gradient. Used for spatial conditioning — maintaining scene depth structure across generations.

ParameterDescription
ModelDA3 model variant — larger models produce more accurate depth at higher cost: da3_mono_large, da3_metric_large, da3_giant
InvertFlips near/far encoding
NormalizeStretches depth values to fill the full 0–1 range
Range Min / MaxClamps the depth range — useful for isolating a specific depth band

Workflow

  1. Go to the Preprocess Panel and load a reference image or video
  2. Select a preprocessing method and configure its parameters
  3. Generate — the conditioned output is saved alongside your source
  4. In the Image Panel, load the preprocessed result as a ControlNet input
  5. Set conditioning weight and guidance range, then generate

Preprocessors also run on video sequences — the output is a per-frame conditioning sequence. Depth + pose is a common combination for character shots.

Regional Conditioning (EliGen)

▶ Video breakdown — coming soon

EliGen integration brings regional conditioning directly into the generation pipeline. Define compositional zones within the frame and assign independent parameters to each — separate prompts, weights, and conditioning per region. This gives you direct spatial control over composition without relying entirely on prompt engineering.

How It Works

Rather than sending a single prompt to the model and hoping for a specific composition, EliGen lets you explicitly partition the frame. Each zone is a mask that defines a spatial area, paired with a prompt and weight that apply only within that area. Zones are composited during the denoising process — the model integrates them into a coherent result rather than pasting regions together.

EliGen is activated by selecting a Qwen Image + EliGen model in the Image Panel. Zone masks are loaded as .psd or .ora files — each layer in the file becomes a separate conditioning zone.

Zone Parameters

ParameterDescription
Entity MasksPath to a .psd or .ora file — each layer is treated as a separate zone mask
Context ImageOptional reference image for the overall scene; set EliGen alpha (0.0–2.0) to control its influence
EliGen AlphaStrength of the context image's influence on the full generation (0.0 = no influence, 2.0 = strong)
Mask StrengthPer-zone conditioning strength

Practical Notes

  • The global prompt still applies to the whole frame — zone prompts add to it rather than replace it
  • Zones work best for broad compositional control (foreground subject, background environment, sky) rather than fine detail placement
  • EliGen and ControlNet can be used together — ControlNet handles structural conditioning, EliGen handles content per region
  • Create zone masks in any application that exports layered PSD or ORA files — Photoshop, Krita, and Affinity Photo all work

Post-Processors

▶ Video breakdown — coming soon

Two finishing passes — upscaling (raise resolution) and frame interpolation (raise frame rate). Both run in the Postprocess Panel, take the same input types (image, video, or frame sequence), and save their result as a new version alongside the original. Neither requires re-running generation.

Work in progress. The post-processors are the least mature part of FUK. Both are constrained by what is available under an open-source licence that also permits commercial use — the current models are older, image-only, and have no temporal awareness. Better options exist, but they are either closed, research-only, or non-commercial, and are not shipped here.

In practice results fall short of the dedicated tools in Topaz, Resolve, Nuke, or Twixtor. Use these passes for previews, dailies, and quick turnarounds; for final delivery, take the frame sequence out to a purpose-built tool. New models are added as licensing allows.

Upscaling

ModelBest ForScaleTemporal
SeedVR2 7BVideo — best temporal coherence2×, 4×Yes
SeedVR2 3BVideo — faster, still temporal2×, 4×Yes
Real-ESRGAN x4 PlusStills and video2×, 4×, 8×No
LanczosFast, non-AI resize2×, 4×, 8×No

SeedVR2 — the temporal option

Status: under evaluation. SeedVR2 is wired up, measured and usable, but it has not yet been signed off as part of the finishing pipeline. The open question is whether the detail it invents is acceptable on clean generated footage — see the two caveats below before committing a shot to it. It is deliberately kept out of the latent → EXR path for the reasons under Bit depth.

SeedVR2 restores a clip as a sequence rather than as a stack of unrelated frames, so detail stays put instead of crawling. It is the default for video and the only upscaler here worth calling a finishing step. Weights download with download_models.sh, or automatically on first use, into {models_root}/seedvr2.

A caveat worth setting expectations on. SeedVR2 is a restoration model — it was trained to recover detail from degraded footage. Pointed at already-clean output it has little real detail to recover, so it invents some, and what it invents varies between frames. Measured on a clean 640×360 clip, frame-to-frame correlation dropped from 0.65 in the source to about 0.25 after restoration, with a period-4 component appearing that matches the VAE's 4× temporal compression. In practice that reads as motion stepping or fine detail shimmering. The 7B model and a wider frame window both reduce it; neither eliminates it. It pays off most on genuinely soft or compressed source.

SeedVR2 settings

SettingWhat it does
Quality7B fp8 is the best available and the slowest; 7B Sharp trades neutrality for detail; 3B fp8 is roughly twice as fast and noticeably less stable in motion. The Q4/Q8 entries are the same models quantized, for when VRAM is tight.
Frame WindowFrames restored together — 5, 9, 13, 17 or 21. 9–13 is the usable band; wider is not better. It is also the dominant VRAM cost. See the measurements below.
Batch BlendingFrames shared and crossfaded between consecutive batches. Leave on Auto. Set to Off and the picture visibly steps every frame-window frames, because each batch is restored as an independent diffusion problem and invents its own fine detail.
Motion ProtectionBlends moving pixels back toward the source to keep their motion blur. 0.7 by default. See below — on footage with fast movement this matters more than every other setting combined.
Resolution CapUpper bound on the longest output edge
Memory ModeAuto starts fast and steps down until the clip fits. Pinning a mode reports the out-of-memory error instead of retrying.

On a 24GB card the VAE, not the transformer, is what runs you out of memory — measured peaks for a 1080p output were 14.5GB in the encode and 11.3GB in the decode against just 6.2GB for the DiT. That is why the frame window and the resolution cap matter far more than any model-offloading setting, and why Auto lowers the window first when a clip does not fit.

Motion blur, stepping and ghosting

The most common complaint about SeedVR2 output — that fast-moving subjects look like they are stepping, with detail ghosting between frames — has one cause, and it is not a bug. SeedVR2 removes motion blur, because that is what a restoration model does. Measured on a Wan clip, the fast-moving region of frame came back roughly 10× sharper (variance of Laplacian 19–28 in the source, 185–266 restored), consistently on every frame.

Motion blur is what makes 24fps read as smooth motion. Strip it out and each frame becomes a crisp snapshot at a distinct position, so the same displacement now reads as stepping — and because the restored detail is hallucinated independently per frame, its shape shifts slightly between frames, which reads as ghosting.

Motion Protection is the fix. It blends each pixel back toward the source in proportion to how fast that pixel is moving, so moving subjects keep their blur while still areas keep the full sharpening. Measured on the same clip at the default 0.7:

RegionSeedVR2 sharpening retained
Fast-moving hand19% — keeps its motion blur
Subject / chair37%
Still background78% — keeps the sharpening

The mask comes from the source, not the restored frames, since the source is what still carries honest motion blur. A static shot produces a near-zero mask and passes through untouched, so there is no reason to turn this off unless you specifically want the full de-blurred look. It costs a few seconds per clip.

Choosing a frame window

The obvious assumption — that a wider window is always more coherent — does not hold. Measured with the 7B on a 45-frame clip, scoring how much detail the model invents (mean frame-to-frame delta) and how much it steps in fours (lag-4 autocorrelation; the source scores 0.08):

WindowInvented detail4-frame steppingTime
51.4690.4782s
91.367−0.1649s
13 (default)1.3880.0554s
171.6740.3338s
211.7150.3645s

Both ends are bad. Too narrow and each batch has too little context to place detail consistently. Too wide and the VAE's 4× temporal compression has to carry more motion than it can represent, so the stepping comes back and the model invents more. These figures are from one 45-frame clip — treat 9–13 as the starting point rather than a law, and re-check if your shots are much longer.

Bit depth, and why SeedVR2 is not in the EXR path

SeedVR2 is 8-bit display-referred at both ends. This is not a setting — it is fixed in the engine:

  • Input is divided by 255 on load, so a 16-bit PNG is misread rather than merely truncated
  • Internals run at fp16
  • Output is multiplied by 255 and cast to uint8, on every write path

There is no float path, no linear-light path, and no way to carry values above 1.0 through it. Patching the engine would take only a few lines, but it would not help: the model was trained on display-referred video, so linear HDR is out of distribution for it. SeedVR2 belongs in display space — that is where it is correct, not a limitation to route around.

This matters because the latent → EXR path does real work that 8-bit throws away. It decodes the latent in float32 rather than bf16, optionally decodes several times with scale or noise bracketing and fuses them with Mertens exposure fusion to recover range a single decode cannot give, then converts sRGB → linear. All of that happens at decode, before any quantisation. Put SeedVR2 downstream of it and the result is crushed to 8-bit immediately — you would be writing float32 EXR containers holding round-tripped 8-bit sRGB, with the bracketing entirely wasted.

Note also that there is no latent-space option: SeedVR2 carries its own VAE and cannot consume Wan latents. The latent must be decoded to pixels first, whatever route you take.

Four ways to sit the two together, in rough order of preference:

ApproachTrade-off
Keep SeedVR2 out of the EXR path (current behaviour)EXR stays the clean linear master at native resolution; SeedVR2 serves delivery and preview. Loses nothing.
Clean resample — lanczos-upscale the float32 linear decodeLarger EXR, full range preserved, nothing invented. Often preferable for VFX: hallucinated detail is not real information and will not match across shots or against plates.
Detail transfer — composite SeedVR2's detail as a ratioUpscale the HDR cleanly, run SeedVR2 on a tonemapped copy, then multiply the HDR by enhanced / unenhanced. Transfers detail without replacing pixels, so highlights above 1.0 survive. Standard practice for folding an LDR-only enhancement into a linear pipeline. Costs real complexity, and the ratio needs guarding in near-black.
Patch the engine for float I/ONot recommended. A few lines, but you would carry a patch on a vendored repo and still have the out-of-distribution problem.

The general principle: the EXR is the master and should stay clean, linear and full-range. AI enhancement is a look decision, and look decisions are better applied downstream where they can be judged and reverted than baked into the master.

Real-ESRGAN Has No Temporal Model

Real-ESRGAN has no temporal model. Applied to video it enhances each frame in isolation, and because it hallucinates detail independently per frame, that detail crawls and shimmers between frames. On Wan output — where frame-to-frame motion is already slightly irregular — this is very visible. Use SeedVR2 for video and keep Real-ESRGAN for stills.

Workflow

  1. Go to the Postprocess Panel and select the Upscale tab
  2. Load an image or a video
  3. Select a model and scale factor
  4. Run — the result is saved as a new version alongside the original

Frame Interpolation

FILM (Frame Interpolation for Large Motion) synthesizes intermediate frames to increase the effective frame rate of generated video. Useful for smoothing motion, converting a 12fps generation to a 24fps deliverable, or creating slow-motion sequences from standard-rate output.

How FILM Works

FILM uses a learned model to estimate motion between adjacent frames and synthesize intermediate frames that are temporally consistent. Unlike traditional optical flow methods, it handles large displacements and occlusions more gracefully — making it a better fit for AI-generated content where frame-to-frame motion can be irregular. It is the best-performing interpolator currently available to FUK under a licence that is both open source and commercially usable.

Parameters

ParameterDescription
Source FramerateThe frame rate of the input sequence — must match the actual rate the sequence was generated at
Target FramerateDesired output frame rate — FILM synthesizes however many intermediate frames are needed to reach it
Video Output ModeWhether to produce an MP4 preview alongside the output frame sequence

Bit depth, and the EXR route

FILM sits differently from SeedVR2 here, and the distinction is worth understanding.

The 8-bit limit is FUK's, not the model's. FILM is a plain PyTorch module in our own code and its interpolation call takes arbitrary float tensors. Everything restricting it to 8-bit lives in our wrapper: frames are loaded with cv2.IMREAD_COLOR (which forces 8-bit) and divided by 255, and saved clamped to [0,1] as uint8. On CUDA it also runs at fp16, not float32. A 16-bit save path exists but is currently unused, and clamps to [0,1] regardless. Raising this to float32 linear would therefore be a change to two methods, not a patch against a vendored repo — the open question is behavioural rather than structural, since FILM was trained on display-referred images. It should tolerate linear light better than a restoration model would, because interpolation is mostly geometric — estimate motion, warp, blend — but this is untested.

Bit depth is the smaller problem, though. Interpolation changes the frame count, and in a VFX sequence the beauty EXR has to stay in lockstep with its AOVs:

  • Cryptomattes cannot be interpolated at all. They are object ID maps — a blend of two IDs is not a third object, it is a meaningless value
  • Depth blends across occlusion edges, producing surfaces that never existed
  • Normals need renormalising after any blend, and interpolated normals drift off the unit sphere

The fix is ordering, not precision. Interpolate the beauty first, then generate depth, normals and crypto from the interpolated sequence. Every layer then derives from the same frames, and crypto is regenerated by SAM2 on real images rather than blended. Interpolating after AOV generation desynchronises the sequence and silently corrupts the mattes — silently being the dangerous part, since a corrupted crypto matte still looks like a crypto matte.

There is no latent-space shortcut either, for a different reason than SeedVR2's: Wan's VAE is 4× temporally compressed, so latent frames are not video frames and interpolating them would interpolate groups of four.

Practical Notes

  • FILM performs best with smooth, continuous motion — highly chaotic or flickering content will not interpolate cleanly
  • Generated at 12fps → interpolated to 24fps is the most common workflow
  • Interpolation does not generate new content — it synthesizes in-between frames; it cannot recover motion that wasn't present in the original generation
  • Interpolation runs on the frame sequence, not the MP4 preview — load the sequence directory, not the video file

SDR → HDR

Converts a finished 8-bit SDR clip into scene-linear HDR using Lightricks' LTX-2.5 SDR-To-HDR IC-LoRA. It runs in the Postprocess Panel and writes a half-float EXR sequence (ACEScg by default) plus a 10-bit BT.2020/HLG master, saved as a new version alongside the original.

Why this is different from EXR export

The latent → EXR path recovers precision, not range. Its ceiling is the VAE's [0, 1] clamp, and bracketed decodes can only redistribute what the latent already held. Highlights that SDR clipped are simply not there to recover.

This model was trained on paired SDR/HDR plates and synthesises the range SDR threw away: blown skies, practicals, speculars. That makes it the real range path, and a different kind of operation. The highlights it writes are a learned reconstruction, not measured light, so judge them on the shot.

How it works

The SDR clip is the whole control signal. There is no prompt, no CFG and no text encoder; the LoRA ships a precomputed embedding of the one caption it was trained on.

FUK's LTX-2.5 normally runs through DiffSynth, but the HDR LoRA depends on more than a LoRA: an ACEScct input transform, seam keyframes at every 24/32-frame border, and a keyframe-aware diffusion VAE decode. Rather than port that, FUK runs Lightricks' own ltx-pipelines from a pinned checkout in fuk/vendor/LTX-2, in a subprocess, the same arrangement as SeedVR2.

Outputs

FileDescription
EXR sequenceHalf-float frames in the chosen colour space. The deliverable for grading and comp
HLG master10-bit HEVC, BT.2020 primaries, HLG transfer. Written whichever EXR colour space you pick
SDR previewHable-tonemapped H.264 for in-app playback only. Browsers on Linux mostly cannot decode 10-bit HEVC, and none show HLG as HLG on an SDR panel

Parameters

ParameterDescription
EXR Colour SpaceACEScg (scene-linear, recommended), Linear Rec.709 / sRGB, or ACEScct (the VAE's log codes, untouched)
Seam KeyframesPins an SDR guide and a generated HDR frame at every 24/32-frame seam and decodes against them. The trained default at strength 0.95; only engages past ~24 frames. Leave on unless comparing
QualityHigh generates 2N−1 frames from a doubled reference and keeps every other one. Fewer temporal artifacts, at roughly twice the time and memory
Memory ModeAuto tries resident FP8 on cards that can hold it, then falls back to offload. Resident needs a 32GB+ card; Offload streams weights from RAM

Memory on a 24GB card

The 22B transformer does not fit 24GB even at FP8. Loading it alone reached 21.1GB and ran out before the first step, so on a 4090 Auto goes straight to offload. The bf16 weights are pinned in system RAM (~42GB) and streamed to the GPU per layer; every layer still computes on the GPU.

The whole clip is denoised as one attention window, so tiling cannot help and length × resolution is the limit. Measured on a 4090: 121 frames at 1920×1088 fits, 225 frames does not. A 17-frame 768×432 clip peaked at 7.7GB and finished in 39s including load. If a run runs out of memory, the error message estimates how many frames will fit at that resolution.

Practical Notes

  • Video input only. Runs at the source's own resolution and length
  • The pipeline needs 8k+1 frames. FUK pads the clip losslessly by holding its last frame, then trims the extra frames back off, so no frames of your plate are dropped
  • Weights are not fetched on first use: the transformer alone is 42GB. Download LTX-2.5 — SDR → HDR from the Model Manager or run download_models.sh
  • The first run in a session reads the weights into page cache sequentially before loading. That takes seconds instead of the minutes a cold mmap load would take
  • Same licence as the LTX-2.5 base FUK already runs (LTX-2.x Community License)

AOVs & Passes

▶ Video breakdown — coming soon

FUK generates Arbitrary Output Variables (AOVs) alongside the beauty render via the Layers Panel. These technical passes enable compositing, grading, and integration with professional DCC tools downstream.

Work in progress. AOV outputs are being refined and quality is improving across builds, but set expectations accordingly: the passes here are estimated from a finished image by inference models, not rendered from scene geometry. They will not match the mathematically exact passes a 3D renderer writes out.

The constraint is as much licensing as it is quality. FUK only ships models that are open source and carry a licence permitting commercial use, and in the depth / normals / segmentation space that rules out several of the strongest available models. What is left is usable for comp work but is not on par with the equivalent tools in Nuke, Houdini, or a production renderer. Where a pass is critical, treat FUK's output as a starting point to be cleaned up rather than a finished deliverable.

Feedback on specific issues is appreciated — contributions welcome.

Available Passes

PassDescriptionChannelsStatus
BeautyMain generation output — full color renderRGBStable
AlphaSubject mask / transparency channelAStable
DepthScene depth encoded as normalized 32-bit float — closer subjects brighterZIn refinement
NormalsSurface normal directions in world or tangent space — RGB encodes XYZ orientationRGBIn refinement
CryptomatteObject and material segmentation masks compatible with the Cryptomatte standard, generated via SAM2RGBA × layersIn refinement

Using AOVs in Compositing

AOV passes are exported together in a single multi-layer EXR file — see EXR Export for the layer structure. Typical uses:

  • Depth — depth-of-field in comp, Z-based fog, depth sorting of elements
  • Normals — relighting in comp, surface-aware grading, integration with CG elements
  • Cryptomatte — instant object isolation, per-element color correction, matte extraction without manual rotoscoping
  • Alpha — subject extraction, compositing over new backgrounds

EXR Export

▶ Video breakdown — coming soon

FUK exports multi-layer EXR files containing all available AOV passes in a single file via the Export Panel. EXR is the standard interchange format in professional VFX and compositing pipelines — it preserves full floating-point precision and carries all passes in one file.

Layer Structure

Layer NameChannelsDescription
RGBAR, G, B, ABeauty render with alpha
depthZDepth pass
normalR, G, BSurface normals
crypto_objectR, G, B, ACryptomatte object layer
crypto_materialR, G, B, ACryptomatte material layer

Export Options

  • Multi-Layer EXR — all passes combined into a single file per frame
  • Single-Layer EXRs — one file per pass per frame; useful when downstream tools don't support multi-layer EXR
  • Bit Depth — 8, 16, or 32-bit per channel; 32-bit recommended for technical passes
  • Compression — ZIP, PIZ, RLE, and others; PIZ is efficient for noisy data, ZIP for smooth gradients

Color Management (ACES)

Output color management is backed by OpenColorIO. The beauty pass can be written in any of the targets below; every export writes the matching chromaticities attribute into the EXR header, so Nuke auto-interprets the file without an artist setting a read node's colorspace by hand.

TargetPrimariesUse
Linear (default)Rec.709Scene-linear Rec.709. The historical FUK output — unchanged, byte for byte
ACEScgAP1The ACES working space. What most ACES pipelines composite in
ACES2065-1AP0ACES interchange / archival
Linear Rec.2020Rec.2020Wide-gamut delivery pipelines outside ACES
sRGBRec.709Display-referred passthrough; no transform applied

It uses your config, not a baked transform

This is the part that matters in a facility. FUK does not ship a fixed ACES transform — it resolves an OCIO config in this order, first hit wins:

  1. The $OCIO environment variable — your facility config, so FUK output lands in whatever color pipeline the seat already runs
  2. color.ocio_config_path in defaults.json — explicit override
  3. ocio://studio-config-latest — the OCIO v2 built-in, so it works out of the box with nothing to install or version

Color space names differ between config generations — the same space is sRGB - Texture in an ACES 1.3 config and sRGB Encoded Rec.709 (sRGB) in the current studio config — so targets are resolved by name aliases, then by OCIO roles, and failing both, bridged from the built-in config through the aces_interchange role. Verified identical output across ocio://default, the CG config, the ACES 1.3 studio config, and a config with the source space deliberately renamed.

The Export panel shows which config is actually in play. A target your config cannot resolve never appears in the dropdown, so there is no way to request an export the seat can't deliver.

What the transform assumes

The VAE was trained on sRGB-encoded imagery, so that is treated as the source encoding. This is an assumption, not a measurement — but it is the right one for web-scraped training data and there is no better one available. It is applied exactly once: the latent decode path already linearizes during bracket fusion, so those exports convert gamut only, while the image-file path applies the transfer function and the gamut matrix together.

What it deliberately does not do

  • No inverse tone mapping. ACEScg output is not HDR output. Nothing here invents highlights the latent never contained — synthesizing them would be a filter dressed as color science, and a compositor will regrade it anyway. Range and color space are separate concerns; range is what the bracketed latent options address
  • No display encodings. No PQ, no HLG, no Rec.2100. EXR output is scene-linear; display transforms belong to the downstream app
  • No clamping. The decode path preserves values below 0 and above 1, and nothing in the color transform clips them — they reach the file intact at both 16- and 32-bit
  • AOVs are never touched. Depth, normals and Cryptomatte carry measurements and IDs, not color. They come out bit-identical whichever target you pick, and Cryptomatte stays 32-bit float even when beauty is written at 16-bit, because half-precision corrupts the hash bit patterns
  • Not an ACES container. ACES2065-1 is offered as a color space, not as ST 2065-4 container compliance — that would force PIZ compression and a fixed attribute set, removing choices the panel exposes

OpenColorIO is optional. Without it, Linear and sRGB still work exactly as before — they use built-in transfer functions and need no config. The wide-gamut targets simply don't appear. If a saved project asks for one anyway, the export falls back to linear Rec.709, writes Rec.709 chromaticities so the header still describes the actual pixels, and returns a warning rather than failing. Install with pip install opencolorio.

Compatible Applications

  • Nuke (full Cryptomatte support via the CryptomatteNode) — auto-interprets the color space from the chromaticities attribute
  • Fusion / DaVinci Resolve (Cryptomatte operator) — Resolve does not read chromaticities reliably; set the clip's input color space from the fuk/colorSpace header attribute if it lands wrong
  • After Effects (with ProEXR for multi-layer access)
  • Blender Compositor (native multi-layer EXR and Cryptomatte)
  • Houdini COPs
  • Katana

LoRA Dataset Builder

▶ Video breakdown — coming soon

The LoRA Dataset Builder generates training datasets for custom LoRA models using FUK's own generation pipeline. Rather than sourcing and curating images manually, it generates a structured set of variations from a subject description — covering pose, lighting, and context diversity needed for effective LoRA training. The tool lives in the Utilities tab.

Workflow

The builder runs in three phases:

  1. Setup — configure the subject, model, and generation parameters
  2. Generation — FUK generates the full variation set; progress is tracked in real time with a cancel option
  3. Curation — review generated images and vote thumbs up / thumbs down on each; finalize saves only the approved images

Setup Parameters

ParameterDescription
Subject TypeCategory preset: character, object, or environment — sets the variation pack and captioning approach
Subject NameName or token for the subject; used as the trigger word in generated captions
Preset PackVariation pack for the selected subject type — determines what poses, lighting, and contexts are generated
Variation DeselectionUncheck specific variations from the pack to skip them
Seed StrategyFixed — all variations use a single seed for consistency; Random — each variation gets its own seed
LoRAOptional: generate using an existing LoRA to produce in-style dataset images
LoRA AlphaBlend weight for the LoRA if one is selected
Steps / CFG ScaleGeneration quality parameters — same as the Image Panel

Curation Phase

After generation completes, every image is presented for review. Thumbs up keeps the image in the final dataset; thumbs down excludes it. Finalize writes only the approved images and their captions to the output directory. Rejected images are not deleted — they remain in a rejected/ subdirectory in case you want to revisit them.

Output Structure

lora_datasets/[subject_name]/
├── approved/
│   ├── 0001.png
│   ├── 0001.txt       ← caption file, one per image
│   ├── 0002.png
│   └── ...
├── rejected/
│   └── ...
└── dataset.json       ← subject name, preset, seed strategy, generation log

Captioning

Captions are generated automatically for each image based on the subject name and variation context. The caption format is compatible with most LoRA training pipelines (kohya_ss, SimpleTuner, etc.). Captions can be edited manually after generation — open the caption editor from the dataset panel before finalizing.

3D Reconstruction

▶ Video breakdown — coming soon

Generates proxy 3D geometry from images — either captured photos or Qwen-generated orbital views from the LoRA Dataset Builder. The tool lives in the Utilities tab, alongside the Spec Tool and Dataset Builder.

The target output is production-useful proxy geometry: collision meshes, depth references, NeRF initialization, and geometry-informed passes for compositing. Synthetic-to-3D — driving reconstruction from generated views rather than photographs — is the workflow this exists for.

This is not photogrammetry. Qwen is a generative model, not a physically consistent renderer, so geometry across generated views is approximate by construction. For prop reference, collision meshes and compositing depth guides this is fine. For precision measurement or hero asset creation it is not.

Two Model Tiers

ModelInputOutputVRAMSpeed
TRELLISSingle imageTextured GLB mesh with baked UVs~12GB peak~55s typical
VGGT1 to hundreds of imagesGLB mesh + PLY point cloud + camera solve~13GB peak~10s inference

TRELLIS decodes Structured 3D Latents into a mesh and bakes a texture onto it. VGGT is a single feed-forward transformer that returns camera parameters, dense depth and a 3D point cloud in one pass — no pairwise matching, no global bundle adjustment. Choose TRELLIS for a fast proxy from one image; choose VGGT when you have coverage.

Image Count Guidance (VGGT)

Angular spread matters more than raw count — clustered views give diminishing returns. The panel warns live as you add or remove views.

ViewsResult
4–6Rough proxy, usable for quick geometry reference
8–12Solid object reconstruction — recommended minimum for a clean mesh
16–24Full 360° coverage with top and bottom; best results

Input Selection

Three input sources: a multi-select file browser, a folder (expanded recursively), or the Dataset Builder shortcut, which lists every generated dataset and loads its approved or generated views in one click.

Selected views appear in a vertical filmstrip between the settings and the viewport. Click any thumbnail to toggle it in or out of the solve — excluded views grey out but stay visible, so the angular spread of the full set stays readable while you narrow it down. All / None / Invert act on the whole set. Drag the splitter to trade filmstrip width against viewport size; double-click it to reset.

This matters more than it sounds. Finding a working image set is mostly elimination — bad angles, inconsistent subject scale, and views the generator rendered differently all drag the reconstruction down, and pulling them out is far quicker than re-picking the input from scratch.

Background Handling

VGGT reconstructs a scene, not an object — it assigns depth to every pixel, background included. A plain studio backdrop is textureless, so those depths are unconstrained and the model invents a curved sheet behind the subject. Across generated views those invented sheets disagree with each other, and the point cloud ends up with a shell of contradictory geometry wrapped around the subject. On a 64-view test orbit, 69% of surviving points were backdrop.

Matting your source images to alpha does not fix this on its own: VGGT composites transparency onto white before inference, which produces exactly the white background that causes the problem. FUK applies alpha after inference instead, where it works.

ModeBehaviour
Remove studio backdrop (default)Keys out bright, near-neutral pixels before meshing. A brightness slider handles pale subjects being over-cut.
Use source alpha matteUses the input images' alpha channel; falls back to backdrop keying when there is none.
Keep everythingCorrect for environment and scene captures, where the background is the subject.

Viewer

A Three.js viewport with matcap shading — deliberately minimal, since this is a proxy review tool rather than a material editor. Left-drag orbits, scroll zooms, right-drag pans. Reframe recentres on the geometry. Toggle between Solid, Wireframe and Point Cloud; when a run exports more than one format, switch which file the viewport is showing. Meshes carrying a baked texture (TRELLIS) render with it rather than matcap. Download buttons are provided per exported format.

Export Formats

FormatUse
GLB (default)Primary deliverable — mesh with vertex colours or a baked texture. Universal; imports directly into Blender, Nuke and Resolve.
PLYPoint cloud, for tools that want the raw solve rather than a surface.
OBJFor compositing workflows that prefer it over GLB.

Output Structure

cache/[project]_shot[shot]_[version]/
└── threed_vggt_001/
    ├── mesh.glb                   ← primary deliverable
    ├── pointcloud.ply             ← optional
    └── reconstruction_meta.json   ← inputs, model, settings, camera solve, timings

reconstruction_meta.json records the exact input list, so a good set of views can be reproduced or re-run against the other model tier. For VGGT it also stores the solved camera extrinsics and intrinsics for every view.

Tuning

Sensible defaults cover most runs; the Advanced panel adapts to the selected model.

ModelControlEffect
VGGTConfidence cutoffKeeps the most confident share of predicted points
VGGTBuild mesh / Poisson depthSurface reconstruction from the point cloud; higher depth captures more detail and more noise
VGGTMax pointsCaps cloud density — a dense solve is millions of points before thinning
TRELLISSeed / Steps / GuidanceStandard sampler controls
TRELLISSimplifyShare of faces removed during postprocessing
TRELLISFill holesCloses gaps by rendering the mesh from 1000 viewpoints. This is the slowest stage by far — turn it off first if a run is dragging.
TRELLISTexture sizeResolution of the baked texture (512 / 1024 / 2048)

TRELLIS runtime is dominated by mesh postprocessing, not sampling. Sampling takes about 5 seconds; simplifying, hole filling, UV unwrapping and texture baking take the rest. The raw decoded mesh is far larger than the export — routinely 600k+ vertices reduced to around 13k — and a denser one can push a run to several minutes. The console reports the raw mesh size and warns when it is large.

Installation Note

VGGT runs in FUK's main environment and needs no extra setup. TRELLIS requires CUDA extensions that conflict with FUK's PyTorch build, so it installs into its own isolated environment and runs as a subprocess — this keeps image and video generation safe from its dependencies. Run bash fuk/core/threed/install_trellis_env.sh once to build it. Until then TRELLIS shows as unavailable in the model list, with the missing pieces named; VGGT is unaffected.

Capture Rig Path

The endpoint accepts an arbitrary list of images, so a multi-camera capture rig feeds the same multi-view path with no architectural changes — the rig simply becomes another input source alongside the file browser and Dataset Builder.

App Layout

The FUK interface is a single-page application organized around a tab bar at the top, a project bar below it, and a collapsible generation history panel on the right. Each tab corresponds to a stage in the pipeline — from generation through post-processing and export.

Tab Overview

TabPurpose
StoryboardProject-level pre-production — shot list, panel grid, project tags, mood, default seeds, active LoRAs; pushes prompts into Image/Video shots
ImageText-to-image and image-to-image generation
VideoImage-to-video and controlled video generation
PreprocessGenerate conditioning maps — depth, pose, edge — from input images or video
PostprocessUpscaling and frame interpolation
LayersGenerate AOV passes — depth, normals, Cryptomatte — from an existing image or video
ExportAssemble AOV passes into multi-layer EXR files
UtilitiesModel Manager, Spec Tool, LoRA Dataset Builder, Describe & Tag and 3D Reconstruct

Typical Pipeline Flow

  1. Image or Video tab — generate the primary output
  2. Preprocess tab (optional) — extract conditioning maps if you need ControlNet on the next generation pass
  3. Layers tab (optional) — generate AOV passes from the output
  4. Postprocess tab (optional) — upscale or interpolate
  5. Export tab — assemble all passes into a deliverable EXR

Result Passing Between Tabs

Results from any tab can be dragged from the Generation History panel and dropped onto the input area of any other tab. The output path is inserted automatically. This is the primary way to chain pipeline steps — no manual file picking required.

Playback Speed

A global playback speed control (6–48 FPS) is available in the main app header. It applies to video previews across all tabs — set it to match the frame rate of your generated sequences for accurate preview timing.

Project Bar

The Project Bar sits below the tab bar and persists across all tabs. It manages the three-level hierarchy — project / shot / version — that all FUK outputs are organized under. Every save operation writes to the currently selected project, shot, and version.

Hierarchy

  • Project — top-level container; typically a film, commercial, or personal project. Maps to a directory under outputs/
  • Shot — a discrete sequence or scene within the project. Maps to a subdirectory under the project
  • Version — an individual saved result within a shot. Versions increment automatically; each version gets its own directory containing the output files and meta.json sidecar

Controls

ControlAction
Project dropdownSwitch between existing projects; opens a folder browser to select or create a project directory
Shot dropdownSwitch between shots in the current project
Version dropdownSwitch between saved versions of the current shot; selecting a version loads its metadata back into the active tab
SaveSave the current generation result to the active project/shot/version
Version UpIncrement the version number and save — preserves the previous version
New ShotCreate a new shot within the current project
New ProjectCreate a new project directory

Unsaved Changes

When a generation result is present but not yet saved, the Project Bar displays an unsaved changes indicator. Switching shots or versions without saving will prompt for confirmation.

Storyboard Tab

The Storyboard tab is FUK's project-level pre-production surface. It sits above the per-shot files rather than replacing them: each panel corresponds to one shot, the imagery and action drafts authored here get pushed into that shot's Image or Video tab, and the per-shot JSON remains the source of truth for generation settings, history, and pinned versions.

Everything on this tab autosaves on a short debounce — there are no Save buttons. The manifest lives next to your shot files as {projectname}_storyboard.json.

Layout

Two stacked sections:

  • Globals — project-wide settings that apply across every shot: project tags, mood, default seeds, active LoRAs.
  • Shots — a grid of panel cards, one per shot, plus an Add Panel card at the end.

A snapshot bar sits above both, providing dated copies of the manifest and one-click restore.

Project Tags

Reusable #markers scoped to this storyboard. Each tag has a name (becomes #name), a category (character, prop, location, other), and a value — the text that #name expands to at generation time. Type # in any storyboard or shot prompt to autocomplete against them.

Project tags shadow workspace tags on marker collision, so a project-local #sarah can override a global #sarah without touching the global tag library. Values themselves can contain other #markers — useful for layering a character description on top of a costume tag.

Mood / Setting

A single sentence merging style and environment (e.g. neo-noir, low-key lighting, rain-soaked Tokyo back alleys at night). It is appended to every shot's prompt at generation time as Mood: …, so a project-wide tone change is one edit rather than a per-shot sweep. This is the "storyboard-level prompt injection" referenced in the Prompt Panel.

Default Seeds

Optional uint32 seeds for image and video. They are baked into a new shot's seed slot the first time you Send the panel to that tab; the shot's seed then lives independently in the Image/Video Seed Control. Changing the global later does not retroactively touch shots that have already received a send. Leave blank to let each shot stay on random.

Each seed field offers Random (generate a new value) and Clear (drop back to random-per-shot) controls.

Active LoRAs

A project-wide toggle list of every LoRA discovered in your install, grouped by model family. Activating a LoRA does two things:

  • Surfaces its trigger_word as a #marker in # autocomplete across every prompt field in the project.
  • Adds any caption phrases the LoRA shipped with to the same autocomplete feed.

It does not automatically attach the LoRA to a shot's generation — the Image/Video tab's LoRA selection still controls what actually loads. Active LoRAs are an authoring affordance: they let you reference the right trigger without flipping back to model docs.

Panel Card

One card per shot. The header shows the shot ID and a save pip. The body has two columns:

  • Imagery (still) — describes the frame: composition, lighting, lens, mood, subject. Pushed to the shot's Image tab positive_prompt.
  • Action (motion) — describes motion within the shot: camera move, subject action, beat timing. Pushed to the shot's Video tab positive_prompt.
  • Duration (s) — planned shot length, for downstream edit handoff.
  • Notes — freeform director notes; storyboard-only.

Both prompt fields accept #markers from project tags, workspace tags, and active LoRAs — markers stay raw in the manifest and resolve live at generation time, so editing a tag value updates every shot that references it.

Side-by-side previews show the current image and video pinned to this panel. Drag any item from Generation History onto a preview slot to pin it — the drop also mirrors the originating prompt into the matching panel field (image → imagery, video → action). The × on a preview clears it.

Send to Image / Send to Video

Each panel has a "→ Image" and "→ Video" button with an adjacent model select. The button flushes any unsaved draft, writes the raw markered prompt into the shot file's positive_prompt, and (if the model select is set) also writes that model selection into the shot. You stay on the Storyboard tab — the Image/Video tab will reflect the change the next time you visit it. If the affected shot happens to be the one currently loaded, its in-memory state is refreshed so you don't see a stale prompt on the next visit.

The model select is per-panel and persists in the manifest. Leave it on (tab default) to keep whatever model the destination tab already had.

Send buttons are disabled when the corresponding prompt field is empty, or when the shot file does not yet exist (the card shows a no shot file warning in that case — create the shot first via Add Panel).

Add Panel

Creates a new panel and the matching shot file in one click. The shot ID must start with an alphanumeric character and may contain letters, digits, and hyphens (up to 32 chars). The new shot file appears in the Project Bar immediately.

Snapshots

The snapshot bar at the top saves a dated copy of the current manifest, lists existing snapshots in a dropdown, and restores any of them with confirmation. Snapshots are the storyboard's version-up mechanic — useful before a structural re-cut or a destructive Mood/Active-LoRA change.

Relationship to Shot Files

The storyboard does not sync bidirectionally with shot files. Send is one-way (storyboard → shot). If you edit the prompt in the Image or Video tab after sending, re-sending will overwrite that edit — version up the shot first if you want to preserve it.

API Endpoints

  • GET /api/storyboard, PUT /api/storyboard — read or replace the whole manifest.
  • GET /api/storyboard/globals, PUT /api/storyboard/globals/{mood|image_seed|video_seed|loras} — per-field global updates.
  • POST /api/storyboard/globals/tags, PUT /api/storyboard/globals/tags/{tag_id}, DELETE /api/storyboard/globals/tags/{tag_id} — project tag CRUD.
  • PUT /api/storyboard/panels/{shot_id}, DELETE /api/storyboard/panels/{shot_id} — panel upsert and delete.
  • POST /api/storyboard/panels/{shot_id}/preview — set or clear a panel's image/video preview.
  • POST /api/storyboard/panels/{shot_id}/send/image, .../send/video — push the panel's prompt into the shot file.
  • PUT /api/storyboard/sequence — reorder panels.
  • POST /api/storyboard/snapshot, GET /api/storyboard/snapshots, POST /api/storyboard/snapshots/{filename}/restore — snapshot lifecycle.

Media Input

The Media Input component (MediaUploader) is the standard file input throughout FUK. It appears in every tab that accepts an image, video, or sequence as input. All instances share the same behavior and supported formats.

Input Methods

  • Drag and drop — drag files or folders directly from your file manager onto the drop zone
  • File dialog — click the upload area to open a native file picker (via the backend tkinter dialog); supports multi-select
  • History drag — drag an item from the Generation History panel directly onto a Media Input to load that output's path without manual file picking
  • Path paste — paste a file path directly into the input field

Supported Formats

TypeExtensions
Images.png, .jpg, .jpeg, .webp, .bmp, .tiff, .exr, .dpx
Video.mp4, .mov, .avi, .mkv, .webm
Image SequencesA directory containing sequentially named image files; FUK detects naming patterns like ####.png or %04d.png automatically

Dimension Detection

When an image or sequence is loaded, FUK reads its dimensions automatically. Tabs that derive their output resolution from the input (Video, Preprocess, Postprocess) update their dimension display immediately. The Image tab displays a warning if the input dimensions don't align to the model's required 16px grid, and offers a "Pad to [size]" button to adjust automatically.

Seed Control

▶ Video breakdown — coming soon

The Seed Control component appears in the Image and Video tabs. It manages the randomness seed used during generation — the single most important parameter for reproducibility.

Modes

ModeBehavior
RandomA new random seed is generated each time you generate. Use this when exploring — every result will be different even with identical settings
FixedThe same seed is used for every generation. Combined with identical parameters, this produces identical results — the basis for repeatable output
IncrementThe seed increments by 1 after each generation. Useful for batch exploration — you get a sequence of related but distinct results

Controls

  • Seed input — visible in Fixed and Increment modes; enter any integer
  • Randomize button (dice icon) — generates a new random seed and puts it in the field; available in Fixed and Increment modes so you can start from a random point while still locking in repeatability
  • Save to favorites (star button) — saves the current seed with an optional label; saved seeds persist across sessions
  • Saved seeds dropdown — load any previously saved seed in one click

Favorites

Favorite seeds are stored in local settings and persist across sessions. Add a descriptive note when saving a seed — the note appears in the dropdown, making it easy to identify which seed produced a specific result without having to cross-reference the History Panel.

Model & LoRA Selection

▶ Video breakdown — coming soon

The Model & Style card appears in both the Image and Video tabs. It selects the base model a generation runs on and layers one or more LoRA adapters on top. The controls behave the same across both tabs — the only difference is that the Image tab can stack multiple LoRAs while the Video tab takes one at a time.

Model Dropdown

  • Lists every model registered in models.json whose category matches the current tab — image models in the Image tab, video models in the Video tab.
  • Settings are persisted per-model — your parameters and LoRA stack are remembered separately for each model, so switching back and forth never clobbers the configuration you had for either.
  • The active model determines which LoRAs are offered: the LoRA dropdown is filtered to the model's family, so a Qwen model won't list Wan-only adapters and vice versa.

LoRA Controls

LoRAs blend a trained concept into the base model at generation time. Each LoRA row exposes:

ControlBehavior
LoRA dropdownSelects an adapter. The list is built from the discovery directories and explicit entries in defaults_loras.json, filtered to the active model's family
MultiplierBlend weight, 0.0–2.0. Starts at the LoRA's default_strength if one is configured, otherwise 1.0. Higher values push the concept harder; overly high values can overcook the result
Bypass toggleTemporarily disables the LoRA without removing it — the fast way to A/B whether an adapter is actually helping
RemoveDrops the LoRA row entirely

Single vs. Stacked

  • Image tab — use the add button to stack multiple LoRAs; they blend together, each with its own multiplier and bypass toggle.
  • Video tab — one LoRA at a time, with the same multiplier and bypass controls.

Trigger Words

If a selected LoRA defines a trigger_word in its config, it is surfaced as a hint but not injected automatically — you still add it to your prompt yourself, or via the Prompt Panel shorthand where each LoRA trigger becomes a #marker. A LoRA that defines inject_text has that text appended to the positive prompt whenever it is active. See defaults_loras.json for how both are configured.

LoRAs are matched to models by family in defaults_loras.json. If an adapter you expect isn't in the dropdown, check that its model field matches the family of the model you currently have selected.

VRAM Management

▶ Video breakdown — coming soon

The VRAM Management dropdown lives in the Generation card of both the Image and Video tabs (and in the Postprocess Panel). It selects the offload strategy FUK uses to fit a model into available GPU memory. The trade-off is always the same: the more of the model that is offloaded to system RAM or disk, the lower the VRAM floor and the slower the generation.

Presets

PresetStrategyVRAM RequiredSpeed Impact
NoneNo offloading — full model in VRAM48GB+Fastest
LowCPU offload in bfloat1616–24GBMinimal
MediumCPU offload in float812–16GBModerate
HighDisk offload8GBSignificant — requires a fast SSD

How to Choose

  • Start at the lowest offload level your card can hold and only move up if you hit out-of-memory errors.
  • Larger output resolutions — and, for video, longer frame counts — raise the VRAM ceiling, so a preset that works for a short clip may need bumping up for a longer one.
  • High (disk offload) is a last resort for 8GB cards; it leans on SSD read speed and is dramatically slower than the CPU-offload presets.

The dropdown overrides the launch default for the current session only — it does not persist to disk. The persistent default and advanced knobs like buffer_gb (activation headroom; raise it if you OOM mid-generation) and computation_dtype live in defaults_vram.json.

Image Panel

The Image tab is the primary generation interface. Its layout is divided into a preview area on the left and a column of parameter cards on the right. See Image Generation for the pipeline overview, supported models, and parameter reference.

Preview Area

Displays the current generation result in a zoomable, pannable viewer. Shows the output dimensions and generation time. When no result is present, the placeholder displays the configured target dimensions. History items can be dragged from the Generation History panel and dropped here to reload their metadata into all parameter cards.

Image Tools Card

Visible when an edit, context, EliGen or inpaint-capable model is selected. Contains controls for reference image input:

  • Control Images — Media Input for one or more reference images used as conditioning; supports multi-image upload
  • Edit Strength — how much the model deviates from the reference (0.0 = identical to reference, 1.0 = freely interprets); range 0.0–1.0
  • Context Image (EliGen models) — optional scene-level reference; EliGen alpha (0.0–2.0) controls its influence
  • Entity Masks (EliGen models) — path to a .psd or .ora file containing per-zone masks; each layer becomes an independent conditioning zone
  • Inpaint Image (inpaint-capable models) — the picture to repaint; sets the output size. Once loaded it reveals a Mask slot, the Paint Mask button, Mask Feather and Keep original pixels outside the mask. See Inpainting

See Regional Conditioning (EliGen) for how zones are composited during denoising and how to author the mask files.

Model & Style Card

  • Model dropdown — selects the active image model; the available list is populated from config/models.json; settings are persisted per-model so switching models doesn't lose your configuration for either
  • LoRA section — add multiple LoRAs via the add button; each LoRA has its own dropdown (selects from models/loras/), multiplier (0.0–2.0), bypass toggle, and remove button; bypass lets you quickly A/B a LoRA without removing it from the list

Generation Card

  • Steps — preset buttons (20, 40) or custom input (1–100)
  • Guidance Scale — prompt adherence, 1.0–10.0
  • Exponential Shift Mu — optional; adjusts noise schedule shift; leave blank for model default or enable auto-calculation
  • VRAM Management — preset dropdown controlling the model offloading strategy; higher offload settings reduce VRAM usage at the cost of generation speed

Dimensions Card

For text-to-image models:

  • Aspect Ratio — dropdown of common ratios; changing it recalculates height automatically
  • Width — input in pixels (512–2048), snaps to 16px; height is calculated from the aspect ratio

For edit/context models, the Dimensions card instead shows the source image dimensions and flags any 16px alignment issues with a "Pad to [size]" button.

Prompt Card

Auto-resizing textareas for the positive prompt and negative prompt. Both expand as you type — no fixed height limit.

Footer

Generate button (disabled until a prompt is entered), batch count control, and a generation progress indicator. Clicking Generate opens the generation modal with a live console and progress bar.

Video Panel

The Video tab drives Wan I2V and Fun Control video generation. Its layout mirrors the Image tab — preview on the left, parameter cards on the right.

Preview Area

A full video player with playback controls, loop, and autoplay. Displays output dimensions, frame count, and duration. The playback speed respects the global FPS setting in the app header. History items can be dropped here to reload metadata.

Input Images Card

Content depends on the selected task:

  • Start Image (I2V) — required; the first frame of the video; Media Input; detected dimensions are shown and used to calculate output resolution
  • End Image (I2V, optional) — if provided, the video will transition toward this image as the final frame
  • Control Video (Fun Control) — required; a reference video that guides the motion and structure of the output; accepts video files or frame sequences
  • Outpaint (Wan 2.2 VACE) — turns the control video into the Source Video to extend, and reveals Output Aspect, Source Scale, Horizontal, Vertical and Edge Feather. See Outpainting

Frame Settings Card

  • Frame Count — total frames to generate; must land on the selected model's frame lattice (Wan 4n+1 from 5, LTX-2.5 8n+1 from 9, MiniMax-H3 17n+5 from 22). The input's step size and label follow the chosen model, and out-of-lattice values are flagged inline with the count they will round up to
  • Frame Inherit — when enabled and a control video is loaded, frame count is set automatically to match the control video's length
  • Trim Frames — optional upper limit; clips the output at this frame count even if more were generated
  • Frame Duration display — shows the calculated duration in seconds and milliseconds based on frame count and the global playback FPS setting

Dimensions Card

  • Source dimensions — read from the start image; displayed for reference
  • Scale Factor — 100%, 75%, 50%, or 25%; output resolution is calculated from the source dimensions × scale factor, rounded to the nearest 64px

Model & Settings Card

  • Task dropdown — selects the video pipeline (I2V-A14B, Fun Control, etc.)
  • LoRA — single LoRA with multiplier and bypass toggle (video generation supports one LoRA at a time)

Generation Card

Steps, Guidance Scale, Sigma Shift, Motion Bucket ID, Denoising Strength, Sliding Window Size/Stride, and VRAM Management — see Video Generation for parameter descriptions.

Preprocess Panel

The Preprocess tab converts input images or videos into conditioning maps — depth, pose skeleton, or edge maps — for use as ControlNet inputs in the Image tab. Preprocessing is a separate step from generation so you can reuse a conditioning map across many generations without recomputing it.

Layout

A method selector at the top (Canny / OpenPose / Depth) switches between preprocessing modes. Below it: an input section with a Media Input, method-specific parameter controls, and a before/after result preview.

Video Mode

When a video or frame sequence is loaded, the panel switches to video mode. Preprocessing runs per-frame and outputs a new sequence. The output mode setting controls whether the result is saved as an MP4, a frame sequence, or both.

Method Parameters

See Preprocessors for full descriptions of each method's parameters.

Result Display

The before/after preview shows the original input alongside the preprocessed output. For video, a frame counter lets you step through the sequence to verify quality before committing to a full run.

Postprocess Panel

The Postprocess tab handles upscaling, frame interpolation, and SDR → HDR conversion. Each saves its output as a new versioned result alongside the original.

Work in progress. These are the least mature passes in FUK, and the licensing constraint behind that is worth understanding before you rely on them — see Post-Processors.

Upscale Tab

  • Input — Media Input; accepts images, videos, or frame sequences
  • Method — upscaling model selector. Video offers SeedVR2 (temporal, the default), Real-ESRGAN and Lanczos; stills offer Real-ESRGAN and Lanczos. Choosing SeedVR2 reveals its quality, frame window, resolution cap and memory mode controls.
  • Factor — scale multiplier: 2×, 4× or 8×

The result preview shows a before/after comparison. For video, the comparison is shown at the current frame. See Upscaling for available models.

Frame Interpolation Tab

  • Input — frame sequence or video file
  • Method — interpolation model (FILM)
  • Source Framerate — the frame rate of the input sequence; must be set correctly for the output to play at the right speed
  • Target Framerate — desired output frame rate; FILM synthesizes as many intermediate frames as needed
  • Video Output Mode — whether to generate an MP4 preview alongside the output sequence

See Frame Interpolation for more detail.

SDR → HDR Tab

  • Input: an SDR video file
  • EXR Colour Space: ACEScg (recommended), Linear Rec.709 / sRGB, or ACEScct
  • Seam Keyframes: on at 0.95 (trained default) or off
  • Quality: Standard, or High (2× frames internally, ~2× time)
  • Memory Mode: Auto, Resident FP8, or CPU offload

The preview plays a tonemapped SDR copy; the EXR sequence and HLG master are the real outputs. If the model or its dependencies are missing, the panel says which and how to install them. See SDR → HDR for more detail.

Layers Panel

The Layers tab generates AOV passes — depth maps, surface normals, and Cryptomatte segmentation — from an existing image or video. This is a post-generation step: you bring your finished beauty output here and extract the technical passes needed for compositing.

Work in progress. These passes are inferred from a finished image, not rendered from geometry, and the models available under a commercially usable open-source licence do not match the pass quality of a production renderer. See AOVs & Passes for detail on the limitations.

Input

A Media Input at the top of the panel accepts a single image, video, or frame sequence. Drop a result from the Generation History to load it automatically.

Layer Selection Card

Checkboxes for each available pass: Depth, Normals, Cryptomatte. Only the checked passes are computed — disable passes you don't need to save processing time.

Depth Settings Card

  • Model — Depth Anything v3 variant: da3_mono_large, da3_metric_large, da3_large, da3_giant; larger models are more accurate but slower
  • Invert — flips near/far encoding
  • Normalize — stretches depth values to fill the 0–1 range
  • Range Min / Max — clamps the output depth range; useful for isolating a specific depth band

Normals Settings Card

  • Method — from_depth derives normals from the depth pass; scratch estimates normals directly from the image
  • Depth Model — which DA3 variant to use for the depth step (only relevant when method is from_depth)
  • Space — tangent (surface-relative) or world (camera-relative) normal encoding
  • Flip Y — flips the Y axis of the normal map; required by some compositing applications
  • Intensity — normal map contrast/strength (0.0–2.0)
  • Num Iterations — refinement passes for the normal estimation (1–20); more iterations improve accuracy at the cost of speed
  • FOV Degrees — assumed camera field of view used in the depth-to-normal conversion (1–180)
  • First Frame Only — when processing video, compute normals only for the first frame; useful for quick checks before a full run

Cryptomatte Settings Card

  • Model — SAM2 variant used for object segmentation (sam2_hiera_large)
  • Max Objects — maximum number of distinct objects to segment and track
  • Min Area — minimum object size in pixels; objects smaller than this threshold are ignored

Result Display

Generated passes are shown as individual previews below the settings. Each pass can be inspected at full resolution before being passed to the Export Panel.

Export Panel

The Export tab assembles beauty and AOV pass images into multi-layer EXR files ready for professional compositing pipelines. Each pass is loaded independently — you can mix outputs from different generation runs if needed. See EXR Export for the layer structure and compatible applications.

Layer Inputs Card

Four inline image inputs, one per pass:

  • Beauty — the primary generation output (RGBA)
  • Depth — depth pass from the Layers Panel
  • Normals — normals pass from the Layers Panel
  • Crypto — Cryptomatte pass from the Layers Panel

Only layers with a loaded input are included in the export. Drop passes from the Generation History to load paths automatically. When sequence inputs are detected, the panel switches to video mode and exports per-frame EXRs.

Save Location Card

  • Export path — destination directory; click Browse Folder to select via file dialog
  • Create New Folder — create a subdirectory within the export path in one step
  • Filename pattern — output filename template; supports {name} (source filename without extension) and {frame:04d} (zero-padded frame number)
  • Sequence start frame — the frame number assigned to the first file in the export; useful when offsetting into a larger sequence

Export Format Card

  • Multi-Layer EXR — all passes in a single file per frame; the preferred format for professional compositing
  • Single-Layer EXRs — one file per pass per frame; use when your compositing application doesn't support multi-layer EXR

EXR Settings Card

  • Bit Depth — 8, 16, or 32-bit per channel; 32-bit recommended for depth and normals passes to preserve floating-point precision
  • Compression — ZIP (good for smooth gradients), PIZ (efficient for noisy/grainy content), RLE (fast, lower compression ratio)
  • Color — the output color space for the beauty pass. AOVs are never transformed, whatever this is set to

Color space

The dropdown is populated from the OCIO config this machine resolved, not from a fixed list — so a target your config cannot deliver never appears as an option. See EXR Export → Color Management for what each target is and how the config is resolved.

  • Linear is the default and stays the default. It is scene-linear Rec.709 and is pixel-identical to what FUK has always written; existing projects do not change color space when they are re-exported. It now also carries a chromaticities header so Nuke interprets it without being told
  • ACEScg is the pick for an ACES pipeline. Select it once and both still and sequence exports follow — the setting is sent with both, so a still and its sequence from the same generation cannot silently end up in different spaces
  • sRGB writes display-referred values into the EXR with no transform. Rarely what you want in a comp, but it is there for round-tripping

Below the dropdown is a status line naming the OCIO version, where the config came from (env, settings or builtin) and its path. It is worth a glance before a delivery: it is how you confirm FUK picked up the facility config and did not quietly fall back to the built-in one. If OpenColorIO is not installed, the line says so and only Linear and sRGB are offered.

Hovering the dropdown explains the source assumption: output is treated as sRGB-encoded because that is what the model was trained on.

If a project was saved with a target this machine can no longer deliver — a config changed, or OpenColorIO was removed — the dropdown keeps showing it, marked unavailable, and the export falls back to Linear with a warning in the result rather than failing or silently substituting.

Channels Card

A visual guide showing which input layer maps to which EXR channel group — useful for verifying the layer mapping before committing to a full export run.

Spec Tool

The Spec Tool lives in the Utilities tab. AI generation spec dimensions have non-obvious constraints — models are trained on specific aspect ratios and resolution buckets, and going outside those ranges degrades output quality. The Spec Tool provides a guided way to create valid generation specs and downloadable composition guide templates.

Spec Configuration

  • Target Model — which video family the spec has to be valid for: Wan, LTX-2.5 or MiniMax-H3. This drives every snap below, because the three disagree on both the latent grid and the frame lattice — see Per-Model Constraints. The header shows the active grid, lattice and frame rate at a glance. LTX-2.5 adds a Two-stage checkbox, since that mode halves the size before its own alignment check and so needs a 64px grid rather than 32px. Switching family re-snaps the frame count and follows that model's frame rate, so a 41-frame Wan spec becomes 56 frames on MiniMax-H3
  • Aspect Ratio — preset dropdown (1:1, 4:3, 16:9, 1.85:1, 2.35:1, 2.39:1, 21:9) or custom W:H input
  • Resolution Width — input in pixels; height is calculated from the aspect ratio, then both round up to the target model's grid. The badge names the multiple that was applied. A 1.85:1 plate at 1920 wide lands at 1920×1040 for Wan, 1920×1056 for LTX-2.5 and MiniMax-H3, and 1920×1088 for LTX-2.5 two-stage
  • Frame Count — for video specs; snaps up to the target model's lattice (Wan 4n+1 from 5, LTX-2.5 8n+1 from 9, MiniMax-H3 17n+5 from 22), with the resulting duration shown beside it at the model's frame rate

The family list is read from the model registry rather than hardcoded, so registering a fourth video family makes it selectable here with no UI change. The exported PNG and the .blend scene both carry the target model in their filename and settings, so specs cut for different models don't get mixed up in the same folder.

Composition Guides

Overlay composition guides on the canvas preview and burn them into the downloadable template:

  • Rule of Thirds
  • Golden Spiral
  • Vanishing Points
  • Action Safe
  • Title Safe
  • Center Cross

Guide color and background color are configurable via color pickers. Background alpha controls transparency of the canvas (set to 0 for a transparent PNG template).

Actions

  • Download PNG — exports the canvas at the configured resolution with the selected guides burned in; use as a layout reference or import into your generation workflow as a composition guide image
  • Save Blender Template — exports the spec as a Blender scene template at the target resolution and frame count

Burn In

When enabled, frame numbers are rendered onto each frame of the Blender template output — useful for editorial reference when working with a delivery spec that has a specific frame count.

Model Manager

▶ Video breakdown — coming soon

Lives in Utilities → Models. It replaces download_models.sh as the normal way to acquire and enable models — the script stays for headless runs, and both agree on what "complete" means because the panel reuses its target list.

The panel has two halves that behave differently on purpose.

Tools

Read-only status, green or red. Each row reports through the same availability check the feature itself uses, so the panel cannot drift from what the feature believes. These are installed by setup.sh, not from here — a red row tells you what is missing and the command that fixes it.

ToolBacks
OllamaDescribe & Tag and the prompt LLM features
SeedVR2Temporal video restoration in Postprocess
TRELLISSingle-image 3D reconstruction
VGGTMulti-view 3D reconstruction
SAM2Mask and cryptomatte preprocessors
Depth Anything 3Depth control passes and the depth AOV
DSINESurface normals. Non-commercial weights

Models

Every entry in models.json, with a download button and an active checkbox.

  • Active checkbox — unchecking unregisters the model. It disappears from the generation dropdowns immediately but stays listed here, so turning it back on is one click and never needs a re-download. This writes enabled into models.json; entries without that field are treated as enabled, so nothing predating the panel changed behaviour.
  • Download — runs in the background with per-component progress. HuggingFace is preferred because it is faster and steadier, with a per-component fallback to ModelScope for the repos HF does not carry. Already-present files are skipped, so an interrupted download resumes by re-running it.
  • Projected size — what a download would actually pull, which is not the same as the model's total. Anything sharing files with a model you already have pulls less: Krea-2 reports about 32.8 GB to fetch of 33.0 GB total, because the Qwen-Image VAE is already on disk.
  • Where the weights go — expands to the HuggingFace and ModelScope links, the exact install path, and a per-component present/missing breakdown, for when fetching something by hand is easier.
  • Optional LoRAs — where a model's function variants ship as LoRAs on its shared base rather than as models of their own, they are listed under it. Today that is LTX-2.5, whose in-context upscaler is ticked and fetched on its own, priced before you commit. They are optional by definition, so they never count toward whether the model itself is complete, and they land in the LoRA directory rather than the model cache — symlinked out of that cache, so a LoRA costs its size once. Downloaded ones show a size and stay listed rather than disappearing, so the set reads as a whole.

Deleting weights

Models can be removed from disk from the same row. Deletion is share-aware, and that matters more than it sounds: the Qwen-Image VAE backs eight models and the Wan T5 encoder five, so removing a model naively would take shared components with it and break most of the registry. A component used by any other entry is never deleted, and the panel names the models keeping it.

It is a two-step action. The first click asks for a plan — what goes, what is kept and why, how much is reclaimed — and removes nothing. Only confirming that plan deletes anything, and nothing is recoverable except by re-downloading. Any pipeline currently loaded for the model is evicted first, so weights never vanish underneath a live pipeline.

Adding a model

The panel lists what is in the registry; it does not invent entries. Adding a new model is still a models.json edit, after which it appears here ready to download.

Prompt Panel

▶ Video breakdown — coming soon

The Prompt Panel is the floating control in every Image and Video tab where you author the positive and negative prompt. It is more than a textarea: it unifies your saved prompt tags, the trigger words of installed LoRAs, and caption analyses exported from the LoRA builder into a single shorthand vocabulary. From that vocabulary you have three ways to build a prompt — fast inline shorthand, structured slot picks, or an LLM refinement — and they all share the same source of truth.

The Three Modes

  • Inline shorthand (# autocomplete) — type # in the prompt textarea and a dropdown of matching tokens appears above the field. Selecting one inserts a marker (e.g. #noir) at the caret. Markers stay in the text as you write — they're expanded later on Compile or Expand.
  • Slot picker — toggle Slots in the header to open a category grid of available tokens. Drilling into a category lists every token in it; clicking one drops it into the Style chip tray below the prompt rather than into the textarea inline. This keeps subject/action language in the main field and accumulates style intent separately so Compile can produce a disciplined two-paragraph prompt.
  • LLM refine (Expand) — sends your current draft plus style chips plus the same vocabulary to qwen3-vl:8b and asks it to refine the text into a cinematographer-grade prompt. The model is instructed to use vocabulary phrases verbatim and preserve your existing intent rather than rewrite from scratch.

The Vocabulary

Every dropdown and slot list draws from one combined token list. Source badges identify where each came from:

  • tag — your saved entries from the Describe & Tag tool. Edit them at fuk/ui/data/prompt_tags.json or via the Describe & Tag UI.
  • lora — synthesized from fuk/config/defaults_loras.json. Each entry's trigger_word becomes a marker, and its inject_text becomes the expansion. The list is filtered by the current model's family (a Qwen tab won't see Wan-only LoRAs).
  • phrase — top bigrams and trigrams imported from caption analyses dropped in fuk/ui/data/lora_captions/ by the standalone LoRA builder. These only appear when the matching LoRA is active in the model panel. They have no marker — they insert as raw text since they're already short natural-language phrases.

Compile (Deterministic)

Compile expands every #marker in the textarea against the vocabulary, then appends a trailing Style: … sentence built from the chip tray. The result is written back to the textarea and the chip tray clears. No LLM is involved.

  • If the textarea already ends in . ! or ? the punctuation isn't doubled.
  • A blank line separates the main paragraph from the Style: sentence so the textarea reads as two paragraphs.
  • Unknown markers (no matching tag or LoRA) stay in place and surface as a warning under the textarea.
  • If an active LoRA's trigger word never appears in the prompt, the response includes missing_lora_triggers — the UI doesn't auto-inject anything, but it's there so a future check could surface it.

Expand (LLM)

Expand runs the same Compile step internally to produce a concrete draft, then sends that draft along with the vocabulary list to qwen3-vl:8b. The system prompt instructs the model to:

  • Refine the draft rather than rewrite it
  • Use vocabulary phrases verbatim where they apply
  • Preserve the Style: sentence as authoritative
  • Add motion language for Video tabs; suppress it for Image tabs
  • Return JSON: { positive, negative, notes? }

On success the textarea is replaced with the model's positive prompt, the negative prompt is updated only if the model provided one, the chip tray clears, and any notes appear as a dismissible note under the warning row. Requires Ollama running and qwen3-vl:8b pulled — see Describe & Tag for setup. Every request uses keep_alive: 0 so the LLM is evicted from VRAM immediately and the generation pipeline gets it back.

Style Chips

The chip tray appears below the prompt textarea whenever slot picks accumulate. Each chip shows the token's display name; hover for its expansion. Click the × on a chip to remove it, or clear on the tray header to drop them all. Chips persist visually until Compile or Expand bakes them into the textarea — at which point the tray clears.

Chips don't persist across shot switches in v1; they live only in panel state. For project-wide style injection (apply a sentence to every shot in a sequence), use the Mood field on the Storyboard tab — it appends to every shot's prompt at generation time.

Disabling States

  • Compile is enabled when the prompt contains at least one #marker or there is at least one style chip.
  • Expand is enabled when the prompt has any non-empty text or at least one style chip.
  • Both buttons are disabled while a generation is running on the host tab.

Tag Marker Format

Markers are lowercased, slug-safe versions of the token name: spaces become _, and only letters/digits/underscore/hyphen are allowed in the body. A tag named Low Key becomes #low_key. LoRA markers come straight from each entry's trigger_word field, so however you spell the trigger in defaults_loras.json is the marker you type.

Marker collisions resolve in this order, first match wins: tags, then LoRA triggers. That means a user-authored tag of the same name overrides the auto-generated LoRA shorthand — useful when you want to swap a LoRA's default inject_text for your own phrasing without touching the LoRA config.

API Endpoints

  • GET /api/prompt/tokens?model=…&active_loras=… — unified token feed: tags + family-filtered LoRA triggers + caption phrases (only for active LoRAs). Returns { tokens, categories, model_family, active_lora_triggers }.
  • POST /api/prompt/compile — deterministic expansion. Body { text, model?, active_loras?, style_chips?, style_label? }, returns { compiled, expanded_markers, unknown_markers, missing_lora_triggers, style_sentence }.
  • POST /api/prompt/expand — LLM refinement. Body { text, model?, active_loras?, style_chips?, mode, intent? }, returns { positive, negative, notes?, model, mode }.

Describe & Tag

The Describe & Tag tool lives in the Utilities tab. It is the first slice of FUK's LLM integration: a vision-language model (Ollama-hosted) writes a cinematographer-style description of any image or short video clip, and lets you save fragments of that description as named prompt-shorthand tags for reuse later in the pipeline.

Requirements

  • Ollama running locally (default http://localhost:11434). FUK does not spawn or manage it — start ollama serve separately
  • The configured vision model pulled: ollama pull qwen3-vl:8b (≈6 GB on disk, ≈6–7 GB VRAM at runtime)
  • The health indicator at the top of the tool reports green when both conditions are met

Override the model with FUK_LLM_MODEL and the host with OLLAMA_HOST environment variables. Every request uses keep_alive: 0 so the LLM is evicted from VRAM immediately after each call, leaving room for the generation pipeline.

Describe an Image

  1. Click the drop zone to open a native file dialog and pick any image
  2. Click Describe Image — the image is downscaled to 1024px JPEG and sent to the model
  3. The result lands in an editable textarea so you can refine wording before tagging

Describe a Video

The same tool handles short video clips. Selecting a video file (.mp4 .mov .webm .mkv .avi .m4v) switches the preview to a playable video and the run button to Describe Video.

  • Six frames are sampled evenly across the clip at 512px each and sent as a single multi-frame request
  • A video-specific system prompt asks the model to treat the frames as one continuous shot and describe camera movement and how the action evolves — not the frames in isolation
  • The response includes the number of frames used, and the timeout extends to 120 s for the multi-frame call

Prompt Tags

Tags are reusable shorthand for chunks of prompt text. They live in fuk/ui/data/prompt_tags.json and persist across sessions. Future prompt-construction and storyboard features will expand tag names back into their full value when assembling prompts.

Saving a Tag from a Description

  1. Highlight any span of text in the description textarea (for example, the sentence describing the subject)
  2. Click Tag selection — the highlighted text drops into the tag form's Value field
  3. Give it a short name (e.g. fat man), pick a category, click Save Tag

The Tag all button uses the full description as the value instead. Tags can also be created manually by typing name and value directly.

Tag Fields

  • Name — 1–64 characters, letters/digits/space/underscore/hyphen. Stored lowercase, must be unique
  • Category — picked from the preset list (see below); optional, can be left as uncategorized
  • Value — up to 4000 characters of free text

Categories

Categories keep the tag list organized once it grows. The starter set:

  • composition — framing, shot type
  • subject — character/object descriptions
  • lighting — key, fill, mood, time of day
  • camera — angle, lens, movement
  • color — palette, grading
  • style — film stock, era, art direction
  • atmosphere — weather, ambient feel
  • setting — location, environment

The category list is user-editable at fuk/ui/data/prompt_tag_categories.json. The file is auto-seeded on first run; add, rename, or remove entries and reload the tab to refresh. Tags assigned to a category that you later remove will be flagged on save until you reassign them.

Managing Tags

The tag list at the bottom of the panel supports:

  • Category filter — dropdown with live counts per category and an uncategorized bucket
  • Text filter — matches against name, category, and value
  • Edit — loads a tag into the form for in-place changes
  • Delete — trash-can icon with a confirmation prompt

API Endpoints

Exposed under /api for use by future features and external tooling:

  • GET /api/llm/health — Ollama reachability and whether the configured model is pulled
  • POST /api/llm/describe — body { image_path }, dispatches image or video by extension, returns { description, kind, frames_used? }
  • GET /api/tags — list all tags, sorted by category then name
  • POST /api/tags — create { name, value, category? }
  • PUT /api/tags/{id} — update
  • DELETE /api/tags/{id} — remove
  • GET /api/tags/categories — the current category list

Generation History

The Generation History is a collapsible side panel available from any tab. It shows all previous generation outputs for the current session and provides drag-and-drop access to any result — the primary way to chain pipeline steps without manual file picking.

Panel Contents

  • Thumbnail grid of all generation results from the current session, most recent first
  • Each thumbnail shows the output type (image, video, preprocessed map, etc.) and basic metadata on hover: seed, model, timestamp
  • Video thumbnails play on hover at the global playback FPS

Drag and Drop

Any history item can be dragged onto:

  • A tab's preview area — reloads all metadata from that result into the active tab's parameter cards, including model, prompt, seed, LoRA settings, and dimensions
  • A Media Input component in any tab — inserts the file path directly as the input, without loading metadata

This is the standard workflow for passing results between pipeline steps — generate in Image, drag to Layers for AOV extraction, drag from Layers to Export for EXR assembly.

Quick Save

Every history item carries a Save action that copies its output to a location of your choosing without leaving the app. The button opens a native "Save As" dialog and writes a copy of the rendered result — the PNG for an image, or the composited MP4 for a video — to the target path, leaving the original version directory untouched. It appears as a compact icon on each thumbnail's action bar and as a labeled button in the fullscreen gallery detail panel, so you can hand a single result off to a client, review folder, or scratch directory without walking the project hierarchy by hand.

Playback Speed

The global playback speed control (6–48 FPS) in the app header affects video thumbnail playback in the history panel. Set it to match your generation frame rate for accurate motion preview.

Config Overview

All FUK configuration lives in fuk/config/ as plain JSON files. There are no environment variables, no hidden settings, and no GUI-only config — everything that affects generation behaviour is readable and editable in these files. Changes take effect on the next launch unless noted otherwise.

File Map

FilePurposeHow Often You'll Edit It
defaults.jsonGlobal generation defaults — model paths, image/video parameters, project settingsInitial setup + ongoing tuning
models.jsonModel registry — which models are available in the UI and how to run themWhen adding or removing models
defaults_vram.jsonGPU memory offloading strategy — which preset to use based on your VRAMOnce at setup, unless you change hardware
defaults_loras.jsonLoRA adapter registry — paths, target models, trigger wordsWhen adding new LoRAs
defaults_dataset.jsonLoRA Dataset Builder — angle, lighting, and variation templatesWhen customising dataset generation
defaults_spec_tool.jsonSpec Tool defaults — aspect ratios, guide overlays, burn-in settingsRarely; UI persists changes automatically
tools/depth-anything-v3.jsonDA3 depth estimation — model variants and inference settingsRarely
tools/sam2.jsonSAM2 segmentation — model variants and auto-mask thresholdsRarely

Editing Guidelines

  • All files are UTF-8 JSON — standard JSON rules apply (no trailing commas, no comments)
  • String paths can use ~ for home directory expansion
  • FUK validates config on startup and will log a specific error for any missing or malformed key
  • The UI persists some per-session overrides in localStorage — if a UI setting seems to ignore your config edit, clear the browser's local storage for the FUK origin
  • Back up defaults.json and models.json before making large changes; both are easy to break in ways that prevent startup

defaults.json

The primary configuration file. Sets generation defaults for all pipelines, the model root path, aspect ratio presets, project management behaviour, and paths to external tools. Located at fuk/config/defaults.json.

models_root

Root directory where all downloaded AI models are stored. All paths in models.json are resolved relative to this.

"models_root": "/home/brad/ai/models"

Change this if your models live on an external drive or network share. The path must be absolute.

aspect_ratios

Array of aspect ratio presets available in the Image and Spec Tool panels. Each entry has a label displayed in the UI, a value used internally, and a ratio float used to calculate height from width.

{ "label": "2.39:1 Anamorphic", "value": "2.39:1", "ratio": 0.418 }

Add entries here to make custom ratios available in all dropdowns. The ratio field is height/width — for 16:9 that's 0.5625.

image

Default values for every control in the Image Panel. These are the values the UI loads when no project state or localStorage override exists.

KeyTypeDefaultDescription
modelstring"qwen_image"Model key — must match an entry in models.json
widthinteger1280Output width in pixels; height is derived from aspectRatio
aspectRatiostring"2.39:1"Must match a value in the aspect_ratios array
stepsinteger20Denoising steps
stepsModestring"preset""preset" or "custom"
guidance_scalefloat4.0Prompt adherence; 1.0–10.0
denoising_strengthfloat1.01.0 = full generation; lower values are for img2img
lorastring / nullnullDefault LoRA key; null = none
lora_multiplierfloat1.0LoRA blend weight
seedinteger / nullnullnull = random on each run
seedModestring"random""random", "fixed", or "increment"
negative_promptstring(quality list)Default negative prompt applied to every generation
save_latentbooleantrueSave latent representation alongside image output

video

Default values for the Video Panel. Key fields:

KeyTypeDefaultDescription
taskstring"wan_i2v_a14b"Active pipeline; must match a task in models.json
video_lengthinteger41Frame count; must land on the model's lattice — Wan 4n+1 (5, 9, 13… 41…), LTX-2.5 8n+1 (9, 17… 121…), MiniMax-H3 17n+5 (22, 39… 124…). Out-of-lattice values round up
scale_factorfloat1.0Output resolution as fraction of input image (0.25–1.0)
stepsinteger20Denoising steps
guidance_scalefloat5.0Prompt adherence
sigma_shiftfloat5.0Noise schedule shift; model-specific, leave at default unless you know the target value
switch_dit_boundaryfloat0.875Dual-DiT handoff point; timesteps below this (×1000) run on the low-noise DiT. A14B models only
denoising_strengthfloat1.0Deviation from input image (img2vid modes)

flux2

Defaults used when a FLUX.2 model is active. FLUX uses lower CFG than Qwen models and needs more steps — the defaults here reflect that:

"flux2": {
    "width": 1024,
    "steps": 30,
    "cfg_scale": 1.0,
    "embedded_guidance": 4.0
}

export

KeyDefaultDescription
prefer_latenttrueSave latent vectors alongside outputs; enables faster post-processing passes
exr_compression"ZIP"EXR compression codec; ZIP, PIZ, RLE, NONE
exr_precision"float32"Bit depth for EXR export; float32 or float16

project

KeyDefaultDescription
shot_label"shot"Prefix used when auto-naming new shots
versioning"DATE""DATE" for date-based version IDs; "NUMERIC" for sequential integers
autosave_interval30Seconds between automatic project saves
cache_cleanup_days7Age in days at which cache files are deleted on startup

tools

"tools": {
    "blender": "/usr/bin/blender",
    "blender_template": "/path/to/template.blend"
}

Path to the Blender executable and a default .blend template file used by the Spec Tool's "Save Blender Template" action. Update blender if Blender is installed in a non-standard location.

models.json

The model registry. Defines every AI model FUK knows about — what pipeline runs it, what files it needs, what parameters it accepts, and what features it supports. Located at fuk/config/models.json.

Only models listed here appear in the UI. Removing an entry hides the model without deleting any files. Adding an entry makes a model available — but you must have the model files downloaded first.

Most day-to-day work on this file is better done from the Model Manager, which downloads, enables, disables and deletes models without hand-editing JSON. Hiding a model no longer means deleting its entry: the panel writes an enabled field instead, so it can be turned back on in one click. Entries without that field are treated as enabled.

Each model is typically 15–30GB. Review this file before running download_models.sh and remove entries for models you don't need. The download script fetches everything listed. The Model Manager downloads one model at a time instead, and shows what each would actually pull before you commit to it.

Model Entry Structure

Each top-level key is a model ID (e.g. "qwen_image"). Keys beginning with an underscore are comments and are skipped by every reader. An entry's value is an object with these fields — only the first six are required:

FieldTypeDescription
model_idstringRepository the files come from, e.g. "Qwen/Qwen-Image". Resolved on HuggingFace first and ModelScope second, so a repo that exists on only one host still downloads. Acts as the default for every components entry that does not name its own
pipelinestringWhich FUK runner handles the model: qwen, wan, flux2, krea2, ltx2, minimax_h3, qwen_video_edit, threed. Also selects the family defaults block in defaults.json
categorystringimage, video or threed — determines which tab the model appears in
descriptionstringHuman-readable label shown in the UI dropdown
aliasesarrayAlternate names that resolve to this key — accepted on the CLI, in the API, and by anything replaying an older saved task string
supportsarrayFeature flags: negative_prompt, edit_image, context_image, keyframes, control_video, eligen, inpaint, vace_video_mask, tiled and so on — controls which UI cards and input slots appear
componentsarrayThe weight files the model needs, as {"pattern": …} objects. pattern is a glob under the repo; add model_id to pull that one component from a different repo, or quantize to override the denoiser heuristic. Omit the whole field for models whose weights arrive another way — the 3D entries do
parameter_mapobjectMaps FUK's generic input slots (control_input, reference_image, edit_targets, end_image) onto the names this model's pipeline expects
tokenizerobject{"pattern": …}, plus model_id when the tokenizer lives in a different repo from the weights
processorobjectSame shape as tokenizer, for the vision-language models that ship one. The two are mutually exclusive in practice
loraobjectA LoRA that is part of the model rather than optional — Control-Union and EliGen are defined this way. Takes model_id, pattern, target (default "dit") and alpha (default 1.0), and is merged at load time
stage2_loraobjectDistilled LoRA for LTX-2.5's two-stage refine pass — a from_pretrained argument, not a runtime LoRA. Takes pattern, optional model_id, and strength (DiffSynth defaults to 0.8; 2.5 wants 1.0)
pipeline_kwargsobjectModel-specific flags passed straight to the pipeline call — tiled, tile_size_in_frames, zero_cond_t. These win over values resolved from defaults or the request
constraintsobjectPer-model overrides of the family's hard limits — latent grid, frame lattice, which shift control exists. Overlaid on the family block from defaults.json; see Per-Model Constraints
enabledbooleanWhether the model is registered into the dropdowns. Absent counts as true. false keeps it listed in the Model Manager with its checkbox clear
audio_sample_rateintegerFallback rate for the audio-video models when muxing. The LTX-2.5 runner prefers the rate reported by the loaded vocoder, because that changed between versions; MiniMax-H3 uses this value directly (32000)
fpsintegerFrame rate the model was trained at, used when writing the clip
size_gbintegerDeclared download size, shown in the Model Manager before anything is fetched. Once files are present the panel reports actual disk usage instead
notesstringFree text surfaced on the model's Model Manager row

The two 3D entries are a different shape, because their weights do not come through the DiffSynth loader: they carry type, name, path, vram_gb_estimate, and — for TRELLIS — isolated_env and install naming the separate environment and the script that builds it. VGGT adds max_input_dim.

Registered Models

Every entry below is registered and downloadable from Utilities → Models. Default is what the entry's enabled flag ships as: on models appear in their tab's dropdown immediately, off ones stay listed in the Model Manager with their checkbox clear — usually because they are a large download or a second variant of something already registered. Ticking one registers it without a re-download, and unticking hides it again without deleting anything. A missing enabled key counts as on.

KeyTypePipelineDefaultDescription
qwen_imageImageqwenonBase Qwen text-to-image
qwen_image_2512ImageqwenonQwen 2512 text-to-image — newer base, same VAE and text encoder
qwen_image_edit_2511ImageqwenonMulti-image editing and img2img
qwen_image_control_unionImageqwenonStructural conditioning — the In-Context Control-Union LoRA over the Qwen base
qwen_image_control_union_2512ImageqwenonThe same control LoRA over the 2512 base
qwen_eligenImageqwenonRegional composition control via EliGen V2
qwen_image_21Imageqwen21onQwen-Image 2.1 — text-to-image and editing in one 7B checkpoint, with native RGBA output (transparency is prompt-driven, not a switch). Shares no components with the qwen entries above, so it is a full 33GB download, and it has no EliGen support; control is the separate entry below. Non-commercial weights — the Qwen Research Licence, unlike the Apache-2.0 Qwen models
qwen_image_21_controlImageqwen21onQwen-Image 2.1 plus the PAI Fun ControlNet-Union — one control map (canny, depth, grayscale, HED, lineart, MLSD, pose or scribble) and/or mask inpainting, at Control Strength 1.0 by default. Same base files as qwen_image_21 plus a 7.5GB ControlNet; needs DiffSynth 2.1.9. Slower per step than the base, since the control branch turns the KV cache off. Non-commercial weights — inherits the Qwen Research Licence
krea2_rawImagekrea2onKrea-2 Raw — text-to-image at 52 steps, CFG 4.5
krea2_turboImagekrea2offKrea-2 Turbo — distilled, 8 steps at CFG 1.0, roughly 6x faster
flux2_devImageflux2offFLUX.2-dev multi-image editing. Non-commercial weights
flux2_klein_4bImageflux2offFLUX.2-klein 4B — small and fast; the commercially usable FLUX.2
wan_i2v_a14bVideowanonWan 2.2 image-to-video (A14B)
wan_vace_a14bVideowanoffVACE-controlled video with reference image
wan_inp_a14bVideowanoffFirst frame to last frame — see FFLF
wan_animate_a14bVideowanoffWan 2.2 Animate — pose and face control from driving video
wan_animate_replace_a14bVideowanoffAnimate Replace — pose and face plus inpaint and mask video
ltx2Videoltx2onLTX-2.5 22B audio-video at 48kHz. Key stays ltx2 — it names the pipeline family, not the version
minimax_h3_fl2vaVideominimax_h3onJoint audio-video at 32kHz from a first and/or last frame
minimax_h3_ref2vaVideominimax_h3onSame family, conditioned on reference image / video / audio
minimax_h3_controlVideominimax_h3onFun ControlNet-Union — canny / depth / hed / mlsd / pose video drives the structure. Needs the unpruned DiT, so it does not share weights with the two above
qwen_video_editVideoqwen_video_editonPrompt-driven video-to-video editing at 360P. Weights carry no declared licence — research only
trellis3DthreedonSingle image to mesh — Structured 3D Latents
vggt3DthreedonMulti-view reconstruction, 1 to hundreds of images. CC-BY-NC weights

The 3D entries carry no components: their weights arrive through install_trellis_env.sh or on first use, so the Model Manager lists them without a download button.

Deferred Models

The _deferred key holds models that were considered and left out, each with the reason: T2V variants excluded as non-professional, SeedVR2 because it is not a DiffSynth pipeline at all (it runs through fuk/core/seedvr2_backend.py), and Wan S2V, Wan Control-Camera and Qwen Blockwise-ControlNet because each needs pipeline or UI work that has not been done. The values are one-line notes rather than model entries, so activating one means writing its entry against the fields above — not moving a block.

Adding a New Model

  1. Download the model files to models_root
  2. Add a new entry to models.json with the correct pipeline, category, and components glob patterns
  3. Set supports to the feature flags that apply — this controls which UI cards are shown for the model
  4. If the model uses different parameter names, add entries to parameter_map
  5. Restart FUK — the model will appear in the appropriate tab's dropdown

defaults_vram.json

▶ Video breakdown — coming soon

Controls how FUK manages GPU memory. When a model is too large to fit entirely in VRAM, FUK offloads unused tensors to system RAM or disk. This file defines the available offload strategies and which one is active. Located at fuk/config/defaults_vram.json.

Choosing a Preset

Set vram.preset to one of the four options:

PresetStrategyVRAM RequiredSpeed Impact
"none"No offloading — full model in VRAM48GB+Fastest
"low"CPU offload in bfloat1616–24GBMinimal
"medium"CPU offload in float812–16GBModerate
"high"Disk offload8GBSignificant — requires fast SSD

Preset Details

KeyDescription
offload_dtypePrecision used when tensors are moved to CPU/disk: bfloat16, float8_e4m3fn, or disk
offload_devicecpu or disk
computation_dtypePrecision during GPU compute — keep at bfloat16 unless you have a specific reason to change it
buffer_gbVRAM headroom reserved for activations; increase if you get OOM errors mid-generation

The Postprocess Panel and individual generation panels also expose a VRAM Management dropdown that overrides this preset per-session. The setting here is the default on fresh launch.

defaults_loras.json

▶ Video breakdown — coming soon

The LoRA adapter registry. Defines which LoRA files are available in the Image and Video panel dropdowns. Located at fuk/config/defaults_loras.json.

Discovery

FUK finds LoRA files in two ways:

  • lora_dirs — array of directories to scan recursively for .safetensors files; any file found is automatically listed in the UI
  • lora_paths — array of explicit paths to individual LoRA files; use this for LoRAs that live outside the standard scan directories

Files found by either method appear in the dropdown using their filename as the label. To give a LoRA a custom label, add it to the loras array instead (see below).

loras Array

For LoRAs that need specific configuration, add an entry here:

FieldDescription
nameDisplay name shown in the UI dropdown
pathAbsolute path to the .safetensors file
modelBase model this LoRA targets — used to filter the dropdown per active model (e.g. "qwen_image")
default_strengthInitial multiplier value when this LoRA is selected; 0.0–2.0
trigger_wordOptional keyword that activates the LoRA concept — shown as a hint in the UI, not automatically injected
inject_textOptional text automatically appended to the positive prompt whenever this LoRA is active

Example Entry

{
    "name": "Studio Lighting v2",
    "path": "/home/brad/ai/models/loras/studio_lighting_v2.safetensors",
    "model": "qwen_image",
    "default_strength": 0.8,
    "trigger_word": "studio_light",
    "inject_text": "studio_light, professional lighting"
}

defaults_dataset.json

▶ Video breakdown — coming soon

Configuration for the LoRA Dataset Builder. Defines the angle, lighting, and context variation templates used when generating training datasets. Located at fuk/config/defaults_dataset.json.

This is the file to edit when you want to add or change the variations the Dataset Builder generates — for example, adding a custom camera angle or a lighting setup specific to your subject matter.

Top-Level Generation Settings

KeyDefaultDescription
denoising_strength1.0Variation amount; 1.0 = full generation from prompt, lower values stay closer to a reference image
seed(integer)Default seed when seed_strategy is "fixed"
seed_strategy"fixed""fixed" — all variations use the same seed for consistency; "random" — each variation gets its own seed
cfg_scale5Guidance scale for dataset generations
steps28Denoising steps; slightly higher than interactive default for dataset quality

variation_prompts

The core of this file. Three subject types — character, object, and environment — each with arrays of angle and lighting variation prompts.

Character Angles (35+ presets)

Covers the full range of shot types needed for a character LoRA: full body front/back/sides, 3/4 angles at 15° and 45°, medium shots, bust shots, closeups, extreme closeups, overhead, knee-level, over-shoulder, seated, and kneeling variations.

Character Lighting (7 presets)

KeyDescription
overcastSoft diffuse, no shadows — good baseline lighting for character recognition
hard_frontalDirect on-axis spot — high contrast, shows facial structure clearly
three_quarter_softClassic key + fill setup — the most natural-looking option
overheadDownward shadowless light
under_lightUpward from below — creates strong under-eye shadows
splitHard split — half the face lit, half in shadow
rimBacklit edge light — silhouette with glowing outline

Object Angles (30+ presets)

Front, side profiles (90°), 45° rotations, high/low orbits, top-down, underside, and detail shots optimised for product-style LoRA datasets.

Environment (Time, Weather, Season)

Three variation axes for environment LoRAs: time of day (dawn, noon, sunset, night), weather (clear, overcast, rain, fog, snow), and season (spring, summer, autumn, winter).

Adding Custom Variations

Add a new key to any angles or lighting object with a prompt string as the value. It will appear as a selectable variation in the Dataset Builder's variation deselection list:

"character": {
    "angles": {
        "my_custom_angle": "extreme low angle, shot from ground level looking up at full body"
    },
    "lighting": {
        "candlelight": "warm candlelight, single small flame source below frame, heavy shadows"
    }
}

Tool Configs

▶ Video breakdown — coming soon

Advanced configuration files in fuk/config/tools/ that control how FUK invokes external pipeline runners. Most users won't need to edit these — they exist to let you tune pipeline execution if you're running non-standard hardware or adding a new model family.

depth-anything-v3.json

Configuration for the Depth Anything V3 depth estimation model used in the Preprocess and Layers panels.

Model KeyDescription
da3_mono_largeMonocular single-image depth — best general-purpose option
da3_metric_largeMetric depth in real-world meters — useful when absolute scale matters for compositing
da3_largeMulti-view capable variant
da3_giantLargest and most accurate — slowest; useful for hero frames or difficult scenes

The inference_defaults.process_res key (default: 1280) sets the resolution at which depth estimation runs. Increasing it improves accuracy but raises VRAM usage and processing time.

sam2.json

Configuration for Segment Anything Model 2 (SAM2), used to generate Cryptomatte segmentation masks in the Layers Panel.

Model KeySizeNotes
sam2.1_hiera_largeLargeDefault — best quality
sam2.1_hiera_baseBase+Balanced
sam2.1_hiera_smallSmallFast, lower VRAM
sam2.1_hiera_tinyTinyMinimal VRAM

auto_mask_generator thresholds

KeyDefaultDescription
points_per_side32Grid density for automatic mask proposals — higher values find more objects but are slower
pred_iou_thresh0.86Minimum predicted mask quality score (0–1); increase to discard low-confidence masks
stability_score_thresh0.92Mask stability threshold; increase to keep only well-defined, consistent masks
min_mask_region_area100Minimum segment size in pixels; increase to filter out tiny noise segments

Keyboard Shortcuts

Shortcuts are blocked when an input, textarea, or select element is focused, except where noted. IME composition (CJK input) is always ignored.

Global

ShortcutActionNotes
Shift+GGenerateWorks inside inputs — shift modifier makes it intentional
EscBlur focused prompt field, or cancel generationIf a prompt textarea is focused, blurs it first; otherwise cancels
1Switch to Utilities tab
2Switch to Storyboard tab
3Switch to Pre-Processors tab
4Switch to Image tab
5Switch to Video tab
6Switch to Post-Processors tab
7Switch to Layers tab
8Switch to Export tab
↑ / ↓Adjust focused number inputNative browser step behaviour
Shift+↑ / Shift+↓Adjust focused number input ×10Custom handler on number inputs

History Panel

ShortcutActionNotes
HCycle history panelClosed → compact strip → fullscreen gallery → closed
Shift+DeleteDelete selected item(s) — no confirmationOnly fires when history panel is open; works on multi-selection in fullscreen gallery
Numpad +Upvote selected itemVotes on current selection in fullscreen gallery
Numpad -Downvote selected itemVotes on current selection in fullscreen gallery
← / →Navigate previous / next itemFullscreen gallery only
+ / -Zoom thumbnails in / outFullscreen gallery only
Shift+ClickRange-select multiple itemsFullscreen gallery only

Image & Video Tabs

ShortcutActionNotes
PFocus prompt field
Shift+PFocus negative prompt field
SCycle seed modeRandom → Fixed → Increment → Random
Shift+RSet seed mode → Random
Shift+FSet seed mode → Fixed
Shift+ISet seed mode → Increment

Mask Painter

Active only while the painter is open, when every other shortcut is suspended. See Inpainting.

ShortcutActionNotes
BBrush
EEraser
XSwap brush and eraser
[ / ]Shrink / grow the brush
Ctrl+ZUndo
EscClose without savingAsks first if there are unsaved changes

Video Tab Only

ShortcutActionNotes
SpacePlay / PausePrevented from scrolling the page
→Advance one frameSeeks by 1/24s; pauses first
←Go back one frameSeeks by 1/24s; pauses first

File Locations

FUK follows a consistent directory structure. Model root and output root can be on separate drives — configure both in config/defaults.json.

Directory Structure

FUK/
├── config/
│   ├── defaults.json       ← model root, output root, UI preferences
│   ├── models.json         ← which models to load and their paths relative to model root
│   └── templates.json      ← saved Spec Tool templates
├── models/
│   ├── checkpoints/        ← base model checkpoint files
│   ├── controlnet/         ← ControlNet model files
│   ├── loras/              ← LoRA weight files
│   ├── upscalers/          ← Real-ESRGAN model files
│   ├── film/               ← FILM interpolation model
│   └── preprocessors/      ← depth, pose, edge detection model weights
├── outputs/
│   └── [project]/
│       └── [shot]/
│           └── [version]/
│               ├── [image or frame sequence]
│               ├── [preview MP4 for video]
│               ├── [multi-layer EXR]
│               └── meta.json   ← complete generation metadata sidecar
├── lora_datasets/          ← LoRA Dataset Builder output
└── logs/                   ← generation logs and error output

Key Config Paths

FilePurpose
config/defaults.jsonSets model root directory, output root directory, default generation parameters, and UI preferences
config/models.jsonLists models to make available in the interface — remove entries to hide models, edit paths if your model directory layout differs
config/templates.jsonSaved Spec Tool templates; safe to copy between machines

Model Files by Type

Model TypeExpected Path (relative to model root)Format
Base Checkpointcheckpoints/[name].safetensors.safetensors
ControlNetcontrolnet/[name].safetensors.safetensors
LoRAloras/[name].safetensors.safetensors
Real-ESRGANupscalers/[name].pth.pth
FILMfilm/film_net_fp16.pt.pt
MiDaS / DA3 (Depth)preprocessors/depth/[model].pt.pt
OpenPosepreprocessors/openpose/[weights].pth / .caffemodel
SAM2 (Cryptomatte)preprocessors/sam2/[model].pt.pt

Cache Folder

Everything you generate lands in fuk/cache/ first. It's the local working store the app reads and writes during a session — and the Generation History panel is simply a view of it: every history card is one folder on disk. The cache is git-ignored and fully regenerable, so it's safe to clear when reclaiming disk space (that just empties history for those shots).

Layout

The cache is organised by shot version, then by generation. Each generation gets its own numbered folder holding the output plus a metadata.json sidecar with the full parameters used.

fuk/cache/                                  ← local working store (git-ignored)
└── {project}_shot{shot}_{version}/         ← one folder per shot version
    │                                         e.g. crazyAL_lookDev_shot01_260606/
    ├── img_gen_001/                        ← a numbered generation, tagged by type
    │   ├── generated.png                   ← the output (png / mp4 / exr)
    │   ├── metadata.json                   ← full parameters — see Metadata & Repeatability
    │   └── latents/generated.latent.pt     ← saved latent, for refine / re-use
    ├── img_gen_002/
    ├── video_001/
    │   └── generated.mp4
    └── preprocess_001/
        └── ...

Generation Types

The prefix on each folder is the tool that produced it. This is how History groups images vs. video and how a result knows which panel to reopen in.

PrefixProduced by
img_gen_Image Panel generations
img_edit_Qwen-Edit / image edits
video_ / video_layers_Video Panel generations
preprocess_Preprocess Panel (depth, pose, canny, …)
layers_Layers Panel (SAM2 mattes, cryptomatte)
upscale_ / interpolate_Postprocess Panel
export_exr_ / export_exr_seq_EXR export staging
import_Imported media — reference only, no copy (see note)

Imports don't duplicate your files — an import_ folder holds only a metadata.json that points at the original media on disk. If you move or delete that source, the imported entry breaks. Everything else in the cache is self-contained.

Metadata & Repeatability

Every generation in FUK captures a complete record of the parameters used. This metadata is written to a meta.json sidecar file alongside the output and is accessible by dropping the output onto any tab's preview area. A generation is fully reproducible from its sidecar alone, on any machine with the same model files.

Captured Metadata

FieldDescription
SeedExact seed used — fixed seeds with identical parameters produce identical results
ModelCheckpoint filename and SHA256 hash — hash confirms you're using the same file, not just the same name
LoRA(s)LoRA filenames, hashes, and per-LoRA blend weights
PromptFull positive and negative prompts, exactly as submitted
ParametersSteps, CFG scale, sampler, scheduler, resolution
ControlNetAny ControlNet models used, their preprocessor, weight, guidance range, and input image hash
EliGen ZonesZone mask paths, per-zone prompts, and weights if regional conditioning was used
PipelineWhich generation pipeline was used (base, controlnet, eligen, img2img, i2v, fun_control)
FUK VersionApplication version string
TimestampISO 8601 date and time of generation
Generation TimeWall-clock time for the generation in seconds

Metadata Format

Sidecar files are standard JSON, saved as meta.json in the version directory. They are human-readable and can be parsed by any standard JSON library. No database or index is required — the History panel reads sidecar files directly from disk.

Metadata Display

The Generation History gallery renders a generation's captured metadata as a structured settings panel rather than a raw JSON dump. Curated fields — resolution, seed, steps, CFG, denoise, sigma shift, exponential shift μ, frame count, sliding window, model, and the LoRA stack — are surfaced as compact labelled cells in a consistent order, while long or path-like values such as LoRA names and source paths get their own full-width rows for readability. Any parameter not in the curated list still appears automatically via a generic pass, so newly added generation settings show up in the panel without a UI change. Positive and negative prompts render as their own text blocks, and two generations can be opened side by side for a field-by-field A/B comparison of their settings.

Portability

Because metadata is stored as sidecar files alongside outputs rather than in a central database, output directories are fully portable. Copy a version directory to another machine and FUK will recognize it on first launch. If a model file referenced in the sidecar is missing or has a different hash, FUK will warn before re-queuing.

Licensing & Commercial Use

FUK itself is MIT licensed. It is an orchestration layer — it ships no model weights of its own, and nearly everything that does the actual work is a third-party component with its own licence. Those licences are not all the same, and three of them prohibit commercial use.

The full audit lives in THIRD_PARTY_LICENSES.md in the repository root. This page is the summary.

Restricted Components

ComponentUsed ForLicencePaid Work
DSINESurface normals preprocessorImperial College London academic licenceNo
VGGT-1B (weights)3D reconstruction utilityCC-BY-NC-4.0No
FLUX.2-devImage editing — alternative to Qwen-Image-EditFLUX [dev] Non-Commercial v2.0Grey — see below

What "Non-Commercial" Means Here

For DSINE and VGGT the restriction attaches to what you use the tool for, not to whether you redistribute FUK. Never packaging or selling FUK does not exempt you. If you are paid for work whose pipeline included either, that is commercial use under the plain reading of these licences.

DSINE is the most explicit — its clause 2(b)(4) prohibits "use of the Software to provide any service to an external organisation for which payment is received." That is precisely the freelance and studio-work case.

Commercial paths exist: DSINE via researchcontracts.engineering@imperial.ac.uk, and VGGT via Meta.

FLUX Is a Special Case

FLUX's licence is not a flat prohibition, and it is easy to read either way. Two clauses pull in opposite directions.

Outputs are explicitly permitted: "We claim no ownership rights in and to the Outputs… You may use Output for any purpose (including for commercial purposes)." Outputs are not Derivatives; the only restriction is that you may not train a competing model on them.

Model use is not: "You may only access, use, Distribute, or create Derivatives of the FLUX.1 [dev] Model… for Non-Commercial Purposes" — and Black Forest Labs define Non-Commercial Purpose to exclude "revenue-generating activity."

So selling an image you generated is squarely permitted; running the model as part of paid work is the contested act. BFL's own tier structure settles how they read it — their Professional tier is sold to agencies producing work "on behalf of named clients," and the entry Builder tier is explicitly "not meant for client use or downstream applications."

Practical reading: personal work, R&D and unpaid experiments are fine on FLUX.2-dev. Paid client deliverables want a Builder or Professional licence, or a different model.

FLUX.1 Krea [dev] is the BFL × Krea collaboration finetune and carries the same non-commercial terms. Despite the name it is not a friendlier option, and it is not the same thing as Krea 2 below.

Krea 2 — The Permissive Alternative

Krea's own from-scratch 13B model, unrelated to the FLUX collaboration, ships under the Krea 2 Community License:

  • Commercial use is free below $1,000,000 USD company-wide annual revenue (trailing twelve months, all affiliated entities). Above that, an enterprise licence is required.
  • You own your outputs — Krea claims no ownership.
  • Two conditions apply at every size: implement reasonable content filtering (an open-source classifier, a moderation API, or human review all qualify), and disclose AI generation where legally or platform-required.
  • Ships as Raw (undistilled, for fine-tuning and LoRA training) and Turbo (8-step distilled). Gated on Hugging Face — accept the licence and Acceptable Use Policy to download.

For a freelancer or small studio this is currently the most permissive frontier-class image model, and a better default than FLUX.2-dev for anything client-facing.

A Clean-for-Hire Configuration

All three restricted components are optional paths, not core infrastructure. The following configuration covers the entire pipeline with no non-commercial component in it:

StageUseInstead Of
Image generationQwen-Image (Apache 2.0), or Krea 2 (free under $1M revenue)—
Image editingQwen-Image-Edit 2511 (Apache 2.0)FLUX.2-dev
Video generationWan 2.2 (Apache 2.0)—
DepthDepth-Anything-3 (Apache 2.0)—
NormalsDA3-derived normals (Apache 2.0)DSINE
CryptomattesSAM 2.1 (Apache 2.0)—
3D reconstructionTRELLIS (MIT)VGGT
UpscalingReal-ESRGAN (BSD-3), SeedVR2 (Apache 2.0)—
InterpolationFILM (Apache 2.0)—

Everything else in the stack — DiffSynth-Studio, the Wan and Qwen weights, the DiffSynth LoRAs, SAM2, TRELLIS, FILM, Real-ESRGAN, SeedVR2 — is Apache 2.0, MIT, or BSD-3-Clause. SeedVR2 is clear for paid work on both counts: the engine code (numz/ComfyUI-SeedVR2_VideoUpscaler) and the weights (re-quantized from ByteDance-Seed/SeedVR2-3B) are both Apache 2.0.

Unverified

The PAI/Wan2.2-VACE-Fun-A14B and PAI/Wan2.2-Fun-A14B-InP repositories are gated on Hugging Face and could not be read without authentication. They are Alibaba PAI derivatives of Apache-2.0 Wan 2.2 and are expected to inherit those terms, but this has not been confirmed. Check the model card before relying on either for paid work.

If You Add Models

Record the licence for the code and the weights separately — they are frequently different, and that is the most common way to get caught out. VGGT is exactly that case: its repository licence carries no non-commercial clause, but its published weights are CC-BY-NC-4.0.

The same applies to community upscaler checkpoints. Many models on OpenModelDB are CC-BY-NC despite running on permissively-licensed architectures; the widely-recommended 4x-UltraSharp is CC-BY-NC-SA-4.0 and its author has stated the restriction extends to generated outputs. Filter by licence before shortlisting by benchmark score.

This summary is a good-faith engineering audit of published licence text, not legal advice. Verify anything you intend to rely on commercially, and re-check before shipping client work — upstream projects relicense.

Plugins

▶ Video breakdown — coming soon

FUK exposes its generation pipeline over a local HTTP API, which makes it straightforward to drive from other applications. Plugins live under fuk/plugins/ and act as clients to the running FUK server — they gather inputs in the host application, hand them to FUK, and bring the results back.

Because a plugin and the FUK server run on the same machine, inputs are exchanged by file path rather than upload, and the shot .json remains the single source of truth for settings.

Where the host application has no plugin API, the direction flips: the controls live in the FUK web UI and the FUK server drives the application instead.

Available Plugins

  • Blender Bridge — render structural control passes from a Blender scene, generate control-guided stills and VACE video in FUK, and bring the results back into the viewport.
  • PhotoCraft Bridge (Beta) — pull composites, masks, layers and @ entity layers from PhotoCraft into the Image tab, and place results and depth maps back as layers.

Blender Bridge

▶ Video breakdown — coming soon

The Blender Bridge is a Blender add-on (fuk/plugins/blender/) that drives FUK from inside Blender. It renders your scene's structural control passes, sends them to FUK for control-guided generation, and returns the result to the viewport — for both stills and VACE-driven video. It targets Blender 4.2+ and is validated on 5.x.

Requires a running FUK server on the same machine, plus the relevant model weights: qwen_image_control_union_2512 (or qwen_image_control_union) for stills, and wan_vace_a14b for video.

Installation

  1. Start the FUK server.
  2. In Blender: Edit ▸ Preferences ▸ Add-ons ▸ Install from Disk… and pick fuk/plugins/blender/addons/fuk_blender.zip. Enable FUK Bridge.
  3. Set the Server URL in the add-on preferences if it isn't the default (http://localhost:8000).
  4. Open the FUK tab in the 3D viewport sidebar (press N).

Connecting to a Shot

Pick your project folder (the one holding the shot .json files) and press Connect; the button reads Connected once it reaches the server. The add-on also auto-connects on file open when a project folder is saved in the .blend, and restores the last shot you used.

Load Shot mirrors the shot's prompt, seed, and settings into the panel (the shot is the source of truth); Save to Shot writes your edits back. Advanced settings you don't edit in Blender — LoRAs, detail bias, VRAM preset — are read from the shot at generation time, so changes made in the FUK web UI apply automatically.

Control Passes

The bridge derives structural control from your 3D scene, which is far more accurate than estimating it from a 2D render:

  • Depth — the exact Z pass, normalized (near = white, far = black, background masked) to match the convention the control model expects.
  • Normals — the normal pass, remapped.
  • OpenPose — from a view layer that renders your pose rig (set it as the Rig Layer); falls back to FUK's estimator if no rig layer is set.
  • Canny — from a view layer that renders your line work (set it as the Canny Layer). The layer is used exactly as it renders, with no edge detection, so it should draw light lines on black. With no canny layer set, FUK derives the map from the beauty render instead.

With a rig layer set, the skeleton is kept out of the main render, so it never appears in the depth map or the beauty.

Combined Controls

The control model reads a single control image, so to use more than one control the add-on layers them into one map before sending it. Four combinations are available in the Control dropdown:

  • Depth + OpenPose — depth for the set, skeleton for the figure.
  • Depth + Canny — depth with line work drawn over it; useful for detail depth cannot carry, such as lettering on a flat wall.
  • Canny + OpenPose
  • Depth + Canny + OpenPose

The layers are always stacked in the same order: depth at the bottom, canny lines over it, and the skeleton on top. Each part is also saved on its own (depth.png, canny.png, openpose.png) next to the combined map in the shot's working folder, so a map that isn't being followed can be traced to the part that is wrong.

A combined control needs every one of its view layers. If the Rig Layer or Canny Layer is missing, the panel says so and the render stops rather than sending a partial map. White canny lines also disappear against very bright (very near) depth, so keep line work on surfaces that sit further back, or use Canny + OpenPose without depth.

The OpenPose Rig

The pose skeleton is generated on top of an Auto-Rig Pro character by fuk/plugins/blender/openpose_gn_prototype.py. The rig file itself is not part of the repository; the script builds the skeleton, its view layer and its drivers into your own rig file.

  • Sticks and dots hold their pixel size. OpenPose maps are drawn at fixed pixel widths, and a skeleton that grows as the camera moves in gets painted into the image as an object. The rig's widths are driven from the camera, so they stay at the standard size at any camera distance, lens, resolution or preview percentage.
  • Face landmarks. The rig draws the 70 OpenPose face points on the head. They appear once the face is at least 80 pixels wide in the map and are hidden below that, where they would merge into a blob. A Face checkbox on the OP_Generator modifier turns them off for shots where the face should be left to the prompt.
  • Expressions. Eleven shape-key sliders on the OP_source object move the face points: jaw_open, smile, frown, pucker, brow_raise.L, brow_raise.R, brow_furrow, blink.L, blink.R, gaze_h and gaze_v. They can be keyframed. Each runs from −3 to 3: values above 1 push past the natural range, and negative values do the opposite (a negative blink is a wide eye).

To build the skeleton into a rig file, or to update one that already has it:

# first build, from an Auto-Rig Pro character
blender MyRig.blend --background --python fuk/plugins/blender/openpose_gn_prototype.py -- --out MyRig_OP.blend

# rebuild in place (needed for anything that changes the skeleton itself, e.g. the face)
blender -b MyRig_OP.blend --python fuk/plugins/blender/openpose_gn_prototype.py -- --in-place

# refresh only the size drivers and view-layer setup
blender -b MyRig_OP.blend --python fuk/plugins/blender/openpose_gn_prototype.py -- --drive-only

Options: --no-face builds the body and hands only, and --face-min-px N changes the size at which the face appears (0 always draws it). Close Blender on the file before running these, or reload it afterwards without saving.

Describe Shot

A control map tells the model where the figure is, but it does not make the model want that composition. With a prompt that only describes the character and the place, a full-body skeleton usually still comes back as a head-and-shoulders portrait. The prompt has to agree with the map.

Describe Shot (under the prompt, on by default) writes that part of the prompt for you. It needs a Rig Layer. At render time the add-on measures the camera against the rig and adds a short description around your prompt:

MeasuredFromExample of what is added
How much of the figure is in the imageWhich parts of the body are inside the camera viewimage from the waist up; image of the whole body from head to feet
Camera angleCamera height relative to what it is looking atthe camera is low, looking up
FacingThe figure's forward direction against the cameraside view, the body in profile; seen from behind, facing away from the camera
PlacementWhere the figure sits across the imagepositioned on the left side of the image

Plain cases add nothing: an eye-level, front-facing, centred figure only gets the line about how much of it is in the image. The size and angle go before your prompt; for views from mid-thigh outwards a second clause goes after it, and standing is added only when the rig's legs are actually upright. A few terms (border, photo print, split panels…) are also added to the negative prompt.

The panel shows the text that will be added for the current view, and Preview includes it. Your own prompt is never changed, in the panel or in the shot file. For video, the description is measured once, at the first frame.

With Describe Shot on, the measured size is also sent with the generation so that a LoRA #tag can use different wording for close, medium and wide views. See inject_variants in the add-on README.

How well the description works depends on the rest of the prompt. A short subject (a man in a dim bar) lets the pose, size, angle and facing follow the map. A long character description that dwells on the face and jacket pulls the image back toward a portrait, and one that mentions shoes will put shoes into a knees-up image. The wording lives in the constants at the top of addons/fuk_blender/framing.py if you want to tune it.

Generating Stills

Frame your camera, choose a control, and press Quick Preview (fast, low-res) or Render Full. The add-on renders the beauty and control passes, sends them to the control-union model, and returns the image. History policy: Quick Preview is ephemeral, Render Full saves a complete entry (result + control + source), and Save to History promotes any result on demand. The FUK web history auto-refreshes when Blender saves.

A saved entry records the prompt exactly as the model received it (tags expanded, shot description included), alongside your own draft, the description that was added and the measurements behind it.

Prompts support FUK's #tags: Insert #tag searches the vocabulary and Preview shows the resolved prompt.

Result Display

Under Result, choose how the image comes back: Viewport (a camera-background overlay with adjustable opacity, registered to your framing), New Window, or Image Editor. With Diffusion Preview on, the image is shown forming step-by-step during generation.

Live Mode

Toggle Live for an IPR-style loop: after you move the camera or edit geometry and the scene settles for the Delay, it auto-runs a Quick Preview. With Interrupt on, a new edit cancels the in-flight preview and restarts with the latest state; with it off, edits made mid-render coalesce into a single trailing render. Selection clicks are ignored. Shortcuts (3D View): Ctrl+Shift+P preview, Ctrl+Shift+L toggle Live.

Video (Wan-VACE)

Animate a still with your scene's motion:

  1. Generate a still first — it becomes the VACE reference (the look).
  2. Set the scene frame range (the motion) and a control: depth, normals, openpose from a rig layer, canny from a canny layer, or any of the combined controls.
  3. Set Video % (resolution scale) and press Generate Video.

The add-on renders the control pass over the whole range into a folder (depth is normalized over a global range so it doesn't flicker) and runs wan_vace_a14b with that sequence as the control video and your still as the reference. The result loads into Blender's Video Sequencer. Video is slow and runs on demand — there is no live mode for it.

Cancelling

Press Esc or the Cancel button to stop a generation. Image generations abort at the next diffusion step; video currently stops waiting but continues rendering on the server.

PhotoCraft Bridge

The PhotoCraft Bridge moves images between FUK and PhotoCraft, the MIT/Apache-licensed image editor from ArtCraft. Paint a mask, block out entity regions, or build a slap comp in PhotoCraft, pull it into the Image tab, generate, and place the result back as a new layer.

Beta. The bridge is new and depends on PhotoCraft's desktop control channel, which supports much less than its protocol docs describe. A PhotoCraft update can change what is available. Re-run the self-check (fuk/plugins/photocraft/pc_probe.py) after updating, and please report anything that breaks.

Unlike the Blender Bridge, this works the other way round. PhotoCraft has no plugin API and cannot call out to other programs, so the controls live in the FUK web UI and the FUK server drives PhotoCraft over its local control channel.

Setup

PhotoCraft is installed as the Flatpak ai.storyteller.photocraft. Start it with the launcher, or press Launch PhotoCraft on the Image tab's PhotoCraft card, which runs the same script:

fuk/plugins/photocraft/launch_photocraft.sh            # this launch only
fuk/plugins/photocraft/launch_photocraft.sh --persist  # also: flatpak override --share=network

The launcher adds three things a plain flatpak run does not:

  • Network sharing. Without it the sandbox gets its own network namespace and FUK cannot see the control port (127.0.0.1:47823).
  • Mailbox present mode. Control requests run on PhotoCraft's frame loop. Under the default vsync mode a hidden window stops drawing, so requests queue up and time out. If you still see "bring its window into view", do that and retry.
  • The control token and exchange folder. Files are exchanged through <Pictures>/fuk_photocraft/exchange/, which the sandbox can already see.

Settings live in defaults.json under tools.photocraft: port, root (the exchange folder), app_id, and max_pull_side. Pulls are downscaled to max_pull_side (default 2048), so a 6K document does not become a 6K generation. Results placed back are scaled up to the document size.

Layer Conventions

LayerUsed for
@<prompt> (e.g. @a red car)One EliGen entity. Its painted pixels are the region (alpha, or luminance if the layer is opaque). The layer nearest the top of the Layers panel becomes entity 01. Hidden or visible both work
_maskInpaint mask when there is no selection. White or painted means repaint
A selectionInpaint mask. A selection wins over _mask

@ and _ layers are always left out of the composite FUK receives. The bridge hides them in a scratch copy, so your document is not changed. Layers inside groups are read too.

Actions

A PhotoCraft card in the Image tab shows the connection status and the active document.

  • From PhotoCraft (control / edit inputs): choose Composite, Active layer, or any named layer. The image is added as a control input.
  • From PhotoCraft (inpaint): sets the composite as the inpaint image and the selection or _mask as its mask in one step. Mask from PhotoCraft fills only the mask.
  • @ layers → EliGen: turns every @ layer into an entity mask and switches the tab to the EliGen model with them loaded. Also available as From PhotoCraft (@ layers) in the EliGen panel.
  • Depth → layer: runs Depth Anything 3 on the composite and places the result back as a layer (near = white), for slap comps. In an 8-bit document the layer has only 256 levels, so pick + 16-bit doc or + 32-bit EXR doc to also open the full-precision map as its own document.
  • → PhotoCraft: on the result preview and on Generation History entries. Adds the image to the active document as a new layer named after its generation, aligned to the canvas.

Pulls never start a generation. Each one creates an import_### entry in the Generation History, and you press Generate when ready.

Known Limitations

  • Bit depth cannot be changed by automation. PhotoCraft's desktop control server refuses the commands that would do it. Layers placed into an 8-bit document are quantised to 8 bits, which is why depth offers to open a separate 16-bit or EXR document.
  • PhotoCraft must be drawing. If its window is fully hidden and requests time out, bring it into view and retry.
  • Stills only. FilmCraft and the other ArtCraft apps are not bridged yet.

Security

The control port listens on loopback only and needs a 256-bit token, stored in a file only your user can read. Network access is shared only with PhotoCraft instances the launcher starts, unless you used --persist.