Pro API: generare e ritoccare immagini
Un'immagine costa 1 credito, qualunque sia la modalità. La generazione da un prompt e il ritocco di un'immagine che fornisci tu passano entrambi per la stessa rotta.
POST /images/quote accetta lo stesso corpo e risponde con il prezzo senza creare nulla, sempre
{ "cost": 1, ... } in questo caso. Esiste per simmetria con i video, dove il prezzo può variare.
Invia un'immagine
POST /images
{ "prompt": "portrait of a woman in a rainy street at night, neon reflections, cinematic",
"width": 832, "height": 1216 }| Campo | Tipo | Predefinito | Cosa fa |
|---|---|---|---|
prompt | string | obbligatorio | La scena. L'inglese dà i risultati più precisi. |
width, height | int | 1024 x 1024 | Dimensione in pixel. Proporzioni consigliate: 1024 x 1024 (quadrato), 832 x 1216 (verticale), 1216 x 832 (orizzontale). |
mode | string | generation | edit, img2img o inpaint, vedi sotto. Assente significa generare dal prompt. |
image_b64 | string | Immagine sorgente in base64 (PNG o JPEG), obbligatoria per tutte e tre le modalità di ritocco. Massimo 12 MB decodificati. | |
mask_b64 | string | Maschera in base64: obbligatoria per inpaint, opzionale per edit. Dipingi in rosso le aree da ritoccare, nelle dimensioni dell'immagine sorgente. | |
lora | string | Un personaggio addestrato sull'account: il name restituito da GET /loras. Inserisci il suo trigger nel prompt. | |
lora2, lora2_strength | string, number | Un secondo personaggio e la sua intensità (da 0 a 1, predefinito 1) per una scena con due persone. | |
count | int | 1 | Quante immagini generare da questa richiesta, da 1 a 8. Ognuna ottiene il proprio seed; con seed, prendono seed, seed+1, seed+2... È il selettore Immagini per generazione dell'app. |
seed | int | casuale | Seed del rendering, da 0 a 4294967295. Stesso seed, stesso prompt e stesse impostazioni: stesso rendering, con differenze minime se cambia la scheda grafica. Mantenere il seed e modificare il prompt dà una variazione che conserva la composizione. |
steps | int | engine | Lascia vuoto. Il motore conosce il proprio valore. |
La risposta:
{ "jobId": "test-79634842-4586-46d4-ad52-d9ea236ae00d", "seed": 178078967, "cost": 1 }Il seed viene restituito nella risposta, che tu lo abbia fornito o sia stato estratto casualmente: conservalo per
rendere di nuovo la stessa immagine, o una sua variazione.
Richiedere più immagini contemporaneamente
Con count superiore a 1, una sola richiesta avvia più rendering, ognuno con il proprio seed, e
la risposta li elenca tutti:
{ "count": 4, "requested": 4, "cost_total": 4,
"jobs": [ { "jobId": "...", "seed": 178078967, "cost": 1 }, { "jobId": "...", "seed": 903412, "cost": 1 } ],
"errors": [],
"jobId": "...", "seed": 178078967, "cost": 1 }Due cose da leggere con attenzione.
Il jobId, il seed e il cost del primo rendering vengono ripetuti al livello superiore. È lì
perché i client scritti prima delle batch continuino a funzionare senza modifiche, non perché il primo
sia più importante. Fai il polling di ogni elemento di jobs, non solo di quello.
E confronta count con requested. Un rifiuto a metà, per mancanza di crediti o perché la chiave ha
raggiunto il limite giornaliero, interrompe la batch nel punto in cui si trova: requested è quello che hai
chiesto, count è quello che è effettivamente partito, e errors spiega perché si è fermato. Un client che
presuppone che i due siano uguali perde rendering in silenzio.
POST /images/quote accetta anche count e calcola il prezzo dell'intera batch. I video non hanno count:
una richiesta, un clip.
Le tre modalità di ritocco
Tutte e tre girano sullo stesso motore di editing guidato da istruzioni, che preserva l'aspetto dell'immagine
sorgente. Quando fornisci un'immagine sorgente, width e height vengono lette dall'immagine stessa e non
è necessario inviarle.
mode | Input | Cosa fa il motore |
|---|---|---|
edit | image_b64 + prompt (+ mask_b64 opzionale) | Applica l'istruzione all'intera immagine ("add sunglasses", "make it snow"). Con una maschera, la modifica si concentra nell'area rossa. |
inpaint | image_b64 + mask_b64 + prompt | Rigenera solo l'area rossa della maschera, seguendo l'istruzione. Il resto viene ricomposto pixel per pixel. |
img2img | image_b64 + prompt | Rielabora l'intera immagine seguendo il prompt mantenendone la composizione e l'aspetto: una variazione. |
In edit, il server sceglie da solo il modo migliore di trattare il ritocco, come l'app:
- con una maschera: legge l'istruzione e sceglie tra sostituire il contenuto della zona (un altro oggetto, un altro capo, un volto: la zona viene ridisegnata in base a ciò che deve comparirvi) e modificare ciò che c'è (colore, materiale, luce). Con un
loradi personaggio, la zona viene sempre ridisegnata, volto compreso; - senza maschera, con un
loradi personaggio ("replace the woman with kara..."): il server trova la persona della foto e la ridisegna con il personaggio; se non trova nessuno, l'istruzione si applica a tutta l'immagine, come prima.
Stesso prezzo in ogni caso (1 credito per immagine). La scelta si vede nel risultato, non nella risposta.
IMG=$(base64 -w0 photo.png)
curl -s $B/images -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d "{\"mode\":\"edit\",\"prompt\":\"add a red scarf, keep everything else identical\",\"image_b64\":\"$IMG\"}"Crea un'immagine con personaggi, oggetti e un'ambientazione
Aggiungi un oggetto multiref a POST /images e il server fa recitare i tuoi personaggi (Personaggi), i tuoi oggetti e animali e un'ambientazione (Soggetti) insieme in una sola immagine, ognuno riconoscibile, come la schermata «Crea un'immagine» dell'app. Chiama ognuno con @Nome nel prompt, in inglese.
{ "prompt": "@Mia hands a cup of coffee to @Tom on a sunny terrace, both smiling",
"multiref": {
"characters": [
{ "character_id": "chr_8f3a...", "name": "Mia", "view": 1 },
{ "character_id": "chr_21bc...", "name": "Tom", "lora": "tom_v1", "strength": 1.0, "lora_pass": 0.55 }
],
"subjects": [ { "subject_id": "sub_...", "name": "Mug" } ],
"location": { "subject_id": "sub_...", "name": "Terrace" }
},
"width": 1344, "height": 768, "seed": 42, "count": 1 }Campo di multiref | Cosa fa |
|---|---|
characters[].character_id, name | Un personaggio da GET /characters; name è la parola scritta dopo @ (lettere, cifre, _). |
characters[].view | La vista della sua sheet che lo rappresenta, da 1 a 5 (1, il busto frontale, per impostazione predefinita). |
characters[].sheet_id | Opzionale: la sheet da usare (la più recente per impostazione predefinita). |
characters[].lora | Opzionale: il suo LoRA d'immagine, un nome della lista image di GET /loras. Il personaggio è allora interpretato dal suo LoRA, non dalla sua vista. |
characters[].strength | Intensità del LoRA, da 0 a 1,5 (1 per impostazione predefinita). |
characters[].lora_pass | Parte dell'immagine ridipinta dalla sua passata LoRA, da 0,3 a 0,9 (0,55 per impostazione predefinita); utile con più soggetti. |
characters[].description | Opzionale, in inglese: outfit, età... |
subjects[] | Oggetti e animali da /subjects: subject_id, name (per impostazione predefinita la prima parola del suo nome), description, image (quale delle sue immagini, 1 per impostazione predefinita). |
location | Un'ambientazione da /subjects (subject_id, name), o uno sfondo occasionale: background_b64 e background_description. |
count | 1 o 2: le immagini vengono generate una dopo l'altra. |
- Al massimo 4 soggetti (personaggi, oggetti e animali). Senza LoRA, solo da immagini: al massimo 4 riferimenti, ambientazione compresa. Il server sceglie il metodo in base ai riferimenti, e colloca ciascuno nell'ordine di
characterse poi disubjects, da sinistra a destra. - Un
@Nomeche non corrisponde a nessun riferimento viene rifiutato (unknown_mention); un riferimento assente dal prompt viene inviato comunque. - Prezzo: una passata costa il prezzo di un'immagine (1 credito). Un'immagine semplice è 1 passata; più personaggi interpretati da un LoRA, 1 più una passata per LoRA (al massimo 4); solo da immagini, una passata per ogni riferimento oltre il primo; un mix, entrambe le cose. Il totale (passate x
count) viene riservato all'invio e addebitato una sola volta, all'immagine finale: un errore o un annullamento non costa nulla.POST /images/quotecon lo stesso corpo dà il prezzo esatto, il metodo e le sue passate, senza avviare nulla. - Risposta
202:{ "jobId": "mri_...", "seed", "cost", "method", "passes", "billed_passes" }(concount2:jobsecost_total). Polling, download e annullamento usano le solite rotte qui sotto; durante il rendering,progressindica la passata in corso ("2/3"). Un'immagine richiede da 1 a 3 minuti. - L'immagine finale resta disponibile per 1 ora, e 10 minuti dopo il suo primo download. Una passata fallita dà
status: "failed"conreason: "render_failed"; un annullamento,reason: "cancelled". - Errori:
invalid_count,invalid_view,invalid_lora_pass,invalid_subject_image,invalid_size,character_not_ready, più quelli di Multi-Ref (unknown_character,unknown_subject,unknown_lora,unknown_mention,multiref_too_many_references,invalid_strength...). Vedi Limiti ed errori.
Polling
GET /images/{jobId}
| Risposta | Significato |
|---|---|
{ "status": "pending", "phase": "IN_QUEUE" } | In coda |
{ "status": "pending", "phase": "IN_PROGRESS" } | In rendering |
{ "status": "completed", "cost": 1, "file_url": "/pro/v1/images/{jobId}/file", ... } | Completato, file pronto |
{ "status": "failed", "detail": "..." } | Fallito, e non viene addebitato nulla |
Fai il polling ogni 3 secondi, non più spesso: la coda è condivisa.
Download
GET /images/{jobId}/file
Il file PNG vero e proprio, come corpo della risposta (Content-Type: image/png). Disponibile non appena
lo stato è completed, e 404 media_unavailable una volta che il rendering è scaduto. Scaricalo subito,
non viene archiviato.
Annullamento
POST /images/{jobId}/cancel
Annulla un rendering in coda o in esecuzione. Risponde { "ok": true }. Non viene addebitato nulla, e il costo
riservato al limite giornaliero della chiave viene restituito.