
Un'integrazione affidabile per un comic a quattro pannelli richiede più di una sola richiesta di generazione. Il ciclo minimo per la produzione è:
carica riferimento del personaggio -> crea quattro pannelli -> esegui polling dello stato finale -> ispeziona ogni pannello -> ripara solo il pannello non riuscito
Questo avvio rapido implementa quel ciclo in TypeScript. Mantiene la chiave API sul server, fornisce un record del personaggio stabile, usa una chiave di idempotenza per la richiesta di creazione, registra il tempo trascorso e gli errori, e prende di mira un solo pannello quando la continuità si interrompe.
Inizia con la LlamaGen.AI Comic API, poi usa l'esempio completo qui sotto come base di integrazione lato server.
Questo articolo è stato verificato rispetto alla documentazione live della Comic API il 10 ottobre 2026.
| Check | Comportamento verificato |
|---|---|
| Autenticazione | Token Bearer su ogni richiesta |
| URL base di produzione | https://api.llamagen.ai |
| Upload | POST /v1/comics/upload restituisce un fileUrl riutilizzabile |
| Creazione | POST /v1/comics/generations accetta fixPanelNum: 4 e comicRoles |
| Stato | GET /v1/comics/generations/{generationId} restituisce stato e output dei pannelli |
| Riparazione | PATCH /v1/comics/generations/{generationId} può rigenerare un pannello indicizzato da zero |
| Utilizzo | Le risposte di creazione e riparazione espongono dati di utilizzo per i tuoi log |
Non abbiamo inventato un benchmark di latenza o tasso di successo. Questi valori variano in base all'account, alla coda, alla configurazione del modello e all'input. L'esempio registra il tuo tempo effettivo trascorso, l'utilizzo API, lo stato finale e i dettagli degli errori così puoi produrre un benchmark difendibile nel tuo ambiente.
Il prompt dice al modello cosa accade. Il riferimento del personaggio gli dice a chi sta accadendo la storia.
Per un ruolo ricorrente, mantieni stabili questi campi:
In questo esempio, il ruolo è un corriere con capelli corti scuri, una giacca antipioggia gialla e una borsa a tracolla rossa. Questi dettagli sono abbastanza compatti da poter essere ripetuti e abbastanza distintivi da poter essere verificati.

Usa Node.js 20 o una versione successiva così fetch, FormData e Blob siano disponibili. Mantieni la chiave in una variabile d'ambiente accessibile solo dal server.
export LLAMAGEN_API_KEY="your_server_side_key"
Non esporre questa chiave in un bundle browser, in un'applicazione mobile, in un repository pubblico o in una richiesta lato client. Se il tuo prodotto ha un frontend, invia la richiesta dell'utente al tuo backend e lascia che sia quel backend a chiamare LlamaGen.AI.
Il flusso di lavoro ha quattro operazioni di rete:

