---
name: dubup-image
description: Écrit les prompts GPT Image 2 des visuels d'une scène Dub'Up - fiches personnage, fiches de lieu, images-clés de plan, avatars et posters - et les range selon la convention lue par dubup-video. Use when on prépare les visuels d'une scène, on crée ou fige un personnage ou un décor d'un univers, il faut un avatar ou un poster de catalogue, ou on parle de GPT Image 2 sur ce projet.
---

# dubup-image

Produit les **images fixes** d'une scène Dub'Up avec GPT Image 2. La vidéo est le travail de
`dubup-video` : ce skill s'arrête aux images, et à la convention de rangement qui permet à
l'autre de les reprendre.

## Ce que la division des rôles impose

La doc OpenAI prévient : *« the model may occasionally struggle to maintain visual consistency
for recurring characters across multiple generations »*. **Ne jamais compter sur GPT Image 2
pour tenir un casting d'un plan à l'autre.** Ce n'est pas son travail ici.

Son travail est de produire des **fiches figées** — une par personnage, **une par lieu** — que
le système de références de Seedance (jusqu'à 50 entrées, appelées `@Image 1`…) réutilise ensuite
pour tenir la cohérence sur les 30 s. D'où la règle : une fiche se génère **une seule fois par
univers**, se relit, se valide, et ne se régénère plus. Si on la régénère, tous les plans déjà
tournés avec deviennent incohérents.

### Pourquoi le lieu compte autant que le personnage — et dure plus longtemps

Une scène de 30 s change de plan quatre ou cinq fois. Si le décor bouge entre deux plans — une
fenêtre qui se déplace, un mur qui change de couleur, un objet qui disparaît — le joueur le voit
immédiatement, et la scène passe pour un montage raté. Or c'est exactement ce qui arrive quand
chaque plan est décrit par un paragraphe de texte : le modèle réinvente la pièce à chaque fois.

La fiche de lieu est donc l'ancrage **géométrique** de la scène, comme la fiche personnage est
l'ancrage des visages. Et elle a une durée de vie plus longue : un personnage appartient souvent
à une scène, un lieu ressert sur **toutes** les scènes de son univers. C'est l'image sur
laquelle il vaut le plus la peine de passer du temps.

Un lieu qui porte plus de deux plans a besoin de **2 ou 3 vues** — vue d'ensemble, puis les axes
que les plans vont emprunter. Une pièce vue d'un seul point de vue ne dit rien de ce qu'il y a
derrière la caméra, et Seedance l'inventera au premier contrechamp.

**Ces vues vont sur UNE seule planche, jamais en générations séparées.** C'est le même
raisonnement que pour un personnage, et il est encore plus tranchant ici : GPT Image 2 ne tient
pas la cohérence d'une génération à l'autre — c'est écrit dans sa propre doc. Trois générations
d'un même cabinet donnent trois cabinets. Sur une seule planche, le modèle est **obligé** de
dessiner la même pièce trois fois, puisqu'elle est dans la même image.

Format : vues **empilées**, pas côte à côte. Un mur est horizontal ; trois panneaux en colonne
gardent à chacun un cadre large. `1536x2592` donne trois cellules de `1536x864`.

## Étape 1 — Établir le profil visuel de l'univers, en deux blocs séparés

**C'est la distinction la plus facile à rater, et elle contamine tout le reste si on la manque.**

**`lookProfile` — la lumière et le rendu.** Qualité et direction de la lumière, température,
niveau de contraste, focale et distance dominantes, grain et support (35 mm, numérique propre,
VHS), registre de jeu. Ce bloc se recopie **à l'identique en tête de chaque prompt qui montre le
film** — fiches de lieu, images-clés, poster. C'est lui qui fait qu'un décor et un plan ont l'air
d'appartenir au même long métrage. **Une fiche personnage en est exemptée** : voir plus bas, elle
suit un gabarit studio fixe.

**`setProfile` — le décor.** La pièce, ses murs, ses meubles, son sol, ses ouvertures, son état.
Ce bloc ne va **que** sur les fiches de lieu, les images-clés et le poster. **Jamais** sur une
fiche personnage.

Pourquoi les séparer : une fiche personnage verrouille **une identité**. Tout ce qu'on y ajoute
devient une chose de plus que Seedance essaiera de reproduire — en concurrence directe avec la
fiche de lieu, seule autorité sur la géométrie. Deux références qui se contredisent sur la pièce
font plus de dégâts qu'une qui n'en parle pas. Et un personnage dont la fiche décrit un décor
n'est plus rejouable ailleurs.

Test simple avant d'envoyer un prompt de fiche personnage : **s'il contient un nom de meuble, un
nom de pièce ou une couleur de mur, il est à corriger.**

Si l'univers existe déjà, relire `output/scenes/*/refs/refs.json` des scènes du même `universe`
et reprendre les deux blocs tels quels plutôt que d'en inventer.

## Étape 2 — Écrire les prompts

Quatre types, quatre tailles. Toutes les tailles sont des multiples de 16, contrainte de
l'API.

| Type | `size` | Pourquoi |
|---|---|---|
| Fiche personnage | `2048x1152` | paysage : trois vues côte à côte sur une planche |
| **Fiche de lieu** | `1536x2592` | portrait : trois vues **empilées**, cellules de `1536x864` |
| Fiche d'accessoire | `2048x1152` | paysage : face, dos, trois-quarts |
| Image-clé de plan | `1536x864` | 16:9 exact, cadre le 1280×720 du catalogue |
| Avatar (`character.avatarUrl`) | `1024x1024` | carré, affiché petit dans l'app ; cadré sur le visage par `scripts/cadrer-avatars.mjs` (voir plus bas) |
| Poster (`video.posterUrl`) | `1536x864` | même cadre que la vidéo |

Le **fichier de l'avatar est le médaillon** : l'app (`Avatar`, apps/mobile/src/ui.tsx) le découpe
en rond tel quel, sans agrandir ni décaler. Il est donc cadré **sur le visage, à la même règle
pour tout le catalogue** — les yeux à 46 % de la hauteur, la distance yeux-menton à 38 % du côté,
le milieu des yeux au centre — par `node scripts/cadrer-avatars.mjs [slug]`, qui détecte le
visage avec MediaPipe (`tools/faces/cadrer_avatar.py`), prend la fiche personnage ou l'original
mis de côté comme source, réécrit `storage/scenes/<slug>/avatar-<key>.jpg` en 512 px et sort une
planche de contrôle dans `tmp/medaillons.png`. GPT Image 2 ne tient pas cette géométrie à la
demande, et un cadrage au jugé donnait à chaque personnage sa présence à lui (2026-09-15).
Sans visage détectable (un casque d'astronaute), le fichier actuel est gardé et signalé : là,
**Benjamin centre à l'œil** avec `node scripts/centrer-avatars.mjs`, qui dessine chaque avatar
comme le médaillon de l'app (on glisse, on agrandit, « Enregistrer » réécrit le fichier ;
l'original est mis de côté dans `storage/avatars-originaux/<slug>/`). Dans les deux cas,
recopier `storage/scenes` sur le Pi après.

Une **fiche de lieu est vide de personnages**. C'est un décor, pas une scène : la pièce, sa
lumière, ses meubles, l'état des choses. Y mettre quelqu'un ferait de la personne un élément du
décor, que Seedance recopierait dans tous les plans. Décrire aussi ce qui **borne** l'espace —
murs, ouvertures, sources de lumière — puisque c'est ce que les contrechamps iront chercher.

### Une fiche personnage est une feuille de modèle, pas un plan de film

C'est l'erreur la plus coûteuse du skill, parce qu'elle produit une image qui a l'air très
réussie et qui travaille contre nous.

Une fiche encode **une identité**, rien d'autre. Trois conséquences, toutes contre-intuitives :

| | À proscrire | À faire |
|---|---|---|
| Vues | une seule, en 3/4 | **trois sur une planche** : pied de face, pied de dos, gros plan visage |
| Lumière | celle de la scène | **studio neutre**, homogène, sans effet ni contre-jour |
| Expression | jouée, émotive | **neutre**, posture relâchée, bras le long du corps |

- **Trois vues**, parce qu'un 3/4 ne dit rien du dos ni de la nuque, et Seedance les inventera au
  premier contrechamp. C'est le même raisonnement que les angles d'une fiche de lieu.
- **Lumière studio**, parce qu'une fiche éclairée par la fenêtre de la scène risque de plaquer
  cette lumière sur tous les plans. La lumière appartient au plan ; la fiche donne le visage.
- **Expression neutre**, parce que l'émotion appartient elle aussi au plan. Une fiche qui pleure
  fera pleurer le personnage partout.

**Le `lookProfile` de l'univers ne s'applique donc PAS à une fiche personnage.** C'est la seule
exception à la règle de l'étape 1 — et c'est ce qui rend une fiche réutilisable dans un autre
univers, avec une autre lumière.

### Un accessoire qui change d'état a sa propre fiche

Le test qui range tout : **est-ce vrai du personnage pendant les 30 s entières ?**

- Oui → sur la fiche. Une coupe de cheveux, une monture de lunettes, une blouse.
- Non → **jamais** sur la fiche. Ça va dans le prompt du plan concerné.

Le piège est qu'un accessoire *ressemble* à du costume. Une poche déformée par un objet, une
manche retroussée, un dossier sous le bras : ce sont des **états**, pas des identités. Posés sur
la fiche, ils se reproduisent dans tous les plans — la poche gonfle encore alors que l'objet est
dans les mains du personnage depuis trois secondes, et la continuité est cassée par la référence
elle-même. C'est la même faute que d'y mettre une émotion.

Ce que la fiche personnage doit dire d'un accessoire : seulement **ce qui le rend possible** —
« deux poches plaquées assez profondes pour contenir un livre de poche, vides et à plat ».

L'objet, lui, prend une **fiche d'accessoire** : même gabarit studio, trois vues (face, dos,
trois-quarts), `kind: "prop"`, `1536x864`. Elle sert dès qu'un objet doit rester le même d'un
plan à l'autre — et c'est presque toujours le cas d'un objet qui porte une chute. Terminer le
bloc par `No logos, no lettering, no branding anywhere on the object` : c'est ce qui tient la
règle « aucune marque » sur un objet reconnaissable.

Structure de chaque prompt, dans cet ordre et en sections séparées :

**Fiche personnage** — gabarit fixe, indépendant de l'univers :

```
Character reference sheet. Three views of the same person side by side in one image,
evenly spaced against a plain seamless mid-grey studio backdrop: full-length front view
on the left, full-length rear view in the centre, head-and-shoulders close-up on the
right. Identical clothing, proportions and features in all three views.

Soft even studio lighting from a large frontal softbox with gentle fill. No coloured
light, no hard shadows, no backlight, no atmosphere. Neutral expression, relaxed upright
posture, arms at the sides. Natural full-colour rendering, never washed out, never
monochrome.

[Personne : cheveux (couleur, texture, coupe), carnation, yeux, forme du visage,
 vêtements, accessoires, morphologie. Marqueurs visuels uniquement, aucune émotion.]

Sharp photographic reference, real skin texture, real fabric texture, no digital
smoothing, no stylisation.
```

**Fiche de lieu, image-clé, poster** — là, le profil de l'univers s'applique :

```
[lookProfile, recopié à l'identique]                          ← TOUJOURS

[setProfile + ce qu'il y a dans le champ, état des choses]

[Personne : marqueurs visuels, posture et énergie jouées.]    ← sauf fiches de lieu

[Action ou pose : ce qui se passe dans le cadre. 1 phrase.]   ← sauf fiches de lieu

[Lumière et ambiance : d'où vient la lumière, ce qu'elle fait, ce que l'image fait ressentir.]

Cinematic still, 35mm, natural film grain, real skin texture, no digital smoothing.
```

Règles non négociables :

- **Aucune marque.** Décrire l'objet : pas « iPhone » mais « téléphone noir à grand écran ».
- **Jamais « desaturated », « washed out », « muted colours » seuls.** Poussés, ces mots virent
  au quasi-monochrome, et Dub'Up est en couleur. Poser la couleur **en positif** — quelles
  couleurs, sur quoi — et l'affirmer : `natural full-colour rendering, never washed out, never
  monochrome`. Une palette sobre se décrit en nommant ses teintes, pas en retirant de la
  saturation.
- **Aucun descripteur démographique.** Uniquement des marqueurs visuels. Un personnage se
  décrit par ses cheveux, sa carnation, sa tenue et sa posture — jamais par une catégorie.
- **Décor et personne toujours en sections distinctes.** C'est ce qui permet de rejouer un
  personnage dans un autre décor sans réécrire sa description.
- **Une image de référence = un prompt.** Ne jamais fondre deux intentions dans un prompt.
- Sur une **fiche de lieu**, supprimer les sections « Personne » et « Action » — il ne reste que
  le profil, le décor, la lumière. Sur une **fiche personnage**, réduire le décor à un fond
  neutre : ce qu'on fige est le visage, pas l'endroit.
- Les images sans personne (décor seul, insert sur un objet) sont souvent les plus utiles en
  référence Seedance : ne pas y forcer une présence humaine.

Ne pas transposer les réflexes de photo lifestyle : ici on cherche du **plan de cinéma**, cadré
et éclairé. Pas de « candid iPhone », pas de « handheld », pas de « not staged ».

## Étape 3 — Appeler l'API

```
POST /v1/images/generations
{
  "model": "gpt-image-2",       // snapshot par défaut : gpt-image-2-2026-04-21
  "prompt": "...",
  "size": "1536x864",
  "quality": "high",
  "background": "opaque",       // jamais "auto" ni "transparent" — voir ci-dessous
  "output_format": "png"
}
```

**`background: "opaque"`, toujours.** Sur une planche, le fond gris n'est pas du décor : son
dégradé et l'ombre de contact au sol disent d'où vient la lumière et où le corps repose. En
`auto`, le modèle peut détourer de lui-même sur un prompt qui contient « reference sheet », ce
qui contredirait le prompt. En `transparent`, le sujet flotte, la lumière n'est plus déductible,
et rien ne garantit ce que le générateur vidéo fera de la couche alpha au téléversement.

Retouche localisée d'une image existante : `POST /v1/images/edits` (inpainting, avec masque
optionnel), par `scripts/retoucher-image.mjs`. **Toujours préférer un `edit` à une régénération**
quand une fiche personnage est presque bonne — une régénération change le visage.

Deux pièges constatés sur la fiche de lieu d'« On vous rappelle » (2026-09-16) :

- **Le prompt d'un `edit` décrit l'image entière, pas la zone.** GPT Image 2 rejoue toute
  l'image en s'appuyant sur le prompt, le masque n'est qu'une consigne. Un prompt qui ne parle que
  du détail à corriger (« mur gris, pas de vitre ») a remplacé la baie vitrée entière par un mur.
  Écrire : « garder cette image exactement telle quelle : [ce qu'elle contient] ; la seule
  modification est [le détail], ne rien changer d'autre ».
- **Passer `size`.** Sans lui, l'API rend la retouche dans une taille à elle (965×1629 pour une
  planche de 1536×2592). Le script redemande la taille de la source.

Variantes `gpt-image-2.5-sunburst` et `gpt-image-2.5-flare` : mêmes paramètres, `quality` monte
à `xhigh` et `max`. À réserver aux fiches personnage, qui resservent longtemps.

Bornes des tailles personnalisées : côtés multiples de 16, ratio entre 1:3 et 3:1, aucun côté
au-delà de 3840 px, total entre 655 360 et 8 294 400 px. Au-delà de 2560×1440 c'est
expérimental.

## Étape 4 — Ranger, et écrire refs.json

**C'est le contrat avec `dubup-video`.** Sans lui, les deux skills ne composent pas.

```
output/scenes/<slug>/refs/
  character-<key>.png        une par personnage, <key> = characters[].key du manifeste
  location-<key>.png         une par lieu ; -2, -3 pour les angles supplémentaires
  shot-<n>.png               une image-clé par plan, numérotées dans l'ordre du montage
  avatar-<key>.png
  poster.png
  refs.json
```

```jsonc
{
  "slug": "the-box",
  "universe": "huis-clos",
  "visualProfile": "…le paragraphe de l'étape 1, mot pour mot…",
  "images": [
    { "ref": "@Image 1", "file": "character-anna.png", "kind": "character",
      "characterKey": "anna", "prompt": "…le prompt complet…" },
    { "ref": "@Image 2", "file": "location-cuisine.png", "kind": "location",
      "locationKey": "cuisine", "angle": "vue d'ensemble", "prompt": "…" },
    { "ref": "@Image 3", "file": "location-cuisine-2.png", "kind": "location",
      "locationKey": "cuisine", "angle": "contrechamp depuis la fenêtre", "prompt": "…" },
    { "ref": "@Image 4", "file": "shot-1.png", "kind": "shot", "shot": 1, "prompt": "…" }
  ]
}
```

Le champ `ref` est ce que `dubup-video` écrira littéralement dans le prompt Seedance — syntaxe
Higgsfield, arobase et espace compris. Le numéro est le **rang de téléversement** dans
l'interface, donc l'ordre de ce fichier. L'ordre est
imposé : **personnages, puis lieux, puis plans**. Ce sont les positions des fiches qui doivent
rester stables d'une scène à l'autre — celles des plans changent à chaque scène, et c'est sans
conséquence.

Les fiches de lieu d'un univers déjà tourné se **copient** depuis la scène précédente, elles ne
se régénèrent pas. Le `locationKey` est ce qui permet de les retrouver.

Garder le `prompt` complet dans le fichier : sans lui, impossible de refaire une image dans le
même esprit six mois plus tard.

## Étape 5 — Rendre compte

Dire lesquelles sont des images de décor et lesquelles portent un personnage, et pourquoi. Pour
chaque lieu, dire **combien d'angles** ont été produits et lesquels des plans prévus ils
couvrent — un contrechamp non couvert est le défaut qu'on ne verra qu'après avoir payé la
génération vidéo.

Puis rappeler ce qui suit : les fiches personnage et les fiches de lieu sont maintenant
**figées** ; toute reprise passe par `images.edit`, pas par une nouvelle génération.

## Itération

Si une image ne va pas, demander : « qu'est-ce qui cloche — la lumière, le décor, le personnage,
ou l'ambiance générale ? », puis réécrire **ce seul prompt**. Ne jamais tout réécrire sans
demande explicite.
