Stable Diffusion — /v1/stablediffusion

The Stable Diffusion endpoints wrap StableDiffusionBridge for text-to-image, image-to-image, and text-to-video generation.

Images are exchanged as Base64-encoded RGBA bytes (width × height × 4 bytes). Video frames use a packed binary format described below.

Initialize

POST /v1/stablediffusion/init

Load a model. For standard image models only modelPath is required. Video models (Wan 2.1/2.2) additionally require vaePath and typically t5xxlPath.

Standard image model:

{
  "modelPath": "/models/dreamshaper.safetensors",
  "threads": 4
}

Video model (Wan 2.1 text-to-video):

{
  "modelPath": "/models/wan2.1-t2v-1.3b.gguf",
  "threads": -1,
  "vaePath": "/models/wan_2.1_vae.safetensors",
  "t5xxlPath": "/models/umt5-xxl-encoder-Q8_0.gguf"
}

threads: number of CPU threads. -1 uses all available threads.

ParameterRequiredDescription
modelPath✅Path to the main model file
threadsCPU thread count (default: -1)
vaePathVAE companion — required for Wan/LTX video models
t5xxlPathT5-XXL text encoder — typically required for video models
clipVisionPathCLIP vision encoder — for image-to-video variants

Response:

{ "ok": true }

All paths must resolve inside MODELS_DIR if that variable is configured.

Text-to-image

POST /v1/stablediffusion/txt2img

Generate an image from a text prompt.

Request:

{
  "prompt": "A cyberpunk llama in neon Tokyo",
  "negativePrompt": "blurry, low quality",
  "width": 512,
  "height": 512,
  "steps": 20,
  "cfgScale": 7.0,
  "seed": 42
}

All fields except prompt are optional.

Response:

{ "imageBase64": "<base64-encoded RGBA bytes>" }

Decode the string with Base64.getDecoder().decode(imageBase64) to get width × height × 4 raw RGBA bytes.

Returns 500 if the model returns an empty byte array.

Image-to-image

POST /v1/stablediffusion/img2img

Transform an existing image guided by a text prompt.

Request:

{
  "initImageBase64": "<base64-encoded RGBA source image>",
  "initImageW": 512,
  "initImageH": 512,
  "prompt": "The same scene as a watercolor painting",
  "negativePrompt": "low quality, blurry",
  "width": 512,
  "height": 512,
  "steps": 20,
  "cfgScale": 7.0,
  "strength": 0.75,
  "seed": 42
}

strength controls source preservation: 0.0 keeps the image almost unchanged, 1.0 ignores it entirely. Values around 0.6–0.8 work well for style transfers.

Returns 400 if initImageBase64 is not valid Base64.

Check video support

GET /v1/stablediffusion/supportsVideo

Returns whether the currently loaded model supports video generation. Call this after init before offering the video feature.

{ "supportsVideo": true }

Returns 500 if no model is loaded.

Text-to-video

POST /v1/stablediffusion/txt2video

Generate a video from a text prompt. Requires a video-capable model (Wan 2.1/2.2, LTX).

Request:

{
  "prompt": "A llama running through a neon-lit city",
  "negativePrompt": "blurry, low quality",
  "width": 512,
  "height": 512,
  "videoFrames": 16,
  "fps": 8,
  "cfgScale": 7.0,
  "seed": 42
}

Response:

{ "videoBase64": "<base64-encoded packed frame buffer>" }

Packed video format

After Base64-decoding videoBase64, the binary layout is:

[frameCount : Int32 LE][width : Int32 LE][height : Int32 LE][fps : Int32 LE]   ← 16 bytes
[frame 0 RGBA : width × height × 4 bytes]
[frame 1 RGBA : width × height × 4 bytes]
...

Parse it in Kotlin:

import java.nio.ByteBuffer
import java.nio.ByteOrder

val raw = Base64.getDecoder().decode(videoBase64)
val header = ByteBuffer.wrap(raw, 0, 16).order(ByteOrder.LITTLE_ENDIAN)
val frameCount = header.int
val width      = header.int
val height     = header.int
val fps        = header.int

val frameSize = width * height * 4
val frames = (0 until frameCount).map { i ->
    raw.copyOfRange(16 + i * frameSize, 16 + (i + 1) * frameSize)
}

See the Video generation guide for saving frames to the device gallery.

Release

POST /v1/stablediffusion/release

Free Stable Diffusion native resources.

{ "ok": true }

Parameter guidance

ParameterRecommended starting valueNotes
width / height512Larger sizes are much slower and require more memory
steps20More steps = better quality but slower
cfgScale7.06.0–8.0 is a typical range
seedany fixed valueUse -1 for random
videoFrames16More frames = longer clip but proportionally slower
fps8Playback rate; does not affect generation speed