Configuration du projet
Objectif : transformer un clone vierge en pipeline qui monte dans le style de cette personne — comprendre ce qu'il/elle aime, connecter ses services et montrer des images de sa future vidéo. Parle dans la langue de l'utilisateur, de manière courte et humaine.
Le projet n'a pas son propre style. Tout ce qui concerne l'apparence de la vidéo — palette, polices, sous-titres, cartes, stickers, poster, tempo, punch-ins, grading, son — est choisi par l'utilisateur ou tiré de ses références. Tu ne proposes pas d'option « standard » ou « populaire », tu ne substitues pas tes préférences et rien de ce qui se trouve déjà dans le projet (les espaces réservés dans harness.config.json et la démo ne sont pas un style, mais un espace vide).
Règles de l'entretien
- Un bloc = un message, les blocs ne sont jamais fusionnés. Ne mets pas deux blocs dans un seul formulaire
AskUserQuestion: les gens cliquent sur la première option d'une série de questions. Les blocs 4 (services), 6 (palette), 7 (polices), 8 (style de montage) sont des conversations en plusieurs messages. - Pas de « (je recommande) » sur le goût. La mention n'est autorisée que pour un choix purement technique — méthode de transcription (bloc 3). Pour les couleurs, polices, style, services et questions sur la personne, elle n'existe pas ; décris les options de manière neutre, en précisant ce que chacune apporte.
- Les options viennent des réponses et des références de la personne. S'il n'y a ni réponses ni références, rassemble 2–3 options sensiblement différentes adaptées à son sujet et ton, et montre-les par des images ; c'est à lui/elle de choisir.
- Montre, ne décris pas : la palette, les polices et le style de montage par des images prêtes via
video/scripts/variants.py. - Sauter un bloc (« passe ») — seulement sur le mot de l'utilisateur. Dans ce cas, il reste un espace réservé neutre dans le profil, et dis-le clairement : « tu pourras configurer plus tard — dis "configure les sous-titres" ».
- Ne devine rien sur la personne. La marque, le nom, le sujet, l'audience et le ton — seulement à partir de ses réponses, pas de l'email du compte, du nom dans le système, du nom du dossier ou du lien vers le dépôt. Le nom du compte dans le lien du dépôt est celui de l'auteur du modèle, pas de l'utilisateur.
- La technique ne fait pas partie de l'entretien : les zones de sécurité, le montage sans queues coupées, le loudnorm en deux passes, la mécanique des punch-ins sur les collures — ce n'est pas du goût, c'est la façon dont le pipeline fonctionne (
CLAUDE.md, « Mécanique »). - Les clés ne passent jamais par le chat. L'utilisateur les saisit lui-même dans
video/.env; tu vérifies l'accès viadoctor.sh, sans rien imprimer. S'il envoie une clé dans le chat, ne l'utilise pas, conseille de la révoquer et d'en créer une nouvelle. - Tout ce qui s'installe via
brew/pipou qui pèse lourd — d'abord « quoi et combien », ensuite « oui ».
Étape 0. Salutation (un seul message)
Deux ou trois lignes : ceci est un montage de vidéos verticales « tête parlante » via Claude Code + Remotion ; le projet n'a pas son propre style — configurons tout maintenant en fonction de toi : parle de toi, envoie ~10 Reels que tu aimes, choisis les couleurs, les polices et le style de montage (je montrerai les options par images), connectons les services nécessaires. Passe immédiatement à l'étape 1.
Étape 1. Environnement
cd video && ( [ -d node_modules ] || npm install ) && bash scripts/doctor.sh
Affiche le résultat dans un court tableau. Pour chaque MISSING, propose une commande tirée de la sortie et, une fois l'accord obtenu, exécute-la :
- Skills Remotion (obligatoire) :
npx -y skills add remotion-dev/skills --skill '*' --agent claude-code -ydepuis la racine du projet. ffmpeg,node,python3,yt-dlp(pour les références) —brew install …(macOS) ; Linux — gestionnaire de paquets ; Windows — WSL.- whisper / rembg — quand ils seront nécessaires selon les réponses (étape 3).
Pas de brew — donne le lien https://brew.sh et attends (l'installation demande un mot de passe, c'est à l'utilisateur de la faire).
Étape 2. Entretien
Bloc 1 — qui es-tu
Marque / nom de la chaîne ; qui apparaît à l'écran ; de quoi parlent les vidéos ; plateformes et handles (Reels, TikTok, Shorts, Telegram…) ; audience ; ton ; langue des vidéos ; appel à l'action final.
Demande de manière ouverte — laisse-le/la répondre dans ses propres mots, même en un seul message. Si tu donnes des options (pour le ton ou l'appel à l'action), elles sont neutres et identiques pour n'importe qui, sans sujet ou niche pré-remplie.
Bloc 2 — références (~10 Reels)
Demande : « Envoie environ 10 liens vers des Reels que tu aimes en termes de montage — Instagram, TikTok ou Shorts. De préférence ceux auxquels tu aimerais ressembler. Grâce à eux, je comprendrai ton goût : tempo, sous-titres, graphiques, couleurs, polices. » Moins de 5 — demande encore : impossible de dégager un goût commun à partir de 3 vidéos. Explique que sans références, il faudra poser plus de questions dans les blocs 6–8.
Une fois les liens reçus — lance immédiatement l'analyse en arrière-plan et passe au bloc 3 :
cd video && python3 scripts/refs.py "URL1" "URL2" … > ../takes/refs.log 2>&1 # run_in_background
Le script télécharge dans takes/refs/ (ne va pas dans git) et mesure : durée, fréquence de changement d'image, changements dans le hook, volume, tempo de parole, première phrase, couleurs vives (palette.png) ; dessine NN-sheet.jpg (24 images par vidéo) et NN-hook.jpg (les 3 premières secondes). Si une partie des liens échoue avec une demande de connexion — options dans SERVICES.md → « Instagram » : relance avec COOKIES_FROM=chrome (uniquement avec un « oui » explicite) ou laisse-le/la télécharger lui/elle-même et placer les mp4 dans takes/refs/ (dans ce cas, passe les chemins au lieu des liens).
Bloc 3 — transcription de la parole
- whisper.cpp en local (je recommande sur Mac) : gratuit, hors ligne ;
brew install whisper-cpp+ modèle large-v3-turbo 1,6 Go. - ElevenLabs Scribe : payant (crédits), rien à installer, fonctionne sur n'importe quel système ; nécessite une clé (bloc 4).
Bloc 4 — services (un message par service)
Ne demande pas d'un seul coup « quoi connecter ». Parcours les services un par un — un message par service : ce qu'il apporte au montage (1–2 lignes avec un exemple), combien ça coûte, ce dont l'utilisateur a besoin et combien de temps ça prend. Question : « on connecte maintenant / plus tard / pas besoin ».
| service | ce qu'il apporte au montage | accès | temps |
|---|---|---|---|
| ElevenLabs | transcription Scribe ; accents sonores selon ton goût ; voix off | clé API | ~3 min |
| Higgsfield | courtes insertions vidéo (b-roll), quand tu parles de quelque chose qu'on peut montrer | connexion via navigateur | ~2 min + après redémarrage |
| 21st.dev | composants React prêts à l'emploi comme base pour de nouveaux graphiques | clé API | ~3 min |
| Buffer | brouillons de posts pour Reels / TikTok / Shorts | connexion via navigateur + canaux dans Buffer | ~5 min |
Ordre : ElevenLabs → Higgsfield → 21st.dev → Buffer. Si Scribe a été choisi au bloc 3, ElevenLabs est obligatoire, dis-le. « Plus tard » et « pas besoin » sont des réponses normales.
Pour chaque service où la réponse est « maintenant », suis la section correspondante de SERVICES.md : liens et étapes dans tes propres mots, attends le « prêt », configure ta partie et vérifie :
- Clés (ElevenLabs, 21st.dev) : si
video/.envn'existe pas —cp video/.env.example video/.env; l'utilisateur saisit la clé lui-même (open -e video/.env). Vérification —bash video/scripts/doctor.sh, sectionaccess. Refusé — probablement copié incomplètement ou sans les droits nécessaires ; qu'il en crée une nouvelle. - 21st.dev : après vérification de la clé, ajoute le serveur localement (la clé est lue depuis
.envdirectement dans le shell) :Sicd video && set -a && . ./.env && set +a && cd .. && claude mcp add --transport http 21st https://21st.dev/api/mcp --header "x-api-key: $TWENTYFIRST_API_KEY" --scope localclauden'est pas dans le PATH — donne cette commande à l'utilisateur pour qu'il l'exécute dans le terminal. - OAuth (Higgsfield, Buffer, facultatif ElevenLabs MCP) : ajoute les serveurs choisis dans le fichier racine
.mcp.json:Connexion via navigateur — après le redémarrage de Claude Code ({ "mcpServers": { "higgsfield": { "type": "http", "url": "https://mcp.higgsfield.ai/mcp" }, "buffer": { "type": "http", "url": "https://mcp.buffer.com/mcp" }, "elevenlabs": { "type": "http", "url": "https://api.elevenlabs.io/v1/mcp" } } }/mcp→ serveur → Authenticate) : dis-le maintenant et rappelle-le à l'étape 5. Pour Buffer, demande de connecter les canaux à l'avance dans Buffer lui-même (Instagram — compte professionnel).
Marque les services connectés dans integrations. Si tu es bloqué sur un service pendant 15 minutes ou plus — propose de le reporter : « on connectera plus tard — dis "connecte Buffer" ».
Bloc 5 — ce que tu aimes (selon les références)
Attends la fin de l'analyse (ps -axo command | grep "[r]efs.py"), lis takes/refs/refs.json, regarde chaque NN-hook.jpg et NN-sheet.jpg et palette.png. Pour chaque vidéo, note ce que les chiffres ne voient pas : sous-titres (position, taille, casse, graisse, couleur, surbrillance des mots, fond), graphiques (cartes et leur apparence, stickers, captures d'écran, b-roll, emojis), plan et punch-ins, proportion de visage nu, palette des graphiques, polices, ce qu'il y a dans le hook (texte-poster, question, action), fin.
Résume en un « profil de goût » : 5–7 tendances qui sont présentes dans au moins la moitié des vidéos, avec des chiffres (médianes de refs.py). Affiche-le en un seul message et demande : « c'est toi ? qu'est-ce que tu veux garder chez toi, et qu'est-ce que tu ne veux pas ? ». Ce qui est accepté deviendra des propositions dans les blocs 6–8 — tu le montreras par des images à côté d'autres options, sans l'appliquer en silence. Ce qui ne correspond pas aux réglages (stickers emoji, écran vert…) — note-le comme souhait dans le profil.
Bloc 6 — palette (2–3 messages)
6.1 Questions — en un seul message, en texte libre :
- As-tu des couleurs de marque — logo, site web, habillage de la chaîne, couvertures ? Envoie des codes hexadécimaux, un lien vers le site ou place le logo / une capture d'écran dans
takes/brand/. - Qu'est-ce qui doit ressortir en couleur dans les vidéos : chiffres, mots-clés, appels à l'action ?
- Quelle sensation veux-tu : stricte, chaleureuse, vive, calme ?
- Quelles couleurs ne veux-tu surtout pas ?
S'il envoie une image, extrais les couleurs principales :
python3 -c "
from PIL import Image; import sys
im = Image.open(sys.argv[1]).convert('RGB').resize((200, 200)).quantize(6)
pal = im.getpalette(); cnt = sorted(im.getcolors(), reverse=True)
print([('#%02X%02X%02X' % tuple(pal[i*3:i*3+3]), round(100*n/40000)) for n, i in cnt])
" takes/brand/logo.png
S'il envoie un lien vers un site — ouvre-le et trouve les couleurs principales (logo, boutons, variables CSS).
6.2 Candidats — 2–3 palettes selon quatre rôles : dark (plaques, écrans), light (texte), accent (surbrillance), pain (carte « pas comme ça », s'il en a besoin) :
- depuis les références —
recurring_coloursdansrefs.jsonetpalette.png; vérifie avec les storyboards que la couleur est un graphique ou du texte, pas un mur, un objet à l'écran ou de la peau ; - depuis les couleurs de marque, si elles existent ;
- selon les réponses 6.1 — sensation et quoi mettre en évidence.
Lisibilité (technique, pas goût) : le texte sur la plaque et par-dessus le footage doit être lisible — vérifie le contraste de chaque candidat (light sur dark ≥ 7:1, accent sur dark ≥ 3:1) ; si un candidat ne passe pas, dis-le et propose le plus proche qui passe :
python3 -c "
import sys
def L(h):
c=[int(h[i:i+2],16)/255 for i in (1,3,5)]
c=[x/12.92 if x<=0.03928 else ((x+0.055)/1.055)**2.4 for x in c]
return 0.2126*c[0]+0.7152*c[1]+0.0722*c[2]
a,b=sorted([L(sys.argv[1]),L(sys.argv[2])]); print(round((b+0.05)/(a+0.05),1))
" '#FFFFFF' '#141414'
6.3 Montre par images :
cd video && python3 scripts/variants.py out/palette-options.png 70,368 \
'{"label":"A","colors":{"dark":"#…","light":"#…","accent":"#…","pain":"#…"}}' \
'{"label":"B","colors":{…}}' '{"label":"C","colors":{…}}'
Affiche la feuille (SendUserFile), légende : « A — d'après tes références, B — d'après le logo, C — d'après la sensation ». Modifications (« A, mais l'accent plus foncé ») — nouveau passage. Ce qui est choisi — dans colors.
Bloc 7 — polices (2–3 messages)
Deux polices : texte (sous-titres et cartes, graisses 500 / 600 / 700) et poster (titre au début de la vidéo, s'il y en a un). Les deux doivent prendre en charge l'alphabet de la langue des vidéos.
7.1 Questions — en un seul message : as-tu des polices de marque (noms ou fichiers dans takes/brand/) ; quel caractère — strict, amical, technologique, éditorial ; sous-titres légers ou denses.
S'il y a eu un bloc 2 — regarde les sous-titres et les titres sur les storyboards et dis ce que tu vois : type (grotesque géométrique, néo-grotesque, étroit, arrondi, avec empattements), graisse, casse. Ne devine pas le nom exact d'après l'image — cherche une police libre similaire.
7.2 Candidats — 2–3 paires « texte + poster » issues de @fontsource avec l'alphabet nécessaire, de caractères différents, adaptés à ses réponses et à ses références. Pour le russe, vérifie le cyrillique ; Bebas Neue — seulement latin. Police de marque achetée — dans video/src/fonts/ + @font-face avec font-display: block manuellement ; rappelle la licence si le dépôt est public.
7.3 Montre par images :
cd video && npm i @fontsource/<a> @fontsource/<b> # candidats
ls node_modules/@fontsource/<a>/ | grep -c cyrillic # pour ru > 0
ls node_modules/@fontsource/<a>/ | grep -E '^[0-9]+\.css$' # graisses disponibles
grep -m1 font-family node_modules/@fontsource/<a>/400.css # nom exact de la famille
Ajoute dans video/src/index.css les imports des graisses des candidats (@import "@fontsource/<a>/600.css"; …), puis :
python3 scripts/variants.py out/font-options.png 70,368 \
'{"label":"A","fonts":{"text":"…","poster":"…","posterWeight":700}}' '{"label":"B","fonts":{…}}'
Affiche, légende. Après le choix, ne laisse dans index.css que les imports choisis et supprime les paquets inutiles (npm un …).
Bloc 8 — style de montage (un message par sujet)
Quatre sujets, chacun dans un message séparé : question, ce qui est visible dans les références (« dans 7 vidéos sur 10, les sous-titres sont centrés, grands »), puis 2–3 options par images via variants.py (clés style.*, images 70,270,368). Sans « je recommande ».
8.1 Sous-titres (style.captions) :
- position :
cycle— les phrases se déplacent dans le cadre (haut-gauche → haut-droite → bas) ;rail— toujours en bas ;center— centré ; - taille
size: [mot normal, mot surligné]en px (≈ 48 petit, 60 moyen, 76 grand) ; - graisse
weight(500–800) ; cassecase:lower/asis/upper; - surbrillance
highlight:color(mots-clés en couleur d'accent) /size(plus grand) /both/none; - fond
box:true— plaque sous la ligne,false— ombre.
8.2 Graphiques :
- cartes
style.cards:glass(verre semi-transparent) /solid(plaque pleine) /none; fréquence — en mots dansediting-taste.md§3 ; - stickers-pictogrammes dans les pauses
style.stickers:true/false; - poster-titre derrière la tête au début
style.poster:enabled, cassecase(upper/asis), petit sous-titrekicker. Activé — besoin de rembg (~30 min en arrière-plan par vidéo, modèle ~1 Go une fois) ; - b-roll (si Higgsfield est connecté) : nécessaire ou non, combien — en mots dans
brand-kit.md§5.
8.3 Mouvement et image :
- tempo
style.tempo:punchy(coupes rapides, beaucoup de punch-ins) /calm(poses, plans larges) ; - punch-ins
style.punchIns:frequent(toutes les 4–7 secondes si le sujet change) /sparse; - zoom
style.zoom:subtle(zoom lent 1.0→1.05 en 3 sec) /pronounced(1.0→1.15) /none; - grade
style.grading:warm(chaud) /cool(froid) /neutral(neutre) — par mots et exemples ; correction des couleurs technique (courbes, balances) — dans le fichierediting-taste.md§1, pas ici.
8.4 Son :
- niveaux
style.audio.levels:voice,musicen pourcentage (moyenne : parole 12 dB, musique -18 dB) ; - audio accent
style.audio.accents:true(si ElevenLabs connecté) — effets sonores aux moments clés (ding, swipe, pop) ; - loudness
style.audio.loudnorm:true(normalisation à -14 LUFS, deux passes). Si l'utilisateur veut plus fort — dans le profil, mais note qu'il dépassera la norme ; - suppression du bruit
style.audio.noiseReduction:light/medium/heavy/none.
Bloc 9 — film d'échantillons (un message)
cd video && python3 scripts/variants.py out/style-preview.png 70,368 \
'{"label":"A","style":{"captions":{…},"cards":"…","tempo":"…",…}}' \
'{"label":"B","style":{…}}' \
'{"label":"C","style":{…}}'
Affiche la feuille d'images de la vidéo d'échantillons (chiffre de l'étape 9). Pas de sélection — les touches des blocs 8.1–8.4 constituent le choix final.
Étape 3. Sauvegarde du profil
cd video && python3 scripts/save_profile.py
Écrit dans les fichiers racine :
harness.config.json— paramètres techniques (services, couleurs, polices, style) — utilise le JSON directement depuis les blocs 2–8 ;brand-kit.md— marque, audience, ton, mots-clés ;editing-taste.md— la partie technique du goût (grading, ratio de punch-ins, mécanique des sous-titres) ;exemplars.md— liens vers les références et ce qui a été appris d'elles.
Les fichiers ne sont pas en git, ils sont créés dans le dossier racine. Tout est prêt. Dis : « Le projet est configuré. Tu peux commencer la première vidéo — écris "fais la première vidéo" ». Et c'est tout.
Spécifique au système de fichiers et au code
- Tous les chemins depuis la racine du projet. Les appels aux scripts utilisent
cd video && …. doctor.shest un script bash dansvideo/scripts/qui vérifie Node, Python, le son, l'accès aux clés (sans imprimer les clés).variants.pygénère une grille d'images (70×368 px par cellule) avec des légendes. Appel :python3 scripts/variants.py <chemin_sortie> <dimensions_cellule> <json1> [json2 …].- Le profil après l'entretien se trouve dans
harness.config.json— un format technique (services, palettes, polices, style). Ne le modifie pas après la sauvegarde sauf demande explicite. - Un fichier
/mcpsert à redémarrer le serveur Claude Code (après ajout de serveurs OAuth). yt-dlptélécharge les références. Cookies pour Instagram — viaSERVICES.md.rembg— modèle pour l'incrustation du portrait (fond).- Les clés dans
.envsont strictement locales, ne les imprime pas et ne les utilise pas dans le chat. SERVICES.md— instructions pour connecter chaque service. Ne contient pas de clés.CLAUDE.md— mécanique du pipeline, règles de montage.
Comportement dans les cas particuliers
- L'utilisateur interrompt l'entretien au milieu : ne devine pas la suite. Demande : « On continue la configuration ? On en était à … » (cite le bloc en cours).
- L'utilisateur a déjà un fichier de profil (configured: true dans harness.config.json) : ne relance pas l'entretien. Demande : « Le projet est déjà configuré. Tu veux changer quelque chose ? Dis "reconfigure" pour tout refaire, ou "change la palette" pour un bloc spécifique. »
- L'utilisateur envoie une clé dans le chat : « Ne partage jamais la clé dans le chat. Révoke-la et crée-en une nouvelle, puis inscris-la dans le fichier .env. »
- L'utilisateur refuse les références : passe les blocs 5, 6, 7, 8 en mode questions (sans carry-over des références). Propose des options génériques.
- Moins de 5 références : idem, sauf si l'utilisateur insiste pour continuer avec ce qu'il a.
- Le script refs.py échoue pour tous les liens : « Les liens ne sont pas téléchargeables. Tu peux télécharger les vidéos toi-même et les mettre dans takes/refs/, ou on continue sans analyse et on choisira les options manuellement. »
- L'utilisateur change d'avis en cours de route : on peut revenir en arrière. « Dis "retour au bloc palette" et on y retourne. »
- L'utilisateur a déjà un .env avec des clés : vérifie via doctor.sh. Si l'accès est bon, passe le bloc 4 en mode confirmation (tout est bon).
- L'utilisateur veut un style « comme ce reel spécifique » : exécute refs.py sur celui-ci (même si ce n'est pas le bloc 2). Utilise-le comme référence unique.
- L'utilisateur dit « c'est trop long » : propose un mode rapide — uniquement les blocs 1, 4, 6, 8 (sans analyse des références ni comparaisons). « On peut raccourcir — juste la palette, les polices et le style. Les détails plus tard. »
- Système d'exploitation non supporté : demande quel OS l'utilisateur utilise. Sur Windows sans WSL, propose WSL. Sur Linux, vérifie la disponibilité de ffmpeg, Python, Node.
- Conflit de dépendances : dis exactement quelle dépendance et quel conflit. « Le package X nécessite la version Y, mais Z est installé. Peut-on mettre à jour ou supprimer Z ? »
- L'utilisateur fournit un lien de référence qui nécessite une connexion (Instagram) : propose d'utiliser les cookies du navigateur (COOKIES_FROM=chrome) ou de télécharger manuellement.
- Après la configuration, l'utilisateur veut ajouter un service : « Dis "connecte [nom du service]" et je t'aiderai. »
- Le script save_profile.py échoue : vérifie les permissions d'écriture dans le dossier racine. « Tu n'as pas les droits d'écriture. Corrige ça ou change de dossier. »