Communitygithub.com

show-n-tell

Créez une vidéo de démonstration commentée et personnalisée d'un site web, avec exploration, storyboard, narration TTS, enregistrement Playwright, mixage audio/vidéo et overlay de marque.

Qu'est-ce que show-n-tell ?

Ce skill orchestre un pipeline complet pour transformer n'importe quel site web, un logo et une intention en une vidéo de démonstration commentée et personnalisée d'environ 5 minutes. Il commence par une phase d'entretien pour collecter les informations clés (URL, notes d'intention, logo, couleurs, type d'authentification). Ensuite, il gère l'exploration du site, la création d'un storyboard détaillé (que l'utilisateur révise en langage naturel), la génération de narration via l'API TTS d'OpenAI, l'enregistrement avec Playwright, le mixage audio/vidéo, l'ajustement de la vitesse, l'application d'overlays de marque, et produit un fichier MP4 finalisé. Il prend en charge l'authentification OAuth/SSO en capturant l'état de session via un navigateur ou des outils spécifiques à l'environnement (Claude Code CLI ou Cowork). Le skill est conçu pour être flexible et robuste, avec des phases distinctes et des recommandations détaillées pour chaque environnement d'exécution.

Compatible avec✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/carveragents/show-n-tell/tree/main/skills/show-n-tell

Demander à votre IA préférée

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

Documentation

Que fait show-n-tell ?

Vous orchestrez un pipeline complet qui transforme n'importe quel site web + un logo + une intention en une vidéo de démonstration commentée et personnalisée d'environ 5 minutes. Les scripts dans scripts/ sont de simples tuyaux ; vous êtes le chef d'orchestre.

Documents de référence dans ce dossier : docs/SCHEMAS.md (grammaire YAML + actions), docs/GOTCHAS.md (problèmes connus + solutions de contournement), docs/CONTEXT.md (à quoi ressemble un bon résultat), examples/halyard-spme/ (exemple complet canonique). Lisez-les si nécessaire — ne les préchargez pas.

Quand utiliser ce skill

  • L'utilisateur souhaite une vidéo de démonstration commentée d'un site web (en ligne, en développement local ou statique).
  • L'utilisateur a au moins des indications légères d'intention ("montre X, Y, Z" / "démo du flux du tableau de bord").
  • L'utilisateur a accès à un logo ou un mot-symbole.

Refusez de continuer si l'utilisateur ne vous donne ni notes d'intention ni logo. Les démos génériques avec une image de marque par défaut sont de mauvaises démos. Demandez des indications plutôt que de produire silencieusement une vidéo faible.

Détection de l'environnement (à lire avant de commencer)

Avant toute chose, déterminez dans quel environnement Claude s'exécute :

  • Cowork : mcp__cowork__list_artifacts et mcp__computer-use__screenshot sont disponibles dans la liste d'outils de Claude.
  • Claude Code CLI : ces outils sont absents.

Ceci est important car plusieurs phases se comportent différemment selon l'environnement. Aide-mémoire :

PhaseClaude Code CLICowork
Répertoire de travail (Phase 5)~/demo-videos/<slug>/request_cowork_directory donne le chemin
Exploration du site public (Phase 2b)Outils Playwright MCPOutils Chrome MCP ou explore_page.py headless
Capture d'authentification OAuth (Phase 2a)Exécutez capture_auth.py via BashL'utilisateur exécute capture_auth.py localement
Commandes longues (Phases 7–9)Exécution synchronenohup + sondage (timeout bash de 45s)
Transfert (Phase 11)Rapport du chemin mp4Chemin mp4 + lien computer://

Phase 1 — Entretien (collecte des informations)

