npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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é

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 (et titre) est un texte, comme avant, ou un objet { fr, ar, en, es, … }. L'option langues rend un film par langue (<code>.<langue>.*) en un seul tournage : à chaque moment, une image par langue. Sans langues, un seul film aux noms d'avant ; un objet y prend la langue langueDefaut (fr). Une langue absente d'un objet : la langue de repli est montrée, avec un avertissement langue.
  • 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. Format vtt, 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 (format mp4-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), et legende seule.
  • 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'option dossierFichiers de tourner. 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é par elementFromPoint) : 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) : choisir vise l'étiquette visible d'un radio caché (tuile).
  • Champ de date : saisir avec la valeur au format du champ (2030-12-01 pour 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 si tourner reçoit le même objet variables.
  • Refus attendu : "attendu": 400 sur cliquer ou aller — l'étape doit produire ce refus (400 à 499), qui se filme ; sinon le film échoue.
  • Sélecteurs : CSS (#nom, [name=prix]) ou texte=…, 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.png

Codes : 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.