What is Obraz
Obraz renders and edits a Wisent image. One service owns the job: the recipe that turns a creator, a pose and a description into a prompt, the adapter that makes the image that creator's, the render itself, the picture that comes back, and the edits made to it afterwards.
Editing takes the tools of a photo editor —
crop, turn, resize, canvas and collage; tone controls, looks, duotone and
colour tables; blur, mosaic, sharpening, vignette and grain; text, stickers
and shapes — as one plan of steps, and sends the steps a model does
(generating, background removal and replacement, erasing, extending the
frame, restyling, colourising, restoring, retouching, relighting) to an
image-model service: Brama in a Wisent deployment, or the OpenAI API. A
person edits in the browser editor Obraz serves at /; the
quickstart goes from installing Obraz to the
first edited picture.
The recipe
- The trigger word leads the prompt, because an adapter
whose trigger word arrives late renders a stranger. Then the description
(
prompt), or the pose (pose_id) with itscaption. The prompt sent is<trigger word>, <description>. - The adapter: one LoRA file
(
lora.filename) and itslora.strength, both required and passed to ComfyUI as given; how strongly a creator's adapter applies is the creator's recipe, not Obraz's. - The frame:
widthandheighttogether, or neither, in which case the deployment'sOBRAZ_FRAME(configuration) is used. Any size limit is ComfyUI's, and its refusal comes back as Obraz's error.
A request that carries graph, a ComfyUI graph the caller
assembled, is executed as written and the recipe is not used.
The service
POST /v1/images render one image
POST /v1/edits edit pictures with a plan of steps (see Editing pictures)
GET /v1/edits/operations the steps an edit plan can hold
GET /health the process is up
GET / the editor, in a browser
GET /readyz the renderer's address, and the image-model service model steps go to or why there is none
POST /v1/images
x-obraz-secret: <the deployment's secret>
{"prompt": "on a balcony at sunset",
"trigger_word": "isre",
"lora": {"filename": "isre_portrait_r64_v1", "strength": 0.9}}
The request also takes pose_id, caption,
width, height, seed,
character_id, graph and
deliver_inline; any other field is refused. The answer is
success, job_id, prompt (as rendered),
url, and error when there is no image. With
deliver_inline: true Obraz fetches the image from the renderer
and adds image_base64 and mime_type; a fetch that
fails is a failed render.
A Rust caller uses obraz::client::ObrazClient and never
assembles a graph itself; the CLI is that
client on a shell.
Refusals the service answers
Every refusal is the same answer shape with success: false and
the reason in error.
401unauthorized
: a missing or wrongx-obraz-secret.400trigger_word is required: without it the adapter renders a stranger
400lora is required: name the creator's adapter file and strength
400lora.filename must name an adapter file
400lora.strength must be a number
400either prompt or pose_id is required
400width and height are required: this Obraz declares no OBRAZ_FRAME for a request that names no size
400width and height are named together, or neither
400width and height must be at least 1
422alorawithoutstrength, refused by the JSON reader naming the field:missing field `strength`
.503this Obraz has no renderer: its deployment sets OBRAZ_COMFYUI_URL
502the renderer's refusal in its own words, or a failed inline fetch:the backend answered <status> for the image it had just rendered
,the backend answered with an empty image
.