Salva quanto segue come comic-quickstart.ts, inserisci un'immagine del personaggio in ./courier-reference.png ed eseguilo dal tuo ambiente server.
Una panoramica delle ultime funzionalità rilasciate di LlamaGen, dei miglioramenti del prodotto, degli aggiornamenti di design e delle correzioni di bug più importanti.
import { basename } from "node:path";
import { readFile } from "node:fs/promises";
import { randomUUID } from "node:crypto";
const API_BASE = "https://api.llamagen.ai";
const API_KEY = process.env.LLAMAGEN_API_KEY;
if (!API_KEY) {
throw new Error("Set LLAMAGEN_API_KEY before running this script.");
}
type UploadResponse = {
code?: number;
fileUrl: string;
};
type Usage = {
total_comics?: number;
redraw_panels?: number;
amount?: number;
};
type Generation = {
id: string;
status: "LOADING" | "PROCESSED" | "FAILED" | "CANCELLED" | string;
usage?: Usage;
comics?: Array<{
page?: number;
panels?: Array<{
panel?: number;
image?: string;
assetUrl?: string;
caption?: string;
}>;
}>;
error?: unknown;
};
async function api<T>(path: string, init: RequestInit = {}): Promise<T> {
const response = await fetch(`${API_BASE}${path}`, {
...init,
headers: {
Authorization: `Bearer ${API_KEY}`,
...init.headers,
},
});
const text = await response.text();
const body = text ? JSON.parse(text) : null;
if (!response.ok) {
throw new Error(
`Comic API ${response.status}: ${JSON.stringify(body)}`,
);
}
return body as T;
}
async function uploadReference(filePath: string) {
const bytes = await readFile(filePath);
const form = new FormData();
form.set("file", new Blob([bytes]), basename(filePath));
return api<UploadResponse>("/v1/comics/upload", {
method: "POST",
body: form,
});
}
async function waitForGeneration(
generationId: string,
timeoutMs = 10 * 60_000,
) {
const startedAt = Date.now();
while (Date.now() - startedAt < timeoutMs) {
const job = await api<Generation>(
`/v1/comics/generations/${generationId}`,
);
console.log(
JSON.stringify({
generationId,
status: job.status,
elapsedMs: Date.now() - startedAt,
usage: job.usage,
}),
);
if (job.status === "PROCESSED") return job;
if (job.status === "FAILED" || job.status === "CANCELLED") {
throw new Error(
`Generation ended as ${job.status}: ${JSON.stringify(job.error)}`,
);
}
await new Promise((resolve) => setTimeout(resolve, 4_000));
}
throw new Error(`Generation ${generationId} timed out.`);
}
async function main() {
const startedAt = Date.now();
try {
const reference = await uploadReference("./courier-reference.png");
const created = await api<Generation>("/v1/comics/generations", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": randomUUID(),
},
body: JSON.stringify({
prompt: [
"Create one four-panel comic page in a restrained cinematic manga style.",
"Panel 1: Ren enters a rain-soaked station and notices a golden key.",
"Panel 2: Close view as Ren lifts the key and studies it.",
"Panel 3: Ren runs toward an old locked service door.",
"Panel 4: Ren opens the door and warm light spills into the station.",
"Keep the same face, haircut, yellow jacket, and red messenger bag.",
"Leave clean space for later lettering.",
].join("\n"),
preset: "japanese_manga",
size: "1024x1024",
fixPanelNum: 4,
language: "en",
comicRoles: [
{
name: "Ren",
age: 22,
gender: "male",
dress: "yellow rain jacket, black trousers, red messenger bag",
image: reference.fileUrl,
},
],
}),
});
const firstPass = await waitForGeneration(created.id);
console.log("first_pass_complete", {
id: firstPass.id,
elapsedMs: Date.now() - startedAt,
usage: firstPass.usage,
pages: firstPass.comics?.length ?? 0,
});
// Example review result: panel 3 lost the red bag.
const repairQueued = await api<Generation>(
`/v1/comics/generations/${created.id}`,
{
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
page: 0,
panel: 2,
panelPrompt:
"Ren runs toward the service door. Preserve his exact face, short dark hair, yellow rain jacket, and visible red messenger bag.",
images: [reference.fileUrl],
}),
},
);
console.log("repair_queued", {
id: repairQueued.id,
usage: repairQueued.usage,
});
const repaired = await waitForGeneration(created.id);
console.log("workflow_complete", {
id: repaired.id,
totalElapsedMs: Date.now() - startedAt,
finalStatus: repaired.status,
});
} catch (error) {
console.error("comic_workflow_failed", {
elapsedMs: Date.now() - startedAt,
message: error instanceof Error ? error.message : String(error),
});
process.exitCode = 1;
}
}
await main();
Eseguilo con:
npx tsx comic-quickstart.ts
L'esempio registra intenzionalmente oggetti strutturati. In produzione, invia gli stessi campi al tuo sistema di osservabilità e includi il tuo identificatore di richiesta o di progetto.
Non approvare una pagina solo perché sembra attraente in formato miniatura. Verifica ogni pannello rispetto al blocco del personaggio:
| Check | Condizione di superamento |
|---|---|
| Volto | Stessa età, stessi tratti e stesse proporzioni |
| Capelli | Stessa silhouette, stessa lunghezza e stesso colore |
| Costume | La giacca gialla rimane gialla e mantiene la stessa struttura |
| Oggetto | La borsa a tracolla rossa rimane presente e correttamente posizionata |
| Sequenza | Chiave, porta, meteo e direzione del movimento restano coerenti |
| Composizione | Ogni pannello ha una funzione narrativa distinta |
| Spazio per il lettering | Volti e azioni essenziali non sono ostruiti |
Tratta questo come controllo qualità leggibile da una macchina se stai costruendo una pipeline più ampia. Memorizza un motivo di superamento/fallimento per ogni pannello, non solo un'approvazione a livello di pagina.
Il prompt di riparazione più rapido nomina sia la nuova azione sia gli elementi che non possono cambiare.
Riparazione pannello 3:
Ren corre verso la porta di servizio.
Preserva il suo volto esatto, i capelli corti scuri, la giacca antipioggia gialla
e la borsa a tracolla rossa ben visibile.
Mantieni la stazione piovosa e il movimento da sinistra a destra.
Gli indici dei pannelli sono basati su zero, quindi il terzo pannello visibile è panel: 2. L'endpoint di aggiornamento può accettare panelPrompt, images di riferimento o una caption sostitutiva.

