Communitygithub.com

Démos UI Synthétiques (synthetic-ui-demo)

Créez des vidéos de démonstration produit et de notes de version sans enregistrement d'écran. Reconstruisez les écrans de l'application en React statique à partir de son code source, puis animez-les dans Remotion avec un curseur et une caméra scriptés.

Qu'est-ce que Démos UI Synthétiques (synthetic-ui-demo) ?

Cette compétence permet de générer des démonstrations produits et des vidéos de notes de version sans jamais enregistrer d'écran. Claude Code lit le dépôt du produit, reconstruit uniquement les écrans affichés dans chaque scène sous forme de React statique, et un curseur ainsi qu'une caméra scriptés exécutent le parcours dans Remotion. Chaque clic correspond à un numéro d'image précis, garantissant un rendu identique à chaque fois, sans avoir besoin de comptes pré-enregistrés ni d'environnement réel. Elle est idéale pour les démos de fonctionnalités, les vidéos de notes de version, ou les changelogs d'applications dont le code source est accessible. Elle est également utile lorsqu'un enregistrement Playwright serait instable, nécessiterait des données de test ou deviendrait rapidement obsolète. Cette approche offre une reproductibilité parfaite et une mise à jour simple par édition du code lorsque le produit évolue, contrairement aux enregistrements d'écran traditionnels. Les blocs de construction incluent Stage (fenêtre de navigateur avec caméra), Cursor (curseur animé) et des kits d'écran produits spécifiques. La méthode implique de spécifier visuellement l'interface depuis le dépôt, de reconstruire statiquement les écrans, de générer l'audio avec un timing précis, et d'ancrer les animations aux mots prononcés via des repères temporels.

Compatible avec✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/digitalsamba/claude-code-video-toolkit/tree/HEAD/.claude/skills/synthetic-ui-demo

Demander à votre IA préférée

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

Documentation

Démos UI Synthétiques

Rien n'est enregistré depuis l'écran. Claude Code lit le dépôt du produit, reconstruit uniquement les écrans qu'une scène montre en React statique, et un curseur ainsi qu'une caméra scriptés exécutent le parcours dans Remotion. Chaque clic est un numéro d'image, donc une scène se re-rend à l'identique, n'a jamais besoin d'un compte pré-rempli ou d'un environnement réel, et est mise à jour en éditant le code lorsque le produit change.

Constructions de référence (à lire en parallèle de cette compétence ; les deux se construisent sans les dépôts produits) :

  • examples/ds-free-schedule-demo : un flux de 26s (planifier un appel) avec une vignette narrateur. Le cas complet le plus simple. Son src/Demo.tsx est une timeline unique avec chaque image clé du curseur, clic et mouvement de caméra.
  • examples/ds-release-649 : une vidéo de notes de version de 80s, huit scènes dans trois applications. templates/ds-release-notes en est la forme réutilisable (livrée en release 650). src/Release.tsx séquence les scènes, src/scenes/ contient un fichier par élément de version, et src/room/ et src/ac/ sont les kits d'écran.

Quand utiliser ceci vs. Playwright

Synthétique (cette compétence)Enregistrement Playwright (/record-demo)
Vous pouvez lire le code source de l'applicationVous avez seulement l'application en cours d'exécution
Notes de version et visites guidées de fonctionnalités refaites à chaque versionCapture unique d'un comportement ou de données réelles
Le flux nécessite des données que vous n'avez pas (un appel complet, d'autres utilisateurs, une vue admin)Le réel est facile d'accès et correct tel quel
Mouvements de caméra, timing de clics exact, re-rendus après un changement de voixInteractions longues et complexes qui seraient coûteuses à reconstruire

Blocs de construction (lib/components)

import { Stage, typed, cursorAt, near } from '../../../../lib/components';

