Communitygithub.com

learnermaker/project-demo-video-skill

Produisez une vidéo de démonstration 1080p narrée, sous-titrée (3 minutes ou moins) pour tout projet logiciel, participation à un hackathon ou produit, sous forme de code, avec Playwright et ffmpeg-static.

Qu'est-ce que project-demo-video-skill ?

Cette compétence permet de créer des vidéos de démonstration professionnelles pour des projets logiciels en les construisant entièrement sous forme de code. Elle enregistre l'application réelle en cours d'exécution, rejoue les sorties réelles du terminal, explore le code source réel, dessine des diagrammes, ajoute une voix de synthèse (voix Windows intégrée par défaut, ElevenLabs en option) et grave les sous-titres dans la vidéo. Le résultat est une vidéo 1920×1080, 30 ips, en H.264 + AAC, avec les sous-titres incrustés, un fichier SRT séparé, une vignette et tous les fichiers de sous-titres. L'ensemble du pipeline est reproductible et peut être re-rendu en quelques minutes après toute modification du projet. La compétence est conçue pour respecter les règles des hackathons (limite de durée inférieure à 3 minutes, pas de déploiement, pas de secrets affichés), et elle est compatible avec les agents Claude Code, Cursor, Codex, GitHub Copilot et d'autres systèmes similaires qui peuvent exécuter Node.js, Playwright et ffmpeg-static.

Compatible avec✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/learnermaker/project-demo-video-skill/tree/HEAD/skills/project-demo-video

Demander à votre IA préférée

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

Documentation

project-demo-video

Construisez la vidéo de démonstration sous forme de code afin de pouvoir la re-rendre en quelques minutes après toute modification. Tout ce qui est à l'écran est réel : l'application en cours d'exécution, la sortie réelle des commandes, les fichiers sources réels. Rien n'est une maquette.

Cette compétence est rédigée pour qu'un agent de codage moins performant puisse la suivre étape par étape. Suivez les phases dans l'ordre. Chaque phase a une ligne Fait quand : ne passez pas à la suivante tant qu'elle n'est pas vraie. Copiez les fichiers de templates/ au lieu de les réécrire.

Installation : copiez l'intégralité de ce dossier (SKILL.md et templates/) vers le dossier des compétences de l'agent, par exemple ~/.claude/skills/project-demo-video/, ou pointez simplement l'agent vers SKILL.md.

Ce que vous produisez

