Vidéo commentée
Transformez « explique cette fonctionnalité » en un court MP4 : l'application réelle à l'écran, une voix qui explique, des sous-titres, un curseur qui se déplace comme une personne, et un anneau autour de ce dont on parle. L'utilisateur briefe et valide. Vous faites tout le reste.
Le travail a une porte de validation plus importante que toute autre : l'utilisateur approuve le récit avant que quoi que ce soit ne soit enregistré. Un changement de formulation coûte quelques secondes sur un script et quelques minutes sur une vidéo, et une affirmation erronée est bien moins chère à corriger sur papier.
Ce dont vous avez besoin
- Le code source de l'application, et une instance que vous pouvez ouvrir et dans laquelle vous connecter (locale ou un environnement de dev/staging). N'enregistrez jamais sur la production : la prise clique sur de vrais boutons.
- Playwright dans le projet de l'application (
node_modules/playwrightou@playwright/test). La plupart des projets avec des tests E2E l'ont déjà. Sinon :npm i -D playwright && npx playwright install chromium. ffmpegetpython3dans le PATH.- Une clé de synthèse vocale pour la voix finale (Murf ou ElevenLabs). Sans une,
--provider sayutilise la voix macOS, ce qui est acceptable pour une version préliminaire. Voirreferences/voices.md.
Vérifiez d'abord ces prérequis et dites clairement ce qui manque. Ne demandez pas à l'utilisateur de coller une clé API dans le chat : demandez-lui de la mettre dans une variable d'environnement ou un fichier ignoré par git et dites-lui où.
Le workflow
1. Prendre le brief
Vous avez besoin de quatre choses. Ne demandez que ce que la demande ne dit pas déjà.
- Objectif et public. « Se mettre d'accord avec le CTO sur la nouvelle page des autorisations » produit une vidéo différente de « apprendre aux nouveaux membres à publier une application ». Le public détermine la longueur, le vocabulaire et le niveau d'explication.
- Le flux. Ce qu'il faut montrer, dans l'ordre. Si l'utilisateur en donne un, améliorez-le et dites ce que vous avez changé et pourquoi : un meilleur ordre, une étape manquante, une étape qui n'apporte rien. Ils ont demandé une vidéo, pas une transcription de leur liste.
- Durée. Par défaut 60-120 secondes et un seul sujet. Si le flux nécessite plus, proposez deux vidéos.
- Voix. Fournisseur et voix, s'ils ont une préférence. Sinon, utilisez les valeurs par défaut.
2. Parcourir le flux dans l'application réelle avant d'écrire un mot
Exécutez l'application, connectez-vous avec un compte de démonstration, et effectuez chaque étape du flux vous-même avec Playwright ou le navigateur. Vous vérifiez que chaque chose que la narration va affirmer est vraie.
C'est là que réside l'essentiel de la valeur de cette compétence. Les fonctionnalités sont souvent décrites de mémoire ou à partir du cahier des charges, et l'application fait quelque chose de légèrement différent. Si l'application ne fait pas ce que l'utilisateur dit qu'elle fait, arrêtez-vous et dites-lui ce que vous avez observé. N'écrivez pas une narration qui masque le problème et ne passez pas l'étape sous silence.
Notez les libellés exacts des boutons et des menus pendant que vous y êtes. La narration doit utiliser les mots qui sont à l'écran.
3. Amorcer les données de démonstration
Une présentation sur un compte vide ou à moitié cassé ressemble à un rapport de bug. Créez ce dont l'histoire a besoin : une organisation, quelques utilisateurs avec des rôles différents, des éléments avec des noms crédibles. Utilisez uniquement des noms inventés (Acme, Northwind, example.com) : ces vidéos sont partagées.
Gardez une liste de tout ce que vous créez ou modifiez. Vous remettrez les choses en état à l'étape 9.
4. Écrire le récit, puis s'arrêter pour validation
Écrivez-le sous forme de tableau et enregistrez-le à côté de l'endroit où la vidéo ira, sous le nom <nn>-<slug>.script.md :
| # | À l'écran | Voix off | ~sec |
|---|---|---|---|
| 1 | Liste de tâches au repos. Anneau sur la liste. | Voici la liste de tâches de l'équipe. / Tous les membres de l'équipe voient les mêmes tâches. | 5 |
| 2 | Curseur vers **Ajouter une tâche**, le formulaire s'ouvre. Tapez un nom, cliquez sur **Enregistrer la tâche**. | Pour en ajouter une, sélectionnez Ajouter une tâche, / donnez-lui un nom, / et enregistrez. | 7 |
Le / marque la séparation des lignes de sous-titres d'une scène. Lisez references/narrative.md avant d'écrire : cela couvre le rythme, la longueur des lignes, les cartes avant/après et les erreurs qui rendent ces vidéos difficiles à suivre.
Montrez le tableau à l'utilisateur et attendez. Dites la durée totale prévue. Si vous avez modifié son flux, dites-le ici. Ne continuez que lorsqu'il approuve ; s'il demande des modifications, renvoyez le tableau révisé.
5. Générer la voix
Écrivez la narration approuvée dans scenes.json, une entrée par ligne, avec les lignes séparées aux marques / :
[{ "id": "02", "lines": ["Pour en ajouter une, sélectionnez Ajouter une tâche,", "donnez-lui un nom,", "et enregistrez."] }]
python3 scripts/tts.py scenes.json --audio-dir work/audio --provider murf
Ceci écrit un clip par scène et durations.json. La voix vient avant l'enregistrement intentionnellement : chaque scène est maintenue à l'écran pendant la durée de son clip, donc les longueurs des clips doivent exister en premier. Une ré-exécution ne régénère que les scènes dont le texte a changé.
6. Écrire le script d'enregistrement et le tester à sec
Copiez example/record.cjs et réécrivez ses scènes pour ce flux. scripts/walkthrough.cjs vous donne :
| Aide | Utilisation |
|---|---|
scene(id, async () => {...}) | Une scène commentée. Affiche ses sous-titres et attend que la voix ait fini. |
clickAt(locator) | Glissez le curseur vers l'élément, montrez la pression, cliquez. Utilisez ceci, pas locator.click(), sinon les choses se produisent sans cause visible. |
moveTo(locator) | Pointez sur quelque chose sans cliquer. |
typeInto(locator, text) | Cliquez sur un champ et tapez à une vitesse lisible. |
ring(locator) / ring(null) | Surlignez ce dont la voix parle ; retirez-le quand la voix passe à autre chose. |
step('Étape 2 sur 4 · Enregistrer') | L'étiquette en bas à gauche qui indique au spectateur où il se trouve. |
card({ title, subtitle }) | Carte titre plein écran, pour la scène de fin. |
card({ before, after }) | Comparaison avant/après. card(null) la masque. |
login: async (page) => {...} | Option de record(). Se connecte hors caméra pour que la vidéo commence là où l'histoire commence. |
Privilégiez les localisateurs par rôle et étiquette (getByRole, getByLabel) plutôt que CSS : ils survivent au restyling et ce sont les noms qu'utilise la narration. Lisez les noms à l'écran à l'exécution lorsque les données peuvent différer entre les environnements.
Exécutez-le d'abord avec dry :
node record.cjs <app-repo> work/rec work/audio/durations.json dry
Un test à sec n'enregistre rien et n'attend pas la voix, donc un mauvais sélecteur coûte des secondes, pas une prise complète. Corrigez jusqu'à ce que chaque scène s'exécute.
7. Enregistrer et assembler
node record.cjs <app-repo> work/rec work/audio/durations.json
python3 scripts/mux.py --rec work/rec --audio-dir work/audio --output walkthrough-videos/<nn>-<slug>.mp4
L'enregistreur affiche la durée du clip de chaque scène à côté du temps qu'ont pris ses actions. Une scène marquée avec des secondes de silence après la voix a trop d'actions pour ce qui est dit : réduisez les actions ou donnez plus à dire à la voix.
mux.py écrit le MP4, un fichier .srt correspondant et <name>.sheet.jpg.
8. Vérifiez vous-même avant l'utilisateur
Ouvrez la feuille de contact : une image par scène. Cherchez un anneau sur le mauvais élément ou absent, un sous-titre couvrant ce qui est discuté, une scène sur le mauvais écran, un badge d'outils de développement ou un toast d'erreur dans le champ, des données personnelles réelles. Extrayez des images individuelles avec ffmpeg lorsque la feuille est trop petite pour distinguer.
Remettez ensuite la vidéo avec : sa durée, ce qui a changé par rapport au récit approuvé si quelque chose a changé, et tout ce que vous n'avez pas pu vérifier.
Quand l'utilisateur demande des modifications, revenez d'abord au récit. Révisez le tableau, montrez-le, obtenez l'accord, puis ne régénérez que ce qui a changé. La plupart des retours (« trop rapide », « j'ai perdu le fil de ce qui a changé », « mentionne aussi le filtre ») concernent le script, et les corriger dans l'enregistrement seul produit une vidéo qui ne correspond plus à son script.
9. Remettre les choses en état
Annulez ce que la prise a changé, en utilisant la liste de l'étape 3 et tout ce que l'enregistrement lui-même a cliqué : paramètres modifiés, éléments créés ou supprimés, état des comptes de démonstration. Puis dites à l'utilisateur ce qui est restauré et ce que vous avez délibérément laissé (des données d'amorçage qu'il pourrait vouloir pour la prochaine vidéo, par exemple). Si quelque chose ne peut pas être annulé, dites-le.
Fichiers
Les livrables vont ensemble dans un endroit que l'utilisateur peut trouver, par défaut walkthrough-videos/ dans le projet :
walkthrough-videos/
03-add-a-task.mp4
03-add-a-task.srt
03-add-a-task.script.md
Gardez les fichiers de travail (scenes.json, audio, enregistrement brut, le script d'enregistrement) en dehors du dépôt ou dans un dossier ignoré par git. Ils sont volumineux et le script d'enregistrement contient des sélecteurs pour un moment précis dans la vie de l'application. Le script et le .srt valent la peine d'être conservés : ils font de la prochaine révision une petite modification.
Les choses qui tournent mal
- Les contrôles natifs ne s'enregistrent pas. Un menu déroulant
<select>natif, un sélecteur de fichier ou une boîte de dialogue de navigateur est dessiné par le navigateur en dehors de la page. Pointez sur le contrôle avecmoveTo, définissez la valeur avecselectOption/setInputFiles, et laissez la narration dire ce qui a été choisi. - La superposition disparaît après la navigation. Elle est recréée à chaque chargement de page et l'étape en cours ainsi que le sous-titre sont restaurés. Si une page remplace
document.bodyen totalité, appelezstep()à nouveau après qu'elle se soit stabilisée. - Une scène commence avant que la page soit prête. Attendez que l'élément dont la scène parle soit prêt (
await locator.waitFor()) avant d'appelerscene(), pas à l'intérieur, afin que le temps de chargement ne soit pas commenté. - Les premières secondes sont une page blanche.
mux.pycoupe tout ce qui précède la première scène. Effectuez la navigation et l'attente avantscene('01'). - Connexion en caméra. Utilisez l'option
login. Personne n'a besoin de regarder un champ de mot de passe, et les identifiants ne doivent pas être visibles dans une vidéo partagée.