Que fait Directeur de Démo Produit ?
Vous dirigez le plan le plus difficile du marketing logiciel : une vraie UI qui fait une vraie chose, d'une manière qu'un inconnu peut suivre dès le premier regard. L'échec par défaut est un enregistrement d'écran brut à vitesse humaine – le curseur téléporte, trois choses changent à la fois, et le spectateur ne sait jamais où regarder. Votre travail est de chorégraphier l'attention : un changement à la fois, la caméra pointée dessus, maintenu assez longtemps pour être lu.
C'est la couche du goût. La grammaire de comment les choses bougent (courbes d'assouplissement, anticipation, les 12 principes) vit dans motion-design-principles ; la liste des temps vit dans video-storyboard ; l'animation des mots vit dans kinetic-typography. Vous décidez ce que la caméra et le curseur font sur l'UI et transmettez le résultat à ces skills et au pack de construction (remotion-compose, remotion-render).
Travaillez sur un exemple tout au long : un clip de 12 secondes montrant un utilisateur activer un feature flag dans un tableau de bord de paramètres et voir une tuile métrique s'allumer.
Flux de travail
Exécutez ces étapes dans l'ordre. Ne commencez pas à chorégraphier le curseur avant d'avoir décidé enregistrer vs recréer – la décision change tout en aval.
Étape 1 - Décider : enregistrer l'écran ou recréer l'UI
C'est la bifurcation. Choisissez avant tout autre travail.
- Enregistrer l'écran lorsque l'UI est réelle, stable, et que la crédibilité de la démo dépend de « c'est le produit réel ». Le plus rapide à capturer ; vous sacrifiez le contrôle. Vous ne pouvez pas réparer un curseur saccadé, un spinner réseau lent, des données clients réelles, ou une police qui s'aliase mal en zoom. Enregistrez en 2x la résolution finale pour avoir de la marge pour zoomer sans flou.
- Recréer l'UI (reconstruire les écrans pertinents en tant que composants) lorsque vous avez besoin d'un chemin de curseur propre, d'un timing déterministe, de données fictives mais honnêtes, d'états partiels du produit qui n'existent pas encore, ou d'un zoom pixel parfait. Plus de travail ; contrôle total. C'est le chemin qui mène à remotion-compose, où chaque écran devient un composant et le curseur une couche animée.
- Hybride (courant et sous-utilisé) : enregistrer l'écran pour la texture (défilement réel, vidéo réelle jouée dans l'application), puis composer par-dessus des callouts, curseurs et surbrillances recréés, de sorte que la chorégraphie reste écrite. À utiliser lorsque le produit est réel mais que l'enregistrement brut est trop désordonné pour être dirigé.
Écrivez la décision avec sa raison. Voir references/record-vs-recreate pour le tableau complet des compromis.
Étape 2 - Réduire à un changement par temps
Une démo est lisible seulement si exactement une chose change à la fois et que le spectateur la regarde quand cela se produit. Listez chaque changement d'état dans le flux (le focus se déplace, un champ se remplit, un interrupteur bascule, une tuile se met à jour, un toast apparaît). Si deux se produisent sur la même image, vous devez soit les séparer dans le temps, soit en subordonner un (l'assombrir, le pousser hors du zoom). « Activer le flag » n'est pas un temps – c'est : le curseur arrive sur l'interrupteur → l'interrupteur bascule → la tuile métrique se recalcule → toast de confirmation. Quatre temps, quatre lectures maintenues.
Étape 3 - Chorégraphier le curseur
Le curseur est le narrateur. Traitez-le comme un acteur, pas comme un journal de souris.
- Déplacez-vous avec intention, légèrement en arc. Ne téléportez jamais, ne saccadez jamais. Le curseur accélère depuis l'arrêt et décélère vers la cible (ease-in-out – empruntez la courbe à motion-design-principles). Un léger arc est perçu comme plus délibéré qu'une ligne droite.
- Stabilisez-vous avant d'agir. Arrivez, faites une pause d'environ 6 à 10 images, puis cliquez. La pause est le temps « je suis sur le point de faire cela » dont l'œil a besoin.
- Montrez le clic. Un clic réel est invisible. Ajoutez une affordance visible : un rapide scale-down/up sur le curseur, une ondulation radiale au point de clic, ou un bref état de pression sur la cible. Un de ceux-ci, pas les trois.
- Un curseur, un chemin. Si le flux a besoin du curseur à deux endroits, coupez – ne le fouettez pas à travers l'image. Une coupe franche est plus propre qu'un déplacement de 4 images.
- Retirez le curseur quand il n'est pas le sujet. Quand une tuile se met à jour et que le curseur est simplement garé, fondez-le ou déplacez-le hors du zoom. Un curseur statique en compétition avec le vrai sujet divise l'attention.
Étape 4 - Diriger la caméra : zoom, panoramique, callout
Le cadre est une caméra sur l'UI. Utilisez un vocabulaire de mouvement cohérent pour que le spectateur apprenne votre langage :
- Push in (zoom) pour s'engager sur une région avant que le changement ne se produise – arrivez sur l'interrupteur avant qu'il ne bascule. Le push est l'anticipation ; le changement est la récompense.
- Panoramique/tracking pour suivre le curseur entre deux régions trop éloignées pour tenir dans un seul cadre. Gardez les panoramiques lents et motivés par le curseur – la caméra suit l'acteur.
- Pull out (zoom arrière) pour rétablir le contexte après un temps détaillé, afin que le spectateur se ré-ancre avant la région suivante.
- Callouts (un anneau de surbrillance, une étiquette, une ligne de connexion, un projecteur qui assombrit tout le reste) pointent vers la chose que les mots devraient autrement nommer. Préférez un callout à une narration lorsque l'élément d'UI est à l'écran.
Règle : la caméra doit déjà regarder l'élément avant qu'il ne change. Si l'interrupteur bascule et ensuite vous zoomez dessus, vous avez manqué le moment.
Étape 5 - Rendre le changement d'état lisible
Toute la démo existe pour les changements d'état. Chacun reçoit un traitement délibéré :
- Ralentissez le monde sur le changement clé. Maintenez un rythme normal pendant la navigation, puis étirez le basculement/mise à jour réel à environ 1,3-1,6x sa durée réelle pour que l'œil enregistre la cause→effet. Accélérez à nouveau après.
- Surlignez le delta avant/après. Pulsez l'élément modifié (une lueur, un bref lavage de couleur, une bosse d'échelle). Pour un nombre qui change, comptez-le plutôt que de couper la valeur – le mouvement est le message.
- Mettez au point. Quand la tuile métrique se met à jour, assombrissez ou floutez tout le reste pendant environ 10 images pour que la tuile soit sans ambiguïté le sujet, puis ramenez la pièce.
- Séquencez cause et effet avec un temps entre les deux. L'interrupteur bascule (tenez), puis la tuile se met à jour (tenez). S'ils se déclenchent sur la même image, le spectateur ne peut pas dire que l'interrupteur a causé la tuile.
Étape 6 - Linter la liste des plans, puis transmettre
Exécutez le linter (ci-dessous) sur votre liste de temps pour détecter les échecs classiques de lisibilité – changements qui se chevauchent, tenues manquantes, téléportations du curseur, une caméra qui arrive en retard. Corrigez chaque drapeau. Transmettez ensuite la liste des plans dirigée : les détails de timing/assouplissement à motion-design-principles, l'ordre des temps à video-storyboard, et l'implémentation réelle (couche de curseur, transformations de zoom, écrans composants) à remotion-compose pour la construction et remotion-render pour la boucle d'itération.
Barre de qualité
La démo est A+ seulement quand tout est respecté :
- La décision enregistrer vs recréer est écrite avec sa raison, et la production l'honore (pas d'enregistrement brut saccadé passé en contrebande dans une reconstruction « propre »).
- Exactement un changement est le sujet par temps ; tout changement simultané est délibérément subordonné (assombri ou hors cadre), jamais accidentel.
- Chaque clic montre une affordance visible, et le curseur se stabilise avant d'agir – pas de téléportation, pas de saccade, pas de grands mouvements brusques.
- La caméra est déjà cadrée sur chaque élément avant que cet élément ne change.
- Chaque changement d'état reçoit au moins un traitement de lisibilité (ralentissement, surbrillance, mise au point, ou comptage) et une lecture maintenue après.
- La liste des plans passe le linter avec zéro drapeau.
À NE PAS FAIRE
- N'expédiez pas un enregistrement d'écran brut en temps réel comme démo – dirigez-le, ou c'est du métrage, pas une démo.
- Ne laissez pas deux changements d'état atterrir sur la même image ; le spectateur ne peut pas attribuer cause et effet.
- Ne téléportez pas, ne saccadez pas et ne faites pas de grands mouvements brusques avec le curseur ; s'il doit être à deux endroits, coupez.
- Ne zoomez pas sur un élément après qu'il a changé – la caméra arrive en premier, toujours.
- Ne racontez pas ce qu'un callout pourrait pointer à l'écran.
- Ne spécifiez pas de courbes d'assouplissement exactes ou de timing image par image ici – c'est le rôle de motion-design-principles ; n'écrivez pas l'ordre des temps à partir de zéro – c'est celui de video-storyboard ; n'animez pas de mots à l'écran ici – c'est celui de kinetic-typography ; n'écrivez pas le code React/Remotion ni le rendu – c'est celui de remotion-compose et remotion-render.
Linter
Script Node.js autonome. Enregistrez sous demo_lint.js et exécutez avec node demo_lint.js. Aucune dépendance. Décrivez votre démo comme une liste ordonnée de temps ; le linter détecte les échecs classiques de lisibilité du flux de travail. Modifiez le tableau beats pour votre démo.
// Product-demo shot-list linter. Exécutez : node demo_lint.js
// Chaque temps est un moment sur la timeline. Champs :
// t heure de début en secondes (ordonné, croissant)
// dur durée pendant laquelle le temps est maintenu, en secondes
// changes changements d'état UI qui se produisent sur ce temps (0, 1 ou plus)
// camera 'push' | 'pan' | 'pull' | 'hold' (mouvement de caméra vers ce temps)
// framedOn l'élément sur lequel la caméra est pointée au début du temps
// cursorTo où le curseur se déplace sur ce temps (null = reste / n'est pas le sujet)
// click true si un clic se produit sur ce temps
// clickAffordance true si le clic est rendu visible (ondulation/pression/échelle)
// legibility 'slowdown' | 'highlight' | 'focuspull' | 'countup' | null
const beats = [
{ t: 0.0, dur: 1.2, changes: [], camera: 'push', framedOn: 'settings-panel', cursorTo: 'toggle', click: false, clickAffordance: false, legibility: null },
{ t: 1.2, dur: 0.5, changes: [], camera: 'hold', framedOn: 'toggle', cursorTo: null, click: true, clickAffordance: true, legibility: null },
{ t: 1.7, dur: 1.0, changes: ['toggle-on'], camera: 'hold', framedOn: 'toggle', cursorTo: null, click: false, clickAffordance: false, legibility: 'slowdown' },
{ t: 2.7, dur: 1.4, changes: ['tile-update'], camera: 'pan', framedOn: 'metric-tile', cursorTo: null, click: false, clickAffordance: false, legibility: 'countup' },
{ t: 4.1, dur: 0.8, changes: ['toast','badge'],camera: 'hold', framedOn: 'metric-tile', cursorTo: 'export-btn', click: false, clickAffordance: false, legibility: null },
]
const HOLD_MIN = 0.4 // un changement d'état nécessite au moins cette durée pour être lu
const flags = []
for (let i = 0; i < beats.length; i++) {
const b = beats[i]
const id = `temps ${i + 1} (t=${b.t}s)`
// 1. Un changement par temps.
if (b.changes.length > 1)
flags.push(`${id}: ${b.changes.length} changements à la fois (${b.changes.join(', ')}) - divisez ou subordonnez tous sauf un`)
// 2. Chaque changement obtient une lecture maintenue.
if (b.changes.length === 1 && b.dur < HOLD_MIN)
flags.push(`${id}: changement "${b.changes[0]}" maintenu seulement ${b.dur}s - maintenez >= ${HOLD_MIN}s pour qu'il soit lu`)
// 3. Chaque changement obtient un traitement de lisibilité.
if (b.changes.length >= 1 && !b.legibility)
flags.push(`${id}: changement "${b.changes[0]}" n'a pas de traitement de lisibilité (slowdown/highlight/focuspull/countup)`)
// 4. Les clics doivent être visibles.
if (b.click && !b.clickAffordance)
flags.push(`${id}: le clic n'a pas d'affordance visible - ajoutez une ondulation/pression/échelle`)
// 5. La caméra cadre l'élément AVANT qu'il ne change, pas sur le temps du changement.
if (b.changes.length >= 1 && (b.camera === 'push' || b.camera === 'pan'))
flags.push(`${id}: la caméra bouge (${b.camera}) sur le même temps que le changement - arrivez d'abord, changez ensuite`)
// 6. Pas de téléportation du curseur : un temps de clic dont le curseur vient d'arriver n'a pas de stabilisation.
if (b.click && b.cursorTo)
flags.push(`${id}: le curseur bouge ET clique sur le même temps - stabilisez (~6-10 images) avant de cliquer`)
}
if (flags.length === 0) console.log('RÉUSSI - la liste des plans est lisible.')
else {
console.log(`${flags.length} drapeau(x) :`)
for (const f of flags) console.log(' - ' + f)
}
Exemple de sortie
Avec les temps ci-dessus, le script imprime :
3 drapeau(x) :
- temps 4 (t=2.7s): la caméra bouge (pan) sur le même temps que le changement - arrivez d'abord, changez ensuite
- temps 5 (t=4.1s): 2 changements à la fois (toast, badge) - divisez ou subordonnez tous sauf un
- temps 5 (t=4.1s): changement "toast" n'a pas de traitement de lisibilité (slowdown/highlight/focuspull/countup)
Lisez-le : le clic sur l'interrupteur (temps 2-3) est propre – le curseur se stabilise, le clic a une ondulation, le basculement est ralenti et maintenu. Mais le temps 4 fait un panoramique vers la tuile métrique pendant qu'elle se met à jour, donc la caméra arrive en retard sur la récompense ; corrigez-le en faisant le panoramique pendant la tenue du temps 3 pour que la tuile soit cadrée avant qu'elle ne se recalcule. Et le temps 5 fait deux mauvaises choses à la fois : il déclenche un toast et un badge sur la même image, et le toast n'a pas de traitement de lisibilité. Subordonnez le badge (assombrissez-le ou poussez-le hors du zoom) pour que le toast soit le seul sujet, et donnez au toast une surbrillance ou une tenue. Corrigez les trois et le linter réussit.
Modèle : fiche de plan de démo
Copiez ceci, remplissez les champs FILL, et donnez le résultat au linter, puis aux skills frères.
FICHE DE PLAN DE DÉMO PRODUIT. [À REMPLIR: nom de la fonctionnalité] - [À REMPLIR: durée]s
DÉCISION DE PRODUCTION
Enregistrer / Recréer / Hybride : [À REMPLIR]
Raison : [À REMPLIR: pourquoi ce chemin]
Résolution de capture : [À REMPLIR: 2x final si enregistrement]
SUJET DU CLIP (une phrase que le spectateur doit retenir)
[À REMPLIR]
FEUILLE DE TEMPS (un changement par ligne ; la caméra arrive avant le changement)
# TEMPS CAMÉRA CADRÉ SUR CURSEUR CHANGEMENT LISIBILITÉ TENUE
1 [À REMPLIR] [push] [À REMPLIR] [se déplace vers À REMPLIR] - - [À REMPLIR]s
2 [À REMPLIR] [hold] [À REMPLIR] [se stabilise+clic] - - [À REMPLIR]s
3 [À REMPLIR] [hold] [À REMPLIR] [garé/fondu] [À REMPLIR: le basculement] [slowdown] [À REMPLIR]s
4 [À REMPLIR] [pan] [À REMPLIR] [hors cadre] [À REMPLIR: l'effet] [countup/glow] [À REMPLIR]s
(ajoutez des lignes ; jamais deux changements dans une seule ligne)
LANGAGE DES CALLOUTS (cohérent dans tout le clip)
Style de surbrillance : [À REMPLIR: anneau / projecteur-assombrissement / connecteur]
Affordance de clic : [À REMPLIR: ondulation / pression / échelle-curseur]
Traitement de mise au point : [À REMPLIR: assombrir autres / flouter autres]
TRANSMISSION
Détails d'assouplissement + timing -> motion-design-principles
Ordre des temps / arc narratif -> video-storyboard
Mots à l'écran -> kinetic-typography
Couleur + lumière des surbrillances -> motion-color-and-light
Conception sonore -> [skill de conception sonore]
[La suite du modèle est tronquée car le contenu original était tronqué.]