Posez une ou deux questions à la fois, pas toutes en même temps. Requis :

  1. URL cible — confirmez qu'elle est accessible.
  2. Notes d'intention de la démo — quelle histoire raconte-t-elle ? Quelles fonctionnalités sont importantes ?
  3. Public + ton — interne/externe/investisseurs ; explicatif/commercial/technique/décontracté.
  4. Durée cible — par défaut 5 min.
  5. Logo — URL ou chemin. Si seulement du texte est disponible, signalez la limitation mais acceptez.
  6. Couleurs de la marque — primaire (encre) + accent. Si non spécifiées, déduisez-les du logo avec PIL.
  7. Authentification ? — le site nécessite-t-il une connexion ?
    • Non → continuez.
    • Oui, formulaire (le site a ses propres champs email/mot de passe que vous contrôlez) → utilisez session.pre_session dans demo_config.yaml. Collectez les noms de variables d'environnement (PAS les valeurs réelles) et l'URL/les sélecteurs de connexion. Dites à l'utilisateur de placer les identifiants réels dans <répertoire_de_travail>/.env lui-même avant l'exécution, jamais dans le chat. Voir examples/login-flow/.
    • Oui, OAuth / SSO / lien magique / clé d'accès (Google, Microsoft, Okta, etc.) → utilisez session.storage_state. L'utilisateur n'exécute AUCUNE commande. VOUS lancez helpers/capture_auth.py pour eux dans la Phase 2a, et ils se connectent uniquement de manière interactive dans la fenêtre du navigateur qui s'ouvre. Le fichier auth.json capturé est ensuite utilisé à la fois pour l'exploration de la Phase 2b ET l'enregistrement de la Phase 8. Voir examples/oauth-storage-state/.

Phase 2a — Capture d'authentification (OAuth uniquement)

Sautez complètement cette phase si la question 7 de la Phase 1 a abouti à "pas d'authentification" ou "formulaire". Pour OAuth / SSO / lien magique / clé d'accès, capturez une session authentifiée MAINTENANT, avant l'exploration du site — la Phase 2b en a besoin pour voir les pages authentifiées.

mkdir -p ~/demo-videos/<slug-démo>/
uv run helpers/capture_auth.py <url_de_connexion_ou_de_départ> \
  --out ~/demo-videos/<slug-démo>/auth.json \
  --viewport <recording.viewport de demo_config.yaml ; défaut 1440x900>

Exécutez ceci via l'outil Bash avec timeout: 600000 (10 minutes — le maximum). Le script ouvre une fenêtre Chromium avec interface graphique. Dites à l'utilisateur en termes simples :

"J'ouvre une fenêtre de navigateur pour vous permettre de vous connecter. Effectuez la connexion (Google, Microsoft, etc., gérez la 2FA), naviguez jusqu'à la page à partir de laquelle vous souhaitez que l'enregistrement commence, puis fermez la fenêtre du navigateur. Je sauvegarderai la session et continuerai automatiquement."

Le script écrit auth.json avec le mode 0600 de manière atomique. Si l'utilisateur prend plus de 10 minutes (rare, mais possible avec la 2FA par téléphone dans une autre pièce), le timeout Bash se déclenche — réexécutez simplement la même commande.

--viewport DOIT correspondre à recording.viewport dans demo_config.yaml. Certains sites vérifient la taille du viewport ; une discordance peut invalider la session capturée au moment de l'enregistrement ou de l'exploration.

Si Chromium de Playwright n'est pas encore installé (nouveau clone du skill), le script affiche une erreur exploitable. Exécutez uv run --with playwright playwright install chromium une fois.

Si exécuté dans Claude Code CLI : exécutez capture_auth.py via Bash comme décrit ci-dessus.

