Pro API: gerar e retocar imagens
Uma imagem custa 1 crédito, independentemente do modo. A geração a partir de um prompt e o retoque de uma imagem que forneças passam ambos pela mesma rota.
POST /images/quote aceita o mesmo corpo e responde com o preço sem criar nada, sempre
{ "cost": 1, ... } aqui. Existe por simetria com os vídeos, onde o preço varia.
Submeter uma imagem
POST /images
{ "prompt": "portrait of a woman in a rainy street at night, neon reflections, cinematic",
"width": 832, "height": 1216 }| Campo | Tipo | Padrão | O que faz |
|---|---|---|---|
prompt | string | obrigatório | A cena. Inglês dá os resultados mais precisos. |
width, height | int | 1024 x 1024 | Tamanho em píxeis. Formatos recomendados: 1024 x 1024 (quadrado), 832 x 1216 (retrato), 1216 x 832 (paisagem). |
mode | string | generation | edit, img2img ou inpaint, ver abaixo. Ausente significa gerar a partir do prompt. |
image_b64 | string | Imagem de origem em base64 (PNG ou JPEG), obrigatória pelos três modos de retoque. No máximo 12 MB descodificados. | |
mask_b64 | string | Máscara em base64: obrigatória para inpaint, opcional para edit. Pinta as áreas a retocar a vermelho, com o tamanho da imagem de origem. | |
lora | string | Uma personagem treinada na conta: o name devolvido por GET /loras. Coloca o seu trigger no prompt. | |
lora2, lora2_strength | string, number | Uma segunda personagem e a sua intensidade (0 a 1, padrão 1) para uma cena com duas pessoas. | |
count | int | 1 | Quantas imagens gerar com este pedido, de 1 a 8. Cada uma recebe a sua própria seed; com seed, usam seed, seed+1, seed+2... É o seletor Imagens por geração da aplicação. |
seed | int | aleatória | Seed do render, de 0 a 4294967295. Mesma seed, mesmo prompt e mesmas definições: o mesmo render, com diferenças muito ligeiras se a placa gráfica mudar. Manter a seed e ajustar o prompt dá uma variação que preserva a composição. |
steps | int | motor | Deixa vazio. O motor conhece o seu próprio valor. |
A resposta:
{ "jobId": "test-79634842-4586-46d4-ad52-d9ea236ae00d", "seed": 178078967, "cost": 1 }A seed é devolvida na resposta, quer a tenhas indicado quer tenha sido sorteada aleatoriamente: guarda-a para
renderizar a mesma imagem de novo, ou uma variação dela.
Pedir várias de uma vez
Com count acima de 1, um pedido inicia vários renders, cada um com a sua própria seed, e a
resposta lista-os todos:
{ "count": 4, "requested": 4, "cost_total": 4,
"jobs": [ { "jobId": "...", "seed": 178078967, "cost": 1 }, { "jobId": "...", "seed": 903412, "cost": 1 } ],
"errors": [],
"jobId": "...", "seed": 178078967, "cost": 1 }Dois pontos a ler com atenção.
O jobId, a seed e o cost do primeiro render são repetidos ao nível superior. Isso existe
para que clientes escritos antes dos lotes continuem a funcionar sem alterações, não porque o primeiro seja mais importante. Faz polling de todas as entradas de jobs, não apenas dessa.
E compara count com requested. Uma recusa a meio do processo, por falta de créditos ou
porque a chave atingiu o limite diário, interrompe o lote onde estiver: requested é o que pediste,
count é o que realmente começou, e errors explica por que parou. Um cliente que assume
que os dois são iguais perde renders silenciosamente.
POST /images/quote também aceita count e calcula o preço de todo o lote. Os vídeos não têm count:
um pedido, um clip.
Os três modos de retoque
Os três funcionam com o mesmo motor de edição por instrução, que preserva o aspeto da
imagem de origem. Quando forneces uma imagem de origem, width e height são lidos a partir da própria imagem e não precisam de ser enviados.
mode | Entradas | O que o motor faz |
|---|---|---|
edit | image_b64 + prompt (+ mask_b64 opcional) | Aplica a instrução a toda a imagem ("add sunglasses", "make it snow"). Com máscara, a alteração concentra-se dentro da área vermelha. |
inpaint | image_b64 + mask_b64 + prompt | Regenera apenas a área vermelha da máscara, seguindo a instrução. O resto é recomposto pixel a pixel. |
img2img | image_b64 + prompt | Rework completo da imagem seguindo o prompt, mantendo a sua composição e aspeto: uma variação. |
Em edit, o servidor escolhe sozinho a melhor forma de tratar o retoque, como a app:
- com máscara: lê a instrução e escolhe entre substituir o conteúdo da zona (outro objeto, outra peça de roupa, um rosto: a zona é redesenhada a partir do que deve lá aparecer) e modificar o que lá está (cor, material, luz). Com um
lorade personagem, a zona é sempre redesenhada, rosto incluído; - sem máscara, com um
lorade personagem ("replace the woman with kara..."): o servidor encontra a pessoa da fotografia e redesenha-a com a personagem; se não encontrar ninguém, a instrução aplica-se à imagem inteira, como antes.
Mesmo preço em todos os casos (1 crédito por imagem). A escolha vê-se no resultado, não na resposta.
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\"}"Criar uma imagem com personagens, objetos e um cenário
Adiciona um objeto multiref ao POST /images e o servidor põe as tuas personagens (Personagens), os teus objetos e animais e um cenário (Sujeitos) a atuar juntos numa só imagem, cada um reconhecível, como o ecrã «Criar uma imagem» da aplicação. Chama cada um por @Name no prompt, em inglês.
{ "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 de multiref | O que faz |
|---|---|
characters[].character_id, name | Uma personagem de GET /characters; name é a palavra escrita após @ (letras, dígitos, _). |
characters[].view | A vista da sua sheet que a representa, de 1 a 5 (1, o busto de frente, por padrão). |
characters[].sheet_id | Opcional: a sheet a usar (a mais recente por padrão). |
characters[].lora | Opcional: o seu LoRA de imagem, um nome da lista image de GET /loras. A personagem é então interpretada pelo seu LoRA, não pela sua vista. |
characters[].strength | Intensidade do LoRA, de 0 a 1,5 (1 por padrão). |
characters[].lora_pass | Parte da imagem repintada pela sua passagem de LoRA, de 0,3 a 0,9 (0,55 por padrão); útil com vários sujeitos. |
characters[].description | Opcional, em inglês: roupa, idade... |
subjects[] | Objetos e animais de /subjects: subject_id, name (por padrão, a primeira palavra do seu nome), description, image (qual das suas imagens, 1 por padrão). |
location | Um cenário de /subjects (subject_id, name), ou um cenário pontual: background_b64 e background_description. |
count | 1 ou 2: as imagens são renderizadas uma após a outra. |
- No máximo 4 sujeitos (personagens, objetos e animais). Sem LoRA, apenas a partir de imagens: no máximo 4 referências, cenário incluído. O servidor escolhe o método a partir das referências e coloca cada uma pela ordem de
characterse depois desubjects, da esquerda para a direita. - Um
@Nameque não corresponde a nenhuma referência é recusado (unknown_mention); uma referência ausente do prompt é enviada na mesma. - Preço: uma passagem custa o preço de uma imagem (1 crédito). Uma imagem simples é 1 passagem; várias personagens interpretadas por um LoRA, 1 mais uma passagem por LoRA (no máximo 4); apenas a partir de imagens, uma passagem por referência além da primeira; uma mistura, ambos. O total (passagens x
count) é reservado na submissão e debitado uma única vez, na imagem final: uma falha ou um cancelamento não custa nada.POST /images/quotecom o mesmo corpo dá o preço exato, o método e as suas passagens, sem iniciar nada. - Resposta
202:{ "jobId": "mri_...", "seed", "cost", "method", "passes", "billed_passes" }(comcount2:jobsecost_total). O polling, o download e o cancelamento usam as rotas habituais abaixo; durante a renderização,progressindica a passagem em curso ("2/3"). Uma imagem demora 1 a 3 minutos. - A imagem final fica disponível durante 1 hora, e 10 minutos após o seu primeiro download. Uma passagem falhada dá
status: "failed"comreason: "render_failed"; um cancelamento,reason: "cancelled". - Erros:
invalid_count,invalid_view,invalid_lora_pass,invalid_subject_image,invalid_size,character_not_ready, mais os do Multi-Ref (unknown_character,unknown_subject,unknown_lora,unknown_mention,multiref_too_many_references,invalid_strength...). Ver Limites e erros.
Polling
GET /images/{jobId}
| Resposta | Significado |
|---|---|
{ "status": "pending", "phase": "IN_QUEUE" } | Em fila |
{ "status": "pending", "phase": "IN_PROGRESS" } | A renderizar |
{ "status": "completed", "cost": 1, "file_url": "/pro/v1/images/{jobId}/file", ... } | Concluído, ficheiro pronto |
{ "status": "failed", "detail": "..." } | Falhou, e nada é cobrado |
Faz polling a cada 3 segundos, não mais rápido: a fila é partilhada.
Download
GET /images/{jobId}/file
O próprio PNG, como corpo da resposta (Content-Type: image/png). Disponível assim que o
estado for completed, e 404 media_unavailable assim que o render for eliminado. Faz o download imediatamente, pois não fica arquivado.
Cancelar
POST /images/{jobId}/cancel
Cancela um render em fila ou em execução. Responde { "ok": true }. Nada é cobrado, e o custo
reservado contra o limite diário da chave é devolvido.