Questo è importante dal punto di vista operativo. Ricostruire tutti e quattro i pannelli può introdurre tre nuovi rischi di continuità mentre ne corregge uno vecchio. La riparazione mirata restringe la superficie di revisione.
Prima di distribuire l'integrazione, aggiungi questi controlli:
Per sequenze più lunghe, passa da fixPanelNum a pagination.totalPages e pagination.panelsPerPage. Non inviare entrambe le modalità nella stessa richiesta di creazione.
Usa la Comic API quando i comic vengono generati all'interno del tuo prodotto, job batch, strumento didattico, pipeline editoriale o flusso di lavoro del cliente.
Usa l'editor visuale quando un creatore vuole esplorare la storia in modo interattivo, confrontare alternative o dirigere artisticamente ogni pagina a mano. Molti team usano entrambi: l'API crea e registra il primo passaggio ripetibile, mentre l'editor gestisce le revisioni eccezionali.
Se la struttura della tua storia sta ancora cambiando, pianificala prima di creare pannelli definitivi. La guida successiva, Storyboard First or Comic Panels First?, mostra come misurare la differenza nel lavoro di rifacimento.
Sì. Invia fixPanelNum: 4 per una richiesta a pagina singola con quattro pannelli. Per più pagine, usa invece l'oggetto pagination.
Carica un'immagine di riferimento pulita, passa il fileUrl restituito in comicRoles[].image, mantieni stabili il nome del ruolo e la descrizione del costume, e controlla ogni pannello restituito prima di continuare la sequenza.
Sì. Invia una richiesta PATCH con gli indici di pagina e pannello basati su zero più un nuovo panelPrompt, immagini di riferimento opzionali o una didascalia.
Usa il comportamento di idempotenza documentato da LlamaGen.AI così i retry di rete non creino accidentalmente lavoro duplicato. Usa una nuova chiave solo quando vuoi intenzionalmente una nuova generazione.
No. Espone la strumentazione necessaria per acquisire i tuoi numeri reali. Pubblica latenza, utilizzo e tassi di errore solo dopo aver eseguito ripetutamente lo stesso input nel tuo account e aver registrato le condizioni.
Scritto da Jay e revisionato tecnicamente rispetto al contratto dell'endpoint live dal team contenuti di LlamaGen.AI. Il comportamento del prodotto può cambiare; la documentazione collegata è la fonte di verità.
Pronto a creare il flusso di lavoro? Apri la LlamaGen.AI Comic API, crea una chiave lato server ed esegui l'avvio rapido con il tuo riferimento del personaggio.
Popular creator tools
Go from comics and storyboards to stylized photos with LlamaGen.
Visualize every scene before production starts.
© 2026 LlamaGen.Ai Tutti i diritti riservati
Plasmare il futuro della generazione di fumetti con l'IA



