VirtualPirate/create-product-demo-video-skill

Compétence Claude Code : enregistre une vidéo de démonstration produit d'un flux utilisateur réel dans votre propre application web — transcrite à partir de l'interface réelle, enregistrée en mp4/gif avec Playwright et ffmpeg.

Qu'est-ce que create-product-demo-video-skill ?

Cette compétence permet de créer automatiquement une vidéo de démonstration d'un flux utilisateur dans une application web, en utilisant Playwright et ffmpeg. L'utilisateur fournit une description du flux (ex. « montrer la création d'un projet »), et la compétence : (1) cartographie le flux sur les routes existantes de l'application, (2) lit le code source de chaque écran pour copier le texte et la mise en page réels, (3) génère un squelette HTML/CSS personnalisé avec des légendes et une piste musicale optionnelle, (4) enregistre la vidéo en mp4 (ou gif). Le principe fondamental est que chaque écran doit être une transcription exacte de l'interface réelle — pas d'invention de contenu, de mise en page ou de composants. La vidéo finale inclut des légendes animées, un curseur simulé et des transitions entre les scènes. La compétence prend en charge la vérification automatique par extraction d'images et analyse audio, et produit un répertoire `demo/vN/` autonome et ré-enregistrable.

Compatible avec✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/VirtualPirate/create-product-demo-video-skill/tree/main/skills/create-product-demo-video

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

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

  1. 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 arborescence app/, 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.

  2. 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.

  3. Préparer la structure. mkdir -p demo/vN (prochain N non utilisé — ne jamais écraser un vN existant), puis copiez assets/skeleton.html → demo/vN/index.html et assets/record.mjs → demo/vN/record.mjs. assets/ se trouve à côté de ce SKILL.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 depuis assets/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 rend vN/ ré-enregistrable plus tard, pour la même raison que record.mjs est copié par version.

  4. 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
    :root tokensLe bloc :root de la feuille de style de l'application, pour que couleur/rayon/typographie correspondent
    ICONSLes 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.
  5. É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.

  6. Écrire play(). Carte de titre → écrans → conclusion. Utilisez des légendes pour nommer chaque étape, et définissez CAPTIONS en haut du script — le style, et steps = combien d'appels say() l'exécution effectue. Les interactions passent par les assistants de pointeur pour que le spectateur puisse suivre ce qui est cliqué.

  7. Enregistrer. node demo/vN/record.mjs → demo/vN/out/product-demo.mp4. Ajoutez --gif pour un gif de 900px. Un fichier demo/vN/music.* est détecté automatiquement ; --music <chemin> en pointe un ailleurs, --music-db <n> ajuste le niveau, --no-music force le silence.

  8. 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; done
    

    Vé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 — volumedetect enregistre au niveau info, donc -v error avalerait 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; done
    

    Attendez-vous à un flux aac à moins de ~0,05s de la durée vidéo, max_volume en 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é.

  9. Écrire demo/vN/README.md — tableau des scènes avec les routes, le mappage des fichiers source, la durée, le style CAPTIONS et la piste musicale avec lesquels la version a été enregistrée, et ce que le flux ignore délibérément. Mettez à jour demo/README.md pour 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() :

AppelEffet
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 :

styleDescriptionÀ choisir quand
pill (par défaut)Capsule d'encre, centrée en basTout ce qui est court et orienté marketing. Moins d'occlusion, ~10 mots par légende
lower-thirdBloc ancré à gauche avec index d'étape + barre de progressionFlux plus longs où le spectateur doit ressentir la séquence ; le plus lisible dans un gif
railBande de 68px sous la fenêtre, points de chapitreDocuments et clips d'assistance où rien ne doit être masqué. Coûte de la hauteur d'application — voir ci-dessous
coachBulle 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 son LICENSES.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-db dé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

Skills associés