Si exécuté dans Cowork : Claude gère cela directement en utilisant les outils computer-use et Chrome — l'utilisateur n'a qu'à se connecter lorsque le navigateur s'ouvre. Étapes :

  1. Assurez-vous qu'un chemin de répertoire de travail est connu. Si la Phase 5 n'a pas encore été exécutée, appelez mcp__cowork__request_cowork_directory maintenant pour obtenir le chemin des sorties et définissez <répertoire_de_travail> sur <chemin_des_sorties>/<slug-démo>/.

  2. Ouvrez Chrome sur le bureau de l'utilisateur :

    mcp__computer-use__open_application  →  "Google Chrome"  (ou "Chrome")
    
  3. Naviguez vers l'URL de connexion. Préférez le Chrome MCP s'il est connecté :

    • Extension Chrome disponible : mcp__Claude_in_Chrome__navigate vers <url_de_connexion_ou_de_départ>
    • Extension Chrome non connectée : utilisez les outils mcp__computer-use__* pour cliquer sur la barre d'adresse et taper l'URL
  4. Dites à l'utilisateur de se connecter — dites en termes simples :

    "Chrome est ouvert sur la page de connexion. Veuillez vous connecter (gérez toute 2FA, SSO, etc.), puis naviguez jusqu'à la page où l'enregistrement doit commencer. Faites-moi savoir quand vous avez terminé."

  5. Attendez et observez. Sondez avec mcp__computer-use__screenshot environ toutes les 15 secondes. Continuez une fois que l'URL n'est plus une page de connexion/auth et qu'un tableau de bord ou une page d'application est visible.

  6. Extrayez l'état de session via JavaScript. Exécutez cet extrait avec mcp__Claude_in_Chrome__javascript_tool :

    (() => {
      const cookies = document.cookie.split(';').map(c => {
        const [name, ...rest] = c.trim().split('=');
        return { name: name.trim(), value: rest.join('='), domain: location.hostname,
                 path: '/', expires: -1, httpOnly: false, secure: location.protocol === 'https:',
                 sameSite: 'Lax' };
      }).filter(c => c.name);
      const ls = {};
      for (let i = 0; i < localStorage.length; i++) {
        const k = localStorage.key(i);
        ls[k] = localStorage.getItem(k);
      }
      const ss = {};
      for (let i = 0; i < sessionStorage.length; i++) {
        const k = sessionStorage.key(i);
        ss[k] = sessionStorage.getItem(k);
      }
      return JSON.stringify({
        cookies,
        origins: [{ origin: location.origin,
                    localStorage: Object.entries(ls).map(([n,v]) => ({name:n,value:v})),
                    sessionStorage: Object.entries(ss).map(([n,v]) => ({name:n,value:v})) }]
      }, null, 2);
    })()
    
  7. Écrivez le résultat dans <répertoire_de_travail>/auth.json en utilisant l'outil Write. Ceci est un format storage_state valide pour Playwright — helpers/explore_page.py et record_demo.py le consomment tous deux via browser.new_context(storage_state=...).

  8. Avertissement concernant les cookies HttpOnly. JavaScript ne peut pas lire les cookies HttpOnly — ils sont intentionnellement invisibles pour document.cookie. Si le jeton de session du site est uniquement HttpOnly (courant avec les anciens cookies de session Rails/Django), l'état extrait sera incomplet. Dites à l'utilisateur :

    "Remarque : les cookies de session marqués HttpOnly ne sont pas accessibles depuis JavaScript, donc je n'ai peut-être pas capturé tous les jetons d'authentification. L'enregistrement essaiera d'utiliser ce qui a été capturé — s'il rencontre un mur de connexion pendant la Phase 8, nous pourrons revenir à l'utilisation de capture_auth.py localement." Continuez ensuite — de nombreux sites modernes (Google, Microsoft, Okta) conservent suffisamment d'état dans des cookies non HttpOnly ou localStorage pour que Playwright fonctionne.

Phase 2b — Exploration du site

Si la Phase 2a a été exécutée (auth.json existe), utilisez helpers/explore_page.py pour voir les pages authentifiées — le Playwright MCP ne peut pas charger storage_state et ne verrait que des murs de connexion. Pour les démos sans authentification, le Playwright MCP est bien et plus interactif ; utilisez-le comme avant.

