
Une intégration fiable de comic en quatre cases nécessite plus d’une seule requête de génération. La boucle minimale en production est :
téléverser une référence de personnage -> créer quatre cases -> interroger l’état terminal -> inspecter chaque case -> réparer uniquement la case en échec
Ce démarrage rapide implémente cette boucle en TypeScript. Il conserve la clé API côté serveur, fournit un enregistrement de personnage stable, utilise une clé d’idempotence pour la requête de création, enregistre le temps écoulé et les échecs, et cible une seule case lorsque la continuité est rompue.
Commencez avec la LlamaGen.AI Comic API, puis utilisez l’exemple complet ci-dessous comme base d’intégration côté serveur.
Cet article a été vérifié contractuellement par rapport à la documentation de l’API Comic en ligne le 10 octobre 2026.
| Vérification | Comportement vérifié |
|---|---|
| Authentification | Jeton Bearer sur chaque requête |
| URL de base de production | https://api.llamagen.ai |
| Téléversement | POST /v1/comics/upload renvoie un fileUrl réutilisable |
| Création | POST /v1/comics/generations accepte fixPanelNum: 4 et comicRoles |
| Statut | GET /v1/comics/generations/{generationId} renvoie le statut et la sortie des cases |
| Réparation | PATCH /v1/comics/generations/{generationId} peut régénérer une case à index zéro |
| Utilisation | Les réponses de création et de réparation exposent des données d’utilisation pour vos propres journaux |
Nous n’avons pas inventé de benchmark de latence ou de taux de réussite. Ces valeurs varient selon le compte, la file d’attente, la configuration du modèle et l’entrée. L’exemple enregistre votre temps réel écoulé, l’utilisation de l’API, le statut terminal et les détails d’échec afin que vous puissiez produire un benchmark défendable dans votre propre environnement.
Le prompt indique au modèle ce qui se passe. La référence de personnage lui indique à qui l’histoire arrive.
Pour un rôle récurrent, gardez ces champs stables :
Dans cet exemple, le rôle est un coursier avec des cheveux courts foncés, une veste de pluie jaune et une sacoche rouge. Ces détails sont assez compacts pour être répétés et assez distinctifs pour être audités.

Utilisez Node.js 20 ou plus récent afin que fetch, FormData et Blob soient disponibles. Conservez la clé dans une variable d’environnement accessible uniquement côté serveur.
export LLAMAGEN_API_KEY="your_server_side_key"
N’exposez pas cette clé dans un bundle navigateur, une application mobile, un dépôt public ou une requête côté client. Si votre produit a un frontend, envoyez le brief de l’utilisateur à votre propre backend et laissez ce backend appeler LlamaGen.AI.
Le workflow comporte quatre opérations réseau :

Enregistrez le contenu suivant sous comic-quickstart.ts, placez une image de personnage dans ./courier-reference.png, puis exécutez-le depuis votre environnement serveur.
Un aperçu des dernières fonctionnalités de LlamaGen, des améliorations produit, des mises à jour de design et des corrections de bugs importantes.
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();
Exécutez-le avec :
npx tsx comic-quickstart.ts
L’exemple journalise volontairement des objets structurés. En production, envoyez les mêmes champs à votre système d’observabilité et incluez votre propre identifiant de requête ou de projet.
N’approuvez pas une page simplement parce qu’elle paraît attrayante en miniature. Auditez chaque case par rapport au verrouillage du personnage :
| Vérification | Condition de réussite |
|---|---|
| Visage | Même âge, mêmes traits et mêmes proportions |
| Cheveux | Même silhouette, longueur et couleur |
| Costume | La veste jaune reste jaune et conserve la même construction |
| Accessoire | La sacoche rouge reste présente et correctement placée |
| Séquence | La clé, la porte, la météo et la direction du déplacement restent continus |
| Composition | Chaque case a une fonction narrative distincte |
| Espace pour le lettrage | Les visages et les actions essentielles ne sont pas bloqués |
Traitez cela comme un contrôle qualité lisible par machine si vous construisez un pipeline plus large. Stockez une raison de réussite ou d’échec par case, et pas seulement une approbation globale de la page.
Le prompt de réparation le plus rapide nomme à la fois la nouvelle action et les éléments qui ne doivent pas changer.
Réparation de la case 3 :
Ren court vers la porte de service.
Préservez son visage exact, ses cheveux courts foncés, sa veste de pluie jaune,
et sa sacoche rouge visible.
Conservez la gare pluvieuse et le mouvement de gauche à droite.
Les index des cases sont basés sur zéro, donc la troisième case visible est panel: 2. Le point de terminaison de mise à jour peut accepter panelPrompt, des images de référence ou un caption de remplacement.

C’est important sur le plan opérationnel. Reconstruire les quatre cases peut introduire trois nouveaux risques de continuité tout en en corrigeant un ancien. Une réparation ciblée réduit la surface de revue.
Avant de livrer l’intégration, ajoutez ces contrôles :
Pour des séquences plus longues, passez de fixPanelNum à pagination.totalPages et pagination.panelsPerPage. N’envoyez pas les deux modes dans une même requête de création.
Utilisez la Comic API lorsque des comics sont générés dans votre propre produit, traitement par lot, outil éducatif, pipeline de publication ou workflow client.
Utilisez l’éditeur visuel lorsqu’un créateur veut explorer l’histoire de manière interactive, comparer des alternatives ou diriger artistiquement chaque page à la main. Beaucoup d’équipes utilisent les deux : l’API crée et journalise la première passe reproductible, tandis que l’éditeur gère les révisions exceptionnelles.
Si la structure de votre histoire évolue encore, planifiez-la avant de produire des cases finalisées. Le guide suivant, Storyboard First or Comic Panels First?, montre comment mesurer la différence de retravail.
Oui. Envoyez fixPanelNum: 4 pour une requête d’une seule page en quatre cases. Pour plusieurs pages, utilisez plutôt l’objet pagination.
Téléversez une image de référence propre, transmettez le fileUrl renvoyé dans comicRoles[].image, gardez stables le nom du rôle et la description du costume, puis auditez chaque case renvoyée avant de poursuivre la séquence.
Oui. Envoyez une requête PATCH avec les index de page et de case basés sur zéro, ainsi qu’un nouveau panelPrompt, des images de référence facultatives ou un caption.
Utilisez le comportement d’idempotence documenté par LlamaGen.AI afin que les nouvelles tentatives réseau ne créent pas accidentellement un travail dupliqué. Utilisez une nouvelle clé uniquement lorsque vous souhaitez intentionnellement une nouvelle génération.
Non. Il expose l’instrumentation nécessaire pour capturer vos vrais chiffres. Ne publiez la latence, l’utilisation et les taux d’échec qu’après avoir exécuté plusieurs fois la même entrée dans votre propre compte et enregistré les conditions.
Rédigé par Jay et relu techniquement par l’équipe de contenu de LlamaGen.AI par rapport au contrat du point de terminaison en ligne. Le comportement du produit peut changer ; la documentation liée fait foi.
Prêt à créer le workflow ? Ouvrez la LlamaGen.AI Comic API, créez une clé côté serveur et exécutez le démarrage rapide avec votre propre référence de personnage.
Popular creator tools
Go from comics and storyboards to stylized photos with LlamaGen.
© 2026 LlamaGen.Ai Tous droits réservés
Façonner l'avenir de la création de bandes dessinées par l'IA