<Stage
  url="app.example.com/settings"             // barre d'adresse ; hôte plus sombre que le chemin
  camera={CAMERA}                             // [{ f, z, x, y }] en pixels du canevas, lissé, limité à la fenêtre
  path={PATH}                                 // [{ f, x, y }] images clés du curseur en pixels du canevas
  clicks={CLICKS}                             // images qui écrasent le curseur et déclenchent une ondulation
  aiNote                                      // "Les personnes montrées sont générées par IA" (ou passez votre propre texte)
  canvasWidth={1440} canvasHeight={810}       // les valeurs par défaut
>
  <SettingsScreen field={typed(frame, 'Q4 Product Review', 128)} />
</Stage>
  • Stage dessine le chrome du navigateur autour d'un canevas d'application de taille fixe, applique la caméra, et place le curseur par-dessus à un zIndex de 100. Au zoom 1, la fenêtre est fit (0,8625) de la largeur du cadre. Les images clés répètent une valeur pour la maintenir.
  • Cursor et cursorAt fonctionnent seuls pour une scène sans navigateur ; near(cursor, target) pilote les états de survol.
  • Les kits d'écran spécifiques au produit (thème, icônes, mises en page) restent dans le projet. Ils ne font pas partie de la bibliothèque.

Méthode

1. Extraire une spécification visuelle du dépôt de l'application, avec des sous-agents