SortieRemarques
<nom>-voiced.mp41920×1080, 30 ips, H.264 + AAC, sous-titres incrustés, avec voix
<nom>-captions-only.mp4même image, piste audio silencieuse (l'utilisateur peut choisir celle-ci ou enregistrer sa propre voix)
<nom>.srtsous-titres sous forme de fichier, même texte que la narration
thumbnail.png1280×720
narration.md, shotlist.mdscript avec horodatages réels ; chaque scène avec sa source
frames/les images de contrôle qualité que vous avez réellement examinées
repo/fichiers du projet modifiés ou nouveaux, reflétés à leurs chemins dans le dépôt
COPY_LIST.md, README-snippet.md, REPORT.mdquoi copier où, une section README "Voir le fonctionnement", ce qui est fait et ce qui est risqué

0. Règles à ne pas enfreindre

  1. Source en lecture seule. N'écrivez jamais, ne validez jamais et ne poussez jamais depuis les vrais dépôts de l'utilisateur. Travaillez dans une copie (robocopy/cp, en excluant node_modules, .git, les artefacts de build), puis exécutez npm ci à cet endroit. Conservez les modifications qui méritent d'être conservées dans le dossier de sortie, en reflétant les chemins du dépôt, plus COPY_LIST.md. Un autre outil ou une autre personne effectue le travail git.
  2. Soyez honnête à l'écran. Tout ce qui est simulé (un appareil, un connecteur, un paiement, un modèle) est étiqueté comme simulé dans la vidéo. Ne sous-entendez jamais de matériel, de déploiements ou d'utilisateurs qui n'existent pas. Copiez le propre tableau "réel vs simulé" du projet ; si le README est erroné, dites-le dans le rapport et ne répétez pas l'affirmation.
  3. Pas de secrets à l'écran ou dans les fichiers livrés : jetons, clés API, contenus de .env, clés privées, e-mails réels. Les jetons de développement que le projet documente (par exemple Bearer dev-alice) sont acceptables. Lorsque vous montrez du code, choisissez des plages de lignes qui excluent les secrets.
  4. Aucune mention de l'outil d'IA qui a écrit le code, ou de son fournisseur, dans les images, la narration, les sous-titres ou les documents livrés, sauf indication contraire de l'utilisateur. Un identifiant de modèle d'exécution qui fait partie de la configuration du produit peut apparaître comme nom de modèle. Vérifiez avec grep -ri avant de terminer.
  5. Respectez les règles du concours. Lisez la limite de durée (généralement "moins de 3:00" ; visez 2:50) et la règle de technologie requise. La vidéo doit montrer la technologie requise en fonctionnement réel, pas seulement la mentionner.
  6. Niveau gratuit, pas de déploiements, pas d'achats. Ne déployez pas, ne créez pas de ressources cloud et ne dépensez pas d'argent. Si une étape nécessite un identifiant ou un enregistrement de l'utilisateur, demandez-le une fois, clairement, et continuez avec tout le reste.
  7. Demandez à l'utilisateur uniquement les identifiants, ses propres enregistrements ou un choix qui lui appartient vraiment (par exemple, quelle voix). Décidez de tout le reste vous-même et dites ce que vous avez décidé.

1. Prérequis (vérifiez, ne présumez pas)

node --version          # 22+ (24 recommandé ; les fichiers .mjs doivent être en JavaScript pur, pas de casts TypeScript)
  • Dans la copie du projet : @playwright/test (avec Chromium installé) et ffmpeg-static doivent exister. Vérifiez : node -e "import('@playwright/test').then(async m=>{const b=await m.chromium.launch();console.log(b.version());await b.close()})" et node -e "import('ffmpeg-static').then(m=>console.log(m.default))". Si manquants et que le projet interdit les nouvelles dépendances, placez-les dans un dossier d'outils séparé et pointez vers celui-ci.
  • Parole : Windows PowerShell avec System.Speech (intégré). Sur macOS, utilisez say, sur Linux espeak-ng ; vous devez alors adapter templates/lib/tts.mjs (seuls synthAll et tts.ps1 sont spécifiques au système d'exploitation).
  • Aucun ffprobe n'est livré avec ffmpeg-static : mesurez les durées à partir des en-têtes WAV (wavSeconds dans templates/lib/tts.mjs) et du chronométrage de l'enregistreur.
  • Remarques sur le shell Windows : privilégiez les outils Write et Edit pour tout fichier contenant des barres obliques inverses, des expressions régulières ou $. La réécriture en ligne python -c/heredoc du JS corrompt silencieusement les échappements. Le sleep au premier plan est bloqué dans certains agents : attendez avec until grep -q "done" log; do sleep 10; done.

2. Phases

Phase A : Exigences et carte de preuve

Lisez la page des règles, le README, les propres documents du projet et toutes les notes sur le scénario. Écrivez un tableau dans vos notes :

Le jury doit être convaincu queOù la vidéo le prouveScène
la technologie requise est appelée dans le codeappel réel visible : journal des requêtes, terminal, extrait de code...
l'expérience fonctionneapplication s'exécutant dans un navigateur...
ce qui est réel vs simuléle propre tableau du projet...

Fait quand chaque ligne a une scène.

Phase B : Espace de travail

  1. Copiez le dépôt dans un dossier temporaire, puis installez : npm ci.
  2. Copiez templates/ dans la copie sous video/ (conservez la structure : video/lib, video/pages, video/scenes, video/final.mjs, video/narration.mjs, ...). Ajoutez aux scripts package.json : "video:final": "node video/final.mjs". N'ajoutez aucune dépendance.
  3. Ajoutez video/out/ à .gitignore dans la copie.

Phase C : Test à blanc de la vraie application et chasse aux bugs (faites ceci avant d'enregistrer quoi que ce soit)

Démarrez l'application comme le ferait un jury (npm run demo ou la commande du README) sur son port par défaut documenté, de sorte que chaque commande affichée à l'écran soit littérale. Pilotez-la avec un petit script Playwright, prenez des captures d'écran à 1920×1080 après chaque étape de l'histoire et examinez-les. Vérifiez :

  • connexion, panneaux vides, bannières d'erreur rouges, erreurs de console ;
  • chaque état dont l'histoire a besoin se rend réellement (la première exécution du projet de référence montrait un échec de connexion, une boîte de réception vide et une vue clé manquante, tous cachés par une ancienne ébauche de vidéo) ;
  • texte dupliqué ou coupé.

Corrigez les vrais bugs dans la copie, de manière minimale, exécutez les propres vérifications du projet (npm run verify, tests, typecheck) et enregistrez chaque correction pour COPY_LIST.md. Si l'application n'a aucun moyen d'afficher le trafic filaire, ajoutez un petit crochet optionnel (un journal des requêtes) plutôt que d'en simuler un. Fait quand toute l'histoire s'exécute proprement deux fois de suite et que les vérifications du projet réussissent.

Phase D : Storyboard et narration

  1. Choisissez les scènes. Histoire de référence (environ 2:50) :
ScèneDuréeMontre
accroche12 sun changement se répercute sur plusieurs engagements (carte animée)
démarrage6 sla commande unique qui démarre tout, sortie réelle
sim (l'application)60 s8-10 temps ; journal des requêtes ouvert sur 2 temps
terminal(e) de preuve17-30 sclient officiel ou CLI contre le même serveur ; vérifications d'authentification
visite du code16 s3-4 extraits réels qui prouvent la technologie requise
architecture, pile cloud, réel vs simulé30 sdiagramme, source de la pile, tableau d'honnêteté, carte open-source
fermeture12 sslogan, liens du dépôt, crédits de construction, pied de page "X est simulé"
  1. Écrivez video/narration.mjs : scenes = [{ id, title, segs: [{ id, text }] }]. Chaque seg est une ligne parlée et un sous-titre (text est affiché textuellement). Règles : environ 2,4 mots par seconde ; nombre total de mots parlés 330-380 ; une idée par ligne ; pas plus d'environ 12 mots sur une carte à l'écran ; casse de phrase ; pas de battage publicitaire.
  2. Ajoutez des indices de prononciation dans la table say pour le moteur de synthèse vocale uniquement (acronymes épelés, "Alexa+" comme "Alexa plus") ; ne modifiez jamais le texte du sous-titre. Fait quand la narration se lit comme une histoire qu'un étranger comprend et que chaque ligne de la carte de preuve est parlée ou montrée.

Phase E : Adaptation des modèles

Modifiez uniquement ce qui est spécifique au projet :

FichierModification
video/narration.mjsvos scènes et lignes
video/scenes/sim.mjsles étapes de votre application : quoi taper ou cliquer, sélecteurs, les zooms de la caméra (lens(...), zoomWire)
video/scenes/static.mjscommandes du terminal (CMD), codeBlocks (fichier + regex de la première ligne + nombre de lignes + regex de surbrillance), appels de page d'accroche/fermeture
video/proofs.mjs, video/proof-auth.mjsles vraies commandes qui prouvent vos affirmations ; elles n'impriment que les codes d'état et les noms d'erreur
video/pages/*.htmltexte, couleurs, tuiles, boîtes de diagramme, lignes de tableau, liens
video/lib/overlay.mjssélecteurs SIM_CSS pour la mise en page de votre application (voir Règles de mise en page), la source de données du ticker
video/final.mjsla constante LIMIT et l'ordre des scènes (l'ordre vient de narration.mjs)
video/thumbnail.mjs, video/docs.mjstitres et la table SHOT

Ne modifiez pas lib/recorder.mjs, lib/director.mjs, lib/tts.* sauf si quelque chose est cassé.

Phase F : Capture de la sortie de preuve réelle

node video/proofs.mjs démarre un nouveau serveur, exécute les vraies commandes (inspecteur officiel ou CLI client, vérifications d'authentification, sortie d'installation/démarrage) et enregistre ce qu'elles ont imprimé dans video/out/proofs.json. Les scènes de terminal rejouent cette sortie capturée dans un terminal HTML à une taille lisible. Règles : montrez le texte réel de la commande (raccourcissez uniquement le chemin du package) ; tronquez visiblement les sorties très longues (une ligne "... N lignes ..." atténuée) et mettez "Exécution enregistrée" dans le pastille ; n'imprimez jamais de jetons ; formatez joliment le JSON et dites-le si vous le faites.

Phase G : Audio de la narration

Par défaut (aucun compte requis) : node video/final.mjs --rate 2 crée un WAV par ligne avec la voix Windows intégrée (Microsoft Zira) et mesure chaque longueur. Le débit 1 donne environ 150 s de parole pour le script de référence, le débit 2 environ 139 s, le débit 3 est trop rapide. Choisissez le débit le plus lent qui maintient l'ensemble de la vidéo sous la limite. Voix humaine optionnelle : voir l'annexe A. Tout ce qui suit fonctionne de la même manière avec l'une ou l'autre.

Phase H : Enregistrement et assemblage

node video/final.mjs --rate 2                   # tout : tts, preuves, enregistrement de toutes les scènes, assemblage des deux montages
node video/final.mjs --rate 2 --reuse-proofs    # sauter la réexécution des preuves
node video/final.mjs --scenes sim,close --reuse-tts --reuse-proofs   # réenregistrer certaines scènes uniquement
node video/final.mjs --assemble-only            # remux (sous-titres, audio) sans réenregistrement
node video/final.mjs --tts-dir video/out/tts-human --name my_video --single    # construire à partir d'un autre dossier audio

Une exécution complète prend 6 à 10 minutes ; exécutez-la en arrière-plan et interrogez le journal. Le script échoue si le total est de 180 s ou plus. Visez 170 s. Important : si vous modifiez le texte de la narration ou la voix, les durées changent, donc chaque scène doit être réenregistrée (les marques proviennent des durées). Changer uniquement les visuels d'une scène signifie --scenes <id> --reuse-tts.

Phase I : Contrôle qualité (ne sautez jamais, ne faites jamais confiance au journal)

  1. Extrayez les images à la fin de chaque ligne de narration du MP4 final : ffmpeg -ss <marqueFin-0.3> -i final.mp4 -frames:v 1 image.png (la timeline est dans video/out/timeline.json). Examinez-les. Vérifiez la lisibilité en 1080p, les espaces vides, le texte coupé, la position et la taille des sous-titres, la synchronisation (l'événement de sous-titre est à l'écran), pas de secret, pas de mention du fournisseur, étiquettes d'honnêteté présentes.
  2. ffmpeg -i final.mp4 -af volumedetect -f null - : moyenne d'environ -22 dB, maximum inférieur à 0 dB.
  3. Durée sous la limite dans les deux montages ; les deux fichiers ont un flux vidéo et un flux audio.
  4. grep -ril "<mots du fournisseur>" video/pages video/narration.mjs <documents de sortie> ne renvoie rien sauf un identifiant de modèle autorisé.
  5. Exécutez à nouveau les vérifications du projet (npm run verify ; e2e si l'interface a changé).
  6. Corrigez et re-rendez jusqu'à ce que tout réussisse.

Phase J : Livrables

Générez narration.md et shotlist.md avec node video/docs.mjs <dossierSortie> (horodatages réels). Copiez les MP4, SRT, vignette (node video/thumbnail.mjs <png>), les images de contrôle qualité et les fichiers du dépôt modifiés (tous les fichiers différents entre l'original et votre copie, à leurs chemins de dépôt). Écrivez COPY_LIST.md (corrections de bugs en premier, puis nouveaux fichiers, messages de validation suggérés, "exécutez build et vérifiez après copie"), README-snippet.md (commande d'exécution, fichier d'entrée :ligne, fichier client :ligne, fichier de compétence, lien d'espace réservé de la vidéo) et REPORT.md (fait, ce que l'utilisateur doit faire, risques). Dites clairement ce que vous n'avez pas pu vérifier (par exemple, vous n'avez pas pu écouter la voix).

3. Comment fonctionne le pipeline (lisez avant de le modifier)

Enregistreur (lib/recorder.mjs). Le recordVideo de Playwright limite le débit binaire et brouille les petits textes, donc celui-ci utilise le screencast Chromium : les images JPEG (qualité 92) sont horodatées à leur arrivée, écrites sur le disque et encodées à un débit constant de 30 ips avec libx264 crf 17. Les écrans statiques produisent peu d'images ; la dernière image est conservée. Les horodatages proviennent d'une même horloge (performance.timeOrigin + performance.now()), la même que celle utilisée par le réalisateur.

Réalisateur (lib/director.mjs). Chaque ligne de narration est un segment. d.seg(id, actions, {tail}) enregistre l'heure de début, exécute les actions à l'écran, puis attend que la ligne ait fini de jouer plus tail * 0.45 secondes (les queues sont coupées globalement pour respecter la limite). Les marques (id, début, fin, texte) sont sauvegardées dans video/out/<scene>.marks.json. Comme l'audio est ensuite placé aux marques enregistrées, l'image et la voix ne peuvent pas dériver. Règle pour un temps : effectuez l'action à l'intérieur du segment et assurez-vous que l'action se termine avant la narration ; si la ligne est plus courte que l'action, divisez-la en deux lignes (c'est pourquoi un temps d'histoire est devenu sim9 et sim10).

Audio (final.mjs). Chaque WAV est retardé à son début global avec adelay, mixé avec amix=normalize=0, limité avec alimiter, et complété avec apad=whole_dur=<total> (sans le complément, -shortest coupe la fin de la vidéo).

Sous-titres. Les repères sont le texte de la narration divisé aux fins de phrase (les décimales telles que "2.0" sont protégées) et aux virgules lorsqu'il dépasse 82 caractères, avec un temps divisé proportionnellement à la longueur. Le fichier .srt est livré. La version incrustée utilise un fichier ASS généré avec PlayResX: 1920, PlayResY: 1080 et une taille de police 36. N'incrustez pas un SRT avec force_style : libass le redimensionne par rapport à un canevas de 288 pixels de haut et le texte sort environ quatre fois trop grand.

Superposition (lib/overlay.mjs), injectée uniquement dans la page de l'application enregistrée (l'application elle-même n'est pas modifiée)...

[... tronqué pour la traduction ...]

Skills associés