Générez une vidéo de démonstration du flux décrit par l'utilisateur. Le résultat est placé dans un nouveau dossier demo/vN/.
La seule règle qui compte : chaque écran est une transcription de l'interface réelle, pas une impression de celle-ci. Une démo qui invente la mise en page, le texte ou les composants est pire qu'aucune démo — elle apprend aux spectateurs un produit qui n'existe pas. Lisez le code source de chaque écran avant d'écrire un seul élément HTML.
Entrées
/create-product-demo-video <ce qui doit se passer> — une description du flux. Si elle est vague (« montrer le
produit »), choisissez le flux complet le plus étroit qui se termine par une valeur visible, dites lequel vous avez
choisi en une ligne, et construisez-le. Ne bloquez pas sur des questions.
Étapes
-
Mapper le flux sur les routes. Transformez l'invite en une liste ordonnée de routes réelles que l'utilisateur emprunterait. Trouvez d'abord le routeur — un répertoire
routes/, une arborescenceapp/, un bloc<Routes>, un manifeste de routes — et listez uniquement les chemins qui existent. Si le flux nécessite une entité qui doit être créée avant qu'un écran ultérieur puisse exister (un projet avant un rapport basé sur le projet), incluez cet écran ou choisissez un périmètre qui n'en a pas besoin — ne sautez pas silencieusement une étape obligatoire. -
Lire le code source de chaque écran. Pour chaque route : le fichier de route, les composants qu'elle affiche, les composants de mise en page partagés de l'application (shell, en-tête de page, état vide), et ses primitives de système de conception (
components/ui/ou leur emplacement). Lisez également tout ce qui génère des chaînes que la démo montre — assistants d'aperçu, noms dérivés, services de rendu/modèle backend. Copiez les chaînes textuellement ; ne paraphrasez pas le contenu du produit. -
Préparer la structure.
mkdir -p demo/vN(prochain N non utilisé — ne jamais écraser un vN existant), puis copiezassets/skeleton.html→demo/vN/index.htmletassets/record.mjs→demo/vN/record.mjs.assets/se trouve à côté de ceSKILL.md, où que la compétence soit installée — un dossier de cache de plugin,~/.claude/skills/, ou le.claude/skills/d'un projet. Résolvez-le à partir du répertoire de la compétence elle-même, jamais du dépôt en cours de démonstration. Le squelette contient un shell d'espace réservé, une échelle de jetons et le moteur de lecture. Pour une démo notée, copiez également la piste choisie depuisassets/music/→demo/vN/music.mp3— voir Musique. La copier (plutôt que de référencer le dossier de la compétence) est ce qui rendvN/ré-enregistrable plus tard, pour la même raison querecord.mjsest copié par version. -
Adapter le squelette à ce produit. Tout ce qui est marqué
REPLACE:est un espace réservé qui doit être remplacé avant que la moindre scène ne soit écrite, car chaque écran en hérite :Dans index.htmlRemplacer par PRODUCTLe nom de l'application, l'hôte que sa barre d'adresse affiche, et son vrai logo svg NAVLa barre latérale transcrite de la vraie navigation — mêmes sections, même ordre, mêmes libellés TOPBARLa vraie barre supérieure ; supprimez les contrôles que l'application n'a pas :roottokensLe bloc :rootde la feuille de style de l'application, pour que couleur/rayon/typographie correspondentICONSLes données de chemin du jeu d'icônes que l'application utilise réellement Supprimez les blocs CSS optionnels (écran tiers, panneaux de diffusion) que le flux n'utilise pas. -
Écrire les scènes. Une
<section class="scene" data-scene="N">par écran, dans l'ordre. Réutilisez les classes CSS du squelette (.pagehead,.card,.btn,.seg,.opt,.chip,.scopeid,.statusbadge,.empty,.input,.pillbar,.toast) — elles sont conçues pour ressembler à la sortie d'un système de type Tailwind/shadcn, alors vérifiez chacune par rapport aux classes réelles du composant et ajustez plutôt que de supposer. Ajoutez du nouveau CSS uniquement pour un composant que le squelette ne possède pas, et déduisez-le des classes réelles de ce composant. -
Écrire
play(). Carte de titre → écrans → conclusion. Utilisez des légendes pour nommer chaque étape, et définissezCAPTIONSen haut du script — le style, etsteps= combien d'appelssay()l'exécution effectue. Les interactions passent par les assistants de pointeur pour que le spectateur puisse suivre ce qui est cliqué. -
Enregistrer.
node demo/vN/record.mjs→demo/vN/out/product-demo.mp4. Ajoutez--gifpour un gif de 900px. Un fichierdemo/vN/music.*est détecté automatiquement ;--music <chemin>en pointe un ailleurs,--music-db <n>ajuste le niveau,--no-musicforce le silence. -
Vérifier en regardant. Extrayez des images et lisez les images — ce n'est pas facultatif, c'est ainsi que les bugs de mise en page sont détectés :
for t in 5 12 20 28 36 44; do ffmpeg -y -loglevel error -ss $t \ -i demo/vN/out/product-demo.mp4 -frames:v 1 /tmp/f$t.png; doneVérifiez : pas d'icônes surdimensionnées, rien de coupé au pli, le pointeur atterrit sur l'élément qu'il prétend cliquer, le texte n'est pas réduit à une seule ligne. Corrigez et ré-enregistrez jusqu'à ce que ce soit propre.
Les images ne peuvent pas vous montrer l'audio. Sur une démo notée, vérifiez également le flux et les fondus —
volumedetectenregistre au niveau info, donc-v erroravalerait sa sortie :ffprobe -v error -select_streams a:0 -show_entries stream=codec_name,duration \ -of default=nw=1 demo/vN/out/product-demo.mp4 for w in "-ss 0 -t 0.25" "-ss 12 -t 0.5" "-sseof -0.25"; do \ ffmpeg -hide_banner -nostats $w -i demo/vN/out/product-demo.mp4 \ -af volumedetect -f null - 2>&1 | grep mean_volume; doneAttendez-vous à un flux
aacà moins de ~0,05s de la durée vidéo,max_volumeen dessous de 0 dB, et la moyenne de début et de fin bien inférieure à celle du milieu — c'est le fondu qui prouve que le script a fonctionné. -
Écrire
demo/vN/README.md— tableau des scènes avec les routes, le mappage des fichiers source, la durée, le styleCAPTIONSet la piste musicale avec lesquels la version a été enregistrée, et ce que le flux ignore délibérément. Mettez à jourdemo/README.mdpour lister la nouvelle version.
Rapportez le chemin, la durée et la taille, puis ouvrez le mp4 pour que l'utilisateur puisse le regarder — open sur macOS,
xdg-open sur Linux, start sur Windows.
API du moteur
Disponible à l'intérieur de play() :
| Appel | Effet |
|---|---|
scene(n) | Fondu croisé vers la scène n, met à jour la barre d'adresse à partir de URLS |
tap(sel, ms) | Déplacer le pointeur vers l'élément et cliquer (ondulation + pression) |
moveTo(sel, ms) / click(sel) | Les deux moitiés, lorsque vous avez besoin de changements d'état entre elles |
hideCursor() / place(x, y, 0) | Réinitialiser le pointeur lors de l'entrée dans une scène |
say(text, opts?) / hush() | Légende entrée/sortie. { at: sel } ancre une légende coach ; { step: n } force l'index |
type(el, text, ms) | Saisie caractère par caractère dans un <span> |
wait(ms) | Pause |
reveal(el) | Appelé automatiquement par moveTo — défile en douceur .main pour que les cibles hors de la zone visible soient visibles |
Définissez window.__demoDone = true à la fin (le squelette le fait déjà) — l'enregistreur attend cette variable.
Conception des légendes
const CAPTIONS = { style: 'pill', steps: 6 } se trouve avec URLS en haut du moteur. Les quatre
styles sont inclus dans le squelette ; say() est le même appel quel que soit le style choisi. Choisissez par vidéo :
style | Description | À choisir quand |
|---|---|---|
pill (par défaut) | Capsule d'encre, centrée en bas | Tout ce qui est court et orienté marketing. Moins d'occlusion, ~10 mots par légende |
lower-third | Bloc ancré à gauche avec index d'étape + barre de progression | Flux plus longs où le spectateur doit ressentir la séquence ; le plus lisible dans un gif |
rail | Bande de 68px sous la fenêtre, points de chapitre | Documents et clips d'assistance où rien ne doit être masqué. Coûte de la hauteur d'application — voir ci-dessous |
coach | Bulle ancrée à l'élément en jeu, le reste atténué | Tutoriels pas à pas. Chaque légende a besoin de { at: sel } ; celles sans reviennent au style pill |
steps pilote l'index, la barre de progression et les points du rail — comptez les appels say() et définissez-le,
ou l'exécution se terminera sur 05 / 06. Vous ne savez pas quel style choisir ? Ouvrez index.html dans un navigateur et changez
CAPTIONS.style — la page se rejoue sur R, donc les quatre peuvent être comparés sans enregistrement.
Musique
Optionnelle, et désactivée sauf si une piste est présente. Le fond sonore est mixé au moment de l'encodage — Playwright ne capture aucun audio, donc rien ne touche à la page de démo ni au moteur.
node demo/vN/record.mjs # utilise demo/vN/music.* si présent, silencieux sinon
node demo/vN/record.mjs --music ~/beds/x.mp3 # le chemin explicite l'emporte sur le fichier voisin
node demo/vN/record.mjs --music-db -4 # fond sonore plus silencieux
node demo/vN/record.mjs --no-music # silencieux même avec une piste voisine
- Les pistes fournies se trouvent dans
assets/music/, une ligne par fichier dans sonLICENSES.md. Aucune piste n'est livrée sans une ligne CC0/CC-BY vérifiable — un mp3 sans licence est un problème pour tous ceux qui installent ceci, pas seulement le vôtre. Incertain ? Gardez-la hors du dépôt et passez--music <chemin>. - Le niveau est normalisé, pas réglé manuellement. Chaque piste est ramenée à −18 LUFS avec un plafond de crête réelle de −1,5 dB,
afin que les fonds sonores échangés entre versions se correspondent sans réglage manuel.
--music-dbdécale cette cible ; il n'ajoute pas de gain par-dessus. - Les fondus sont automatiques — 1,5s à l'entrée, 2,5s à la sortie, la sortie calée sur la durée réelle de la vidéo.
- Choisissez une piste plus longue que la vidéo. Tout ce qui est plus court sera bouclé et la jointure sera audible ; l'enregistreur émet un avertissement lorsqu'il doit le faire. 60s+ couvre une démo normale de 40 à 60s.
- Pas de voix, pas de chutes brusques. Le spectateur lit les légendes et le texte de l'interface en même temps.
- L'audio atterrit uniquement dans le mp4. Le webm est la capture brute silencieuse, et un gif n'a aucune piste audio
du tout — un changement uniquement musical est invisible dans la sortie
--gif.
Conventions
- La scène est un navigateur simulé fixe de 1280×800 ; 44px de cela sont le chrome du navigateur, laissant 1280×756 pour l'application. Le squelette fournit un écran de 48