@mostajs/geste-film
v0.3.0
Published
Filmer un geste d'utilisation d'une application web : un scénario déclaratif par ligne de formation, Chrome piloté sur tube DevTools (sans dépendance), pointeur et légende, MP4, GIF et affiche par ffmpeg, sous-titres WebVTT, un film par langue, film parlé
Maintainers
Readme
@mostajs/geste-film
Auteur : Dr Hamid MADANI [email protected] · Licence AGPL-3.0-or-later · Niveau N1 · aucune dépendance à l'exécution
Filmer un geste d'utilisation d'une application web : une ligne de fiche de formation = un scénario JSON = un film.
Chrome sans écran est piloté par son protocole DevTools sur tube (--remote-debugging-pipe, ni WebSocket ni
bibliothèque) ; ffmpeg assemble les images en MP4, GIF et affiche. Programmes requis : google-chrome ou chromium, ffmpeg.
{ "format": "geste-film/1", "code": "EX-A1", "titre": "Renommer l’agence et enregistrer",
"adresse": "http://exemple.banc.test/",
"etapes": [
{ "legende": "Les réglages de l’agence" },
{ "saisir": "#nom", "valeur": "Agence d’Oran centre", "legende": "Changer le nom" },
{ "cliquer": "texte=Enregistrer", "legende": "« Enregistrer »" },
{ "attendre": "texte=Enregistré", "legende": "Le réglage est enregistré" }
] }import { tourner, verifierScenario } from '@mostajs/geste-film';
const bilan = await tourner(scenarios, { sortie: 'films', regles: 'MAP *.banc.test 127.0.0.1:5555', journal: console.log });
// films/EX-A1.mp4, films/EX-A1.gif, films/EX-A1.png (affiche), films/EX-A1.vtt (sous-titres, 0.3.0),
// films/films.json (bilan geste-film-bilan/1)Langues, sous-titres et narration (0.3.0)
{ "saisir": "#nom", "valeur": "Agence d’Oran centre",
"legende": { "fr": "Changer le nom", "ar": "تغيير الاسم", "en": "Change the name", "es": "Cambiar el nombre" } }import { creerVoix } from '@mostajs/voix'; // ou tout objet { dire({ texte, langue }) → { fichier, dureeMs } }
const bilan = await tourner(scenarios, { sortie: 'films', langues: ['fr', 'ar'], narrateur: creerVoix({ /* … */ }) });
// films/EX-A1.fr.mp4 .fr.gif .fr.png .fr.vtt — le film muet, référence de la recette
// films/EX-A1.fr.voix.mp4 .fr.voix.vtt — le film parlé, pour la formation
// films/EX-A1.ar.* — idem en arabe (bandeau de droite à gauche)- Légende par langue :
legende(ettitre) est un texte, comme avant, ou un objet{ fr, ar, en, es, … }. L'optionlanguesrend un film par langue (<code>.<langue>.*) en un seul tournage : à chaque moment, une image par langue. Sanslangues, un seul film aux noms d'avant ; un objet y prend la languelangueDefaut(fr). Une langue absente d'un objet : la langue de repli est montrée, avec un avertissementlangue. - Sous-titres WebVTT (
<code>[.<langue>].vtt) : une réplique par suite d'images de même légende, minutée par les durées réelles des images. Formatvtt, produit par défaut. Le bandeau incrusté reste ;legendeIncrustee: false(--sans-bandeau) le retire des images, les sous-titres restent. - Narration par un port injecté
narrateur(aucune synthèse vocale dans ce module ; même forme que@mostajs/voix) :dire({ texte, langue }) → Promise<{ fichier (wav), dureeMs }>. Chaque légende est dite une fois ; la suite d'images qui la porte est tenue au moins la durée de sa narration (+margeVoixMs, 300 ms) ; ffmpeg pose les voix sur un film à part,<code>[.<langue>].voix.mp4(formatmp4-voix, ajouté par défaut quand un narrateur est donné), avec ses sous-titres<code>[.<langue>].voix.vtt. Le film muet reste produit, à sa durée d'avant. Narrateur en panne :E_VOIX(le film muet est déjà là).
geste-film verifier scenarios/ # validation seule, sans Chrome
geste-film tourner scenarios/ --sortie films --regles "MAP *.banc.test 127.0.0.1:5555" # code 1 s'il y a un échec- Actions :
aller,cliquer,saisir+valeur,choisir+valeur,cocher,attendre,montrer,defiler,retenir+valeur(+motif),joindre+fichier(0.2.0,fichier: 0.3.0),position(0.3.0), etlegendeseule. - Joindre un fichier :
{ "joindre": "[name=piece]", "fichier": "fixtures/recu.png" }(ou"valeur", comme en 0.2.0) pose le fichier dans le champ (DOM.setFileInputFiles), même caché sous une étiquette habillée ; un chemin relatif part de l'optiondossierFichiersdetourner. Fichier absent :E_FICHIER. - Position (0.3.0) :
{ "position": { "lat": 35.6971, "lon": -0.6308, "precision": 25 } }accorde la géolocalisation au navigateur et fixe la position de l'onglet (Emulation.setGeolocationOverride, précision 10 m par défaut). Une image seulement si l'étape porte sa légende. La page doit être dans un contexte sûr (https, ou localhost). - Clic (0.3.0) : le clic vise le centre du premier rectangle de l'élément qui le touche vraiment (
getClientRects, vérifié parelementFromPoint) : un lien replié sur deux lignes est cliqué sur le lien, non entre les lignes. Un élément sur une ligne est cliqué au même point qu'avant. - Bouton radio caché (0.2.0) :
choisirvise l'étiquette visible d'un radio caché (tuile). - Champ de date :
saisiravec la valeur au format du champ (2030-12-01pour une date). - Valeur retenue :
{ "retenir": "#numero", "valeur": "colis", "motif": "GW[0-9]+" }lit un code tiré par l'application ;{{colis}}le remet dans une étape suivante (sélecteur, valeur, adresse, légende), même dans un autre film sitournerreçoit le même objetvariables. - Refus attendu :
"attendu": 400surcliqueroualler— l'étape doit produire ce refus (400 à 499), qui se filme ; sinon le film échoue. - Sélecteurs : CSS (
#nom,[name=prix]) outexte=…, le libellé visible que la fiche cite entre « ». - Marques : rond rouge sur l'élément visé, cadre, bandeau de légende, code de la ligne en coin. Elles sont posées par le CSSOM, sans jamais lever la CSP de la page, et retirées après chaque prise de vue.
- Images à des moments choisis, jamais un flux : deux tournages du même scénario donnent les mêmes images (T-GFM-10).
- Bilan
films.json: statut, fichiers, images, durée, octets, empreinte SHA-256 du scénario, avertissements (CSP, exceptions).
Un échec qui renseigne
Quand une étape échoue, seule sa ligne s'arrête ; la série continue. La ligne dit le code, l'étape, l'action, le sélecteur,
l'adresse, et montre la page (<code>-echec.png) :
✗ EX-A2, étape 2 sur 2 (cliquer « texte=Publier ce service ») : introuvable après 5 s
sur http://exemple.banc.test/ ; capture : EX-A2-echec.pngCodes : E_INTROUVABLE, E_HTTP, E_INACTIF, E_SCENARIO, E_CHROME, E_FFMPEG, E_STRICT, E_FICHIER (0.2.0),
E_VOIX (0.3.0). Une option fausse (langues, langueDefaut, narrateur) lève E_OPTION avant tout tournage.
Compatibilité 0.3.0
Un scénario d'avant 0.3.0 garde son empreinte, ses images, son MP4 et son GIF, octet pour octet ; seul s'ajoute
<code>.vtt (format vtt par défaut ; formats: ['mp4', 'gif'] le retire).
Exemple et essais
node examples/run.mjs : un petit serveur sous CSP stricte (examples/formulaire/) ; EX-A1 est filmé (7 images,
MP4 d'environ 26 ko, GIF d'environ 32 ko), EX-A2 finit en E_INTROUVABLE.
npm test : 15 essais unitaires sans Chrome (T-GFM-1 à 3, 13, 16, 21 à 30) et 20 essais avec Chrome et ffmpeg
(T-GFM-4 à 12, 14, 15, 17 à 20, 31 à 35), puis l'exemple.
Le module ne crée aucune session et ne sème aucune donnée : l'application filme son banc, sur des données fictives.
SBOM : sbom.cyclonedx.json.