Envoyez un sous-agent par application ou domaine, en parallèle, et demandez à chacun de retourner une spécification compacte plutôt que des dumps de fichiers :

  • Thème : palette, famille de polices, rayons, espacements, ombres (depuis le fichier de thème ou les variables CSS).
  • Chaînes : les chaînes de langue anglaises exactes pour chaque étiquette, élément de menu, dialogue et toast que la scène montre (public/locales/en/*.json, src/i18n/locales/en/*). Ne paraphrasez jamais le texte de l'interface utilisateur.
  • Icônes : si l'application utilise une police d'icônes, son fichier selection.json icomoon/fontello contient les chemins SVG de chaque glyphe. Extrayez ceux dont vous avez besoin dans un petit JSON et rendez-les sous forme de <svg><path d=...>. Sinon, copiez les composants SVG.
  • Mise en page et comportement : arbre des composants pour les écrans affichés, ordre de la barre d'outils, valeurs par défaut, ce que fait chaque contrôle.

Lisez la branche par défaut depuis le dépôt distant (git show origin/main:chemin, ou git fetch puis lisez origin/<default>). Les checkouts locaux sont souvent obsolètes et vous donneront l'interface du trimestre dernier.

Pour les notes de version, tracez chaque élément jusqu'au commit et au composant qui le livrent en premier. Cela vous donne les chaînes exactes et les valeurs par défaut à afficher.

2. Reconstruire uniquement ce qu'une scène montre, sur un canevas fixe

  • Disposez chaque élément avec des positions absolues sur un canevas fixe (1440x810 est une bonne valeur par défaut). Exportez les rectangles importants sous forme de constantes (SAVE_BTN = { x, y, w, h }), afin que les cibles de clic soient arithmétiques, pas des suppositions.
  • Construisez seulement ce que la caméra voit. Un panneau qui n'est jamais dans le champ peut être une couleur unie.
  • Restez en React statique : pas d'état, pas d'effets. Chaque changement visuel est une fonction de frame.
  • Placez le kit dans son propre dossier (src/ui/, src/room/) avec un theme.ts pour les constantes.

3. La voix d'abord, puis placez la timeline en images

  • Écrivez une ligne par scène, coupez aux phrases (un .txt par phrase), et générez l'audio en premier (voiceover.py --scene-dir ...). Trois prises et tools/pick_takes.py valent mieux qu'une seule prise plus --max-wpm : un clone copie le rythme et la platitude de son clip de référence, donc si les lignes sortent précipitées ou monotones, corrigez le clip avec tools/voice_prosody.py expand plutôt que d'étirer la sortie (voir "Clone Prosody" dans CLAUDE.md). Lisez les durées mesurées, et tools/captions.py pour les timings des mots.
  • Dimensionnez chaque scène à sa ligne plus un temps mort, et gardez un commentaire d'en-tête listant le début et la durée de chaque ligne. Ce commentaire est la source de vérité (voir "Audio-Anchored Timelines" dans CLAUDE.md).
  • Tout est une constante d'image en haut du fichier de scène : images clés du curseur, CLICKS, images clés de la caméra, changements d'état de l'interface utilisateur (frame >= C.save montre le dialogue). Exportez les images de clic pour que le parent puisse placer les effets sonores de clic.
  • Cherchez les images à partir de la narration, ne les définissez pas manuellement. voice() (lib/components/cues.ts ; le template ds-release-notes en a une copie) prend les phrases de la scène avec leurs .captions.json et images de début, et cue('save') retourne l'image où le mot commence. Ancrez chaque action au mot qu'elle illustre, avec un décalage, et chaque image clé du curseur et de la caméra à ces ancres :
    import line06a from '../../public/audio/scenes/06a_link.captions.json';
    export const LINK_VOICE = voice([{ file: '06a_link', at: 10, captions: line06a }, ...]);
    const { cue } = LINK_VOICE;
    const C = { field: cue('avant', { offset: -3 }), save: cue('enregistrer') };
    const PATH = [{ f: C.field - 6, ...field }, { f: C.save - 24, ...saveBtn }];
    
    Régénérez ou re-timing une phrase et les clics, la frappe, le curseur et la caméra la suivent. Un repère dont les mots ne sont plus prononcés échoue le bundle avec les mots qui le sont. Options : offset, edge: 'end', after (une image, pour un mot répété), nth, in (une phrase). Le parent place l'audio depuis LINK_VOICE.lines, donc l'image de début d'une phrase est écrite une fois. templates/ds-release-notes/src/scenes/FreeCustomLink.tsx est l'exemple travaillé.

4. Diviser les lignes de liste denses à leurs pauses

Une ligne qui liste plusieurs choses ("planification, contacts, enregistrements et transcriptions") est trop rapide pour une seule prise. Divisez l'audio à ses pauses en fichiers de phrase (07a, 07b, ...), donnez à chaque phrase sa propre prise, et placez chaque phrase sur son propre temps mort. ds-release-649's moreVo fait cela.

5. Mesurer les cibles de clic à partir d'une planche contact avant le rendu complet

Une coordonnée devinée est généralement décalée de 20 à 50 px une fois que la caméra zoome. Effectuez un rendu d'images fixes à chaque image de clic et quelques images avant, juxtaposez-les et vérifiez que la pointe du curseur se trouve sur la cible :

i=1; for f in 46 78 122 212; do npx remotion still MyComp out/stills/s$i.png --frame=$f; i=$((i+1)); done
ffmpeg -start_number 1 -i out/stills/s%d.png -vf "scale=640:-1,tile=2x2" -frames:v 1 out/contact.png

Corrigez les constantes, re-rendez les images fixes, et seulement ensuite effectuez le rendu de la vidéo.

6. Étiqueter les personnes générées par IA à l'écran

Toute personne qui n'est pas réelle (portraits FLUX.2 dans les vignettes, avatars, narrateur) reçoit une étiquette visible : aiNote sur le Stage, ou un badge "IA" sur une vignette de narrateur. Les noms, contacts et données d'appel sont également inventés, donc gardez-les clairement fictifs.

7. Rendre, puis normaliser

tools/qc.py --project ... avant le rendu, puis qc.py --render out/video.mp4 --fix pour -14 LUFS. qc.py --project ... --layout vérifie le propre texte de la vidéo (sous-titres, cartes, note IA) pour la taille et le contraste, et liste séparément celui de l'interface utilisateur du produit. Stage marque sa fenêtre data-qc="product" ; mettez le même attribut sur toute maquette de téléphone ou tablette que vous construisez en dehors, ou son texte d'interface utilisateur sera jugé comme celui de la vidéo.

Pièges

  • Les logos SVG monochromes rendent en noir. Un logo_mono.svg a généralement des remplissages noirs ; sur un fond sombre, utilisez filter: brightness(0) invert(1).
  • Branches locales obsolètes. Lisez origin/<default>, pas la branche sur laquelle le checkout local se trouve.
  • rsync --exclude src supprime aussi node_modules/*/src. Lors de la copie d'un projet ou kit, ancrez les exclusions à la racine de transfert avec une barre oblique : --exclude /src.
  • La caméra se limite. Un centre de caméra près du bord du canevas est tiré vers l'intérieur pour que le bord de la fenêtre ne dépasse jamais du cadre. Si un zoom atterrit quelque part d'inattendu, c'en est la raison ; visez un point plus à l'intérieur.
  • Les menus et dialogues doivent se trouver à l'intérieur du canevas. Le canevas coupe ses enfants. Positionnez un menu pour qu'il s'ouvre vers l'intérieur, comme le fait l'application réelle.
  • Les états de survol viennent du chemin du curseur. Utilisez near(cursorAt(frame, PATH), target) plutôt qu'un second ensemble de constantes d'image, de sorte que déplacer une image clé déplace le survol avec elle.
  • Une ligne vocale modifiée déplace tout ce qui la suit. Dans une scène avec repères, les clics, le curseur et la caméra suivent d'eux-mêmes, mais la longueur de la scène et les at des phrases ultérieures doivent encore être vérifiés. Dans une scène réglée manuellement, re-mesurez chaque image. Dans tous les cas, mettez à jour le commentaire d'en-tête et les longueurs de scène, puis revérifiez les images fixes de clic. Si un narrateur lip-sync est piloté par la piste vocale assemblée, régénérez-le aussi.
  • Un kit survit à sa démo. Un kit d'écran reconstruit peut héberger d'autres vidéos : le ds-release-notes room est devenu la scène d'une édition de marque d'un court métrage parodique, avec des visages animés dans ses vignettes et aucun nouveau travail d'écran. Copiez le kit dans le nouveau projet et mettez à l'échelle son canevas logique au cadre (.claude/skills/parody-short/formats.md).

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

digitalsamba/claude-code-video-toolkit

Python video composition with moviepy 2.x — overlaying deterministic text on AI-generated video (LTX-2, SadTalker), compositing clips, single-file build.py video projects. Use when adding labels/captions/lower-thirds to LTX-2 or SadTalker outputs, building short ad-style spots in pure Python without Remotion, or doing programmatic video composition. Triggers include text overlay on video, label LTX-2 clip, caption SadTalker output, lower third, build.py video, moviepy, Python video composition, sub-30s ad spot.

digitalsamba/claude-code-video-toolkit

Video and audio processing with FFmpeg. Use for format conversion, resizing, compression, audio extraction, and preparing assets for Remotion. Triggers include converting GIF to MP4, resizing video, extracting audio, compressing files, or any media transformation task.

digitalsamba/ideogram4

Prompting patterns for Ideogram 4 text-to-image — best-in-class in-image text rendering and exact color/layout control via structured JSON captions. Use when generating images that need legible on-image text (title cards, thumbnails, logos, signage, CTAs), precise brand colors, or controlled spatial layout. Triggers include title slide image, thumbnail with text, on-image text, legible text in image, brand color palette image, bounding-box layout, Ideogram.

digitalsamba/parody-short

Comedy shorts about a group's own life - a team's launch, quarter end, office move or leaving do; a club's season; a class's year; a family's Christmas - or about a shared topic everyone recognises (video calls, the return to the office), told in a borrowed genre (80s action intro, creature feature, Dickens Christmas ad, heist, nature documentary) and starring the group's real, animated photos or an invented cast. Covers mining the group's own context for in-jokes (chat, email, calendars,...

Skills associés