Pour les pages authentifiées :

mkdir -p ~/demo-videos/<slug-démo>/_explore/
uv run helpers/explore_page.py https://cible.example.com/tableau-de-bord \
  --storage-state ~/demo-videos/<slug-démo>/auth.json \
  --out-dir ~/demo-videos/<slug-démo>/_explore/

Ceci écrit trois fichiers par page dans _explore/ : <slug>.png (capture d'écran), <slug>.dom.html (DOM pour la sélection de sélecteurs), <slug>.meta.json ({url_demandée, url_finale, titre, statut}). Lisez le PNG avec l'outil Read pour voir la page ; grep le DOM pour les sélecteurs. Si final_url dans meta.json pointe vers une page de connexion, la session a expiré — réexécutez la Phase 2a.

Pour les pages publiques (page d'accueil, pages marketing de toute démo ; tout dans une démo sans authentification) — utilisez les outils Playwright MCP (mcp__plugin_playwright_playwright__*) comme avant :

  • browser_navigate vers l'URL cible, puis vers 2 à 5 pages dont l'utilisateur a mentionné l'intention.
  • browser_snapshot ou browser_take_screenshot pour voir la mise en page de chaque page.
  • Utilisez browser_evaluate pour lire le DOM et trouver des sélecteurs stables (préférez les sélecteurs sémantiques aux nth-of-type lorsque c'est possible).

Si exécuté dans Claude Code CLI : utilisez les outils mcp__plugin_playwright_playwright__* comme décrit ci-dessus.

Si exécuté dans Cowork : Assurez-vous d'abord que Chromium est disponible :

uv run --with playwright playwright install chromium

Choisissez ensuite la meilleure méthode disponible :

  • Si mcp__Claude_in_Chrome__navigate est disponible (extension Chrome connectée), utilisez mcp__Claude_in_Chrome__navigate + mcp__Claude_in_Chrome__read_page pour explorer le site de manière interactive.
  • Sinon, utilisez l'exploration headless :
    mkdir -p <répertoire_de_travail>/_explore/
    uv run helpers/explore_page.py <url> --out-dir <répertoire_de_travail>/_explore/
    
    (Pas besoin de --storage-state pour les pages publiques — l'argument est désormais facultatif.)

Notez pour chaque page significative :

  • Les moments dignes d'une démo (défilement vers une fonctionnalité, clic pour voir les détails, survol d'info-bulle).
  • Les adaptations nécessaires du site : astuce d'en-tête collant ? Lien profond PDF ? Bloqueurs de modale ? Mur d'authentification ?
  • Les sélecteurs qui semblent fragiles et pourraient nécessiter des défenses wait_for_selector.

Ne parcourez pas de manière exhaustive. 2 à 5 actions par page est suffisant.

Phase 3 — Projet de storyboard.yaml

Générez 15 à 30 séquences. Chaque séquence = une action de caméra + 1 à 3 phrases de narration. Voir docs/SCHEMAS.md pour la grammaire des actions (sous-ensemble Phase A : goto, goto_and_scroll, scroll_into_view, scroll_y, hover, click).

Objectif pour une vidéo de 5 minutes à une accélération de 1,2x :

  • Temps total post-accélération : ~5:00
  • Temps total brut : ~6:00
  • Moyenne par séquence : ~12s, dont ~9–10s de narration

Règles strictes lors de la rédaction de la narration :

  1. Chaque affirmation factuelle doit être visible à l'écran dans cette séquence. Pas de chiffres inventés ("l'agent a signalé 199 modifications"). Si vous ne le voyez pas sur la capture d'écran, ne le dites pas.
  2. Les initialismes lus lettre par lettre doivent être écrits avec des traits d'union : S-P-M-E, K-Y-B, A-P-I. L'invite TTS applique cette convention.
  3. La longueur correspond au contenu visuel : 8–18s pour les séquences de défilement, 6–12s pour les séquences de clic.
  4. Le ton correspond au champ voice.tone de branding.yaml.

Regroupez mentalement les séquences en segments (Vue d'ensemble / Fonctionnalité A / Fonctionnalité B / Conclusion) mais écrivez une liste plate en YAML — pas de marqueurs de section.

Phase 4 — Révision en langage naturel

L'utilisateur n'édite pas le YAML directement. Vous présentez le projet sous forme de liste numérotée et acceptez les commentaires en langage naturel. Utilisez ce format exactement :

Voici le flux de démonstration que j'ai élaboré. Durée estimée : 5:08 (après accélération 1,2x).
Dites-moi ce que vous souhaitez modifier.

VUE D'ENSEMBLE (60s)
1. Arrivée sur la page d'accueil (10s) — "Bienvenue sur Acme Cloud, une plateforme serverless pour les petites équipes..."
2. Défilement vers les fonctionnalités (15s) — "Trois capacités principales animent la plateforme..."
3. Défilement vers les sorties (8s) — "Ces dix domaines politiques..."

FONCTIONNALITÉ 1 — Tableau de bord (45s)
4. Navigation vers le tableau de bord (8s) — "En cliquant dans le tableau de bord..."
5. Survole du flux d'activité en direct (12s) — "Chaque projet affiche un flux d'activité en direct..."
...

CONCLUSION (20s)
27. Retour aux statistiques de la page d'accueil (12s) — "Trois raisons pour lesquelles les équipes choisissent Acme..."
28. Conclusion (8s)

Puis : "Quelque chose à ajouter, supprimer ou réorganiser ? Des ajustements de ton de narration ? Quelque chose à sauter ?"

Traduisez les commentaires en langage naturel en modifications YAML :

  • "Supprimer la séquence 7" → supprimez du YAML
  • "Allonger la séquence 3" → étendez la narration avec plus de détails à l'écran (divisez en deux séquences si beaucoup plus long)
  • "Mentionner les prix quelque part" → identifiez la bonne séquence et ajoutez une phrase (vérifiez que les prix sont effectivement visibles dans cette séquence)
  • "Ton trop formel" → réécrivez la narration avec un phrasé plus décontracté
  • "Montrer la page d'équipe au lieu de à propos" → échangez l'URL + ajustez la narration

Re-présentez le flux mis à jour. Itérez jusqu'à ce que l'utilisateur approuve explicitement.

Vérification de la dérive de durée avant TTS : somme de len(beat.narration) / 16 (caractères/s à 140 mots/min) sur toutes les séquences. Si estimé * (1 / multiplicateur_vitesse) est à plus de 30s de la cible, signalez-le : "Cela donne actuellement ~6:20 post-accélération alors que votre objectif est de 5min. Voulez-vous que je réduise ?"

Phase 5 — Configuration du répertoire de travail

mkdir -p ~/demo-videos/<slug-démo>/_assets
cp <chemin_du_logo>             ~/demo-videos/<slug-démo>/_assets/<logo>.png
# écrivez storyboard.yaml, branding.yaml, demo_config.yaml à partir de vos projets

Si exécuté dans Claude Code CLI : utilisez ~/demo-videos/<slug-démo>/ comme indiqué ci-dessus.

Si exécuté dans Cowork : appelez mcp__cowork__request_cowork_directory pour obtenir le chemin des sorties de l'utilisateur. Définissez le répertoire de travail sur <chemin_des_sorties>/<slug-démo>/. Utilisez ce chemin pour TOUTES les écritures de fichiers ultérieures dans les Phases 6–11 — stockez-le maintenant et conservez-le cohérent tout au long de la session. Créez le sous-répertoire _assets/ sous ce chemin, pas sous ~/demo-videos/.

Si l'utilisateur n'a pas de fichier logo sur le disque et a seulement une URL, téléchargez-le avec curl et placez-le dans _assets/.

[Suite du document...]

Skills associés