REVAMP : Firefox handling
This commit is contained in:
130
README.md
130
README.md
@@ -42,8 +42,9 @@ IP publique nécessaire, et obs-websocket reste sur `127.0.0.1`.
|
||||
- Node.js **22+** sur le serveur et sur chaque VM (le serveur utilise `node:sqlite`).
|
||||
- OBS **28+** sur chaque VM, avec *Outils → Paramètres du serveur WebSocket* activé.
|
||||
Note le port (4455 par défaut) et le mot de passe.
|
||||
- Pour le rappel du plein écran sous Ubuntu : `xdotool` et une session X11
|
||||
(voir [Prérequis pour le rappel du plein écran](#prérequis-pour-le-rappel-du-plein-écran)).
|
||||
- Pour le rappel du plein écran sous Ubuntu : Firefox, en mode de pilotage « WebDriver BiDi »
|
||||
(voir [Deux façons de piloter le navigateur](#deux-façons-de-piloter-le-navigateur)).
|
||||
Le mode historique exige en plus `xdotool` et une session X11.
|
||||
|
||||
## Démarrage rapide (développement)
|
||||
|
||||
@@ -157,9 +158,75 @@ moment coûte plus cher que quelques secondes d'écran d'attente enregistrées :
|
||||
Un passage `hors-ligne` (`idle`) ne provoque ni pause ni reprise : seul le retour effectif
|
||||
du flux public relance l'enregistrement.
|
||||
|
||||
### Prérequis pour le rappel du plein écran
|
||||
### Deux façons de piloter le navigateur
|
||||
|
||||
L'envoi de touche se fait au niveau du système, pas via OBS.
|
||||
Le rappel du plein écran dépend entièrement de ce choix, qui se règle par agent dans
|
||||
« Pilotage du navigateur ».
|
||||
|
||||
| | **WebDriver BiDi** (recommandé) | **Lancement simple** (historique) |
|
||||
| --- | --- | --- |
|
||||
| Ouverture d'une page | commande dans l'instance pilotée | un processus lancé par page |
|
||||
| Plein écran | commande WebDriver adressée à Firefox | touche envoyée au serveur d'affichage |
|
||||
| Effet vérifié ? | oui — `document.fullscreenElement` est relu | non |
|
||||
| Session Wayland | **fonctionne** | impossible (voir plus bas) |
|
||||
| Dépendances | Firefox | xdotool + session X11 |
|
||||
|
||||
#### WebDriver BiDi
|
||||
|
||||
Firefox expose ce protocole dès qu'on le lance avec `--remote-debugging-port` : ni
|
||||
geckodriver, ni Selenium, une simple WebSocket JSON sur la boucle locale. L'agent
|
||||
implémente le strict nécessaire (`bidi.ts`, `firefox.ts`).
|
||||
|
||||
Le renversement est là : **l'agent possède le navigateur** au lieu de lui envoyer des URL
|
||||
en espérant. Il parle à Firefox, pas au serveur d'affichage — d'où le fonctionnement
|
||||
identique sous Wayland, où xdotool ne voit rien.
|
||||
|
||||
Séquence du rappel de plein écran, dans cet ordre volontaire :
|
||||
|
||||
1. `browsingContext.activate` — sans quoi la touche partirait vers un onglet d'arrière-plan ;
|
||||
2. `input.performActions` — la touche configurée (`f` par défaut), délivrée à la page comme
|
||||
un vrai évènement (`isTrusted: true`), donc traitée par le lecteur du site ;
|
||||
3. relecture de `document.fullscreenElement` ;
|
||||
4. si la page n'a pas bougé : `requestFullscreen()` sur l'élément `<video>`, avec
|
||||
`userActivation` ;
|
||||
5. relecture, et verdict rapporté dans l'historique de la VM.
|
||||
|
||||
**Un profil Firefox dédié est obligatoire**, pas cosmétique : le port de pilotage ne
|
||||
s'ouvre qu'au démarrage du processus, et deux instances ne peuvent pas partager un profil.
|
||||
L'agent en gère un sous `~/.stream-control/firefox-profile` et y réécrit un `user.js` à
|
||||
chaque lancement — chaque préférence y supprime quelque chose qui finirait dans le fichier
|
||||
enregistré, ou qui empêcherait un démarrage sans surveillance :
|
||||
|
||||
| Préférence | Pourquoi |
|
||||
| --- | --- |
|
||||
| `full-screen-api.warning.timeout = 0` | le bandeau « … est maintenant en plein écran » se retrouvait dans les premières secondes de chaque fichier |
|
||||
| `media.autoplay.default = 0` | sans lecture automatique, l'agent enregistre une image fixe sans que rien ne le signale |
|
||||
| `browser.aboutwelcome.enabled = false`, `browser.startup.page = 0`, … | tout onglet d'accueil passerait devant la page du streamer |
|
||||
| `browser.sessionstore.resume_from_crash = false` | un dialogue modal bloquerait toute commande |
|
||||
| `app.update.auto = false` | une mise à jour fermerait la fenêtre que capture OBS, en plein enregistrement |
|
||||
|
||||
**Au premier passage en BiDi, une nouvelle fenêtre Firefox s'ouvre** : pointe la source
|
||||
« capture de fenêtre » d'OBS dessus une fois. Ensuite elle survit aux enregistrements
|
||||
comme aux redémarrages de l'agent — le processus est lancé détaché, et l'agent se
|
||||
rattache au port plutôt que de relancer.
|
||||
|
||||
#### Si le plein écran est refusé
|
||||
|
||||
Firefox refuse le plein écran à un document **dont la fenêtre n'a pas le focus**. C'est la
|
||||
première cause d'échec sur une VM : il suffit qu'OBS ou un terminal l'ait pris. L'agent
|
||||
relit alors trois conditions depuis la page et nomme celle qui manque, plutôt que de
|
||||
répercuter un « Fullscreen request denied » qui ne dit rien :
|
||||
|
||||
| Message | Cause |
|
||||
| --- | --- |
|
||||
| `la fenêtre Firefox n'a pas le focus` | une autre fenêtre est active dans la session |
|
||||
| `aucun élément vidéo dans la page` | le lecteur n'a pas fini de charger — augmente le délai avant plein écran |
|
||||
| `l'API plein écran est désactivée dans ce profil` | `full-screen-api.enabled` forcé à faux |
|
||||
|
||||
#### Lancement simple
|
||||
|
||||
Conservé comme défaut pour ne pas changer le comportement d'un agent existant à la mise à
|
||||
jour. L'envoi de touche se fait au niveau du système, pas via OBS.
|
||||
|
||||
| OS | Mécanisme | À prévoir |
|
||||
| --- | --- | --- |
|
||||
@@ -168,13 +235,8 @@ L'envoi de touche se fait au niveau du système, pas via OBS.
|
||||
| Windows | `SetForegroundWindow` + `SendKeys` | L'agent doit tourner dans la session interactive — d'où la tâche planifiée plutôt qu'un service |
|
||||
| macOS | AppleScript System Events | Autorisation Accessibilité (prévu pour le développement) |
|
||||
|
||||
Dans les deux cas la fenêtre du lecteur passe **au premier plan** : les navigateurs
|
||||
ignorent les évènements clavier synthétiques envoyés sans focus (`XSendEvent`). Sans
|
||||
conséquence sur une VM d'enregistrement dédiée, gênant si quelqu'un s'en sert en même
|
||||
temps.
|
||||
|
||||
Le bouton ⛶ sur la fiche de l'agent renvoie la touche à la demande, et ⟳ force une sonde
|
||||
immédiate — les deux servent à valider le titre de fenêtre sans attendre un vrai show privé.
|
||||
La fenêtre du lecteur passe **au premier plan** : les navigateurs ignorent les évènements
|
||||
clavier synthétiques envoyés sans focus (`XSendEvent`).
|
||||
|
||||
Le **titre de fenêtre** à renseigner est celui de la fenêtre, pas le nom du processus. Sous
|
||||
Firefox il vaut `<titre de la page> — Mozilla Firefox`, et le titre d'une page Stripchat se
|
||||
@@ -182,9 +244,6 @@ termine par `| Stripchat` : `Stripchat` comme `Firefox` conviennent donc. En cas
|
||||
l'agent liste les fenêtres qu'il voit réellement, et `agent.cjs --check` fait de même sans
|
||||
rien déclencher.
|
||||
|
||||
Trois causes distinctes produisaient autrefois le même message « aucune fenêtre ne
|
||||
correspond » ; elles sont maintenant séparées :
|
||||
|
||||
| Symptôme | Cause |
|
||||
| --- | --- |
|
||||
| `Authorization required` / `Invalid MIT-MAGIC-COOKIE-1 key` | cookie X introuvable ou périmé |
|
||||
@@ -192,6 +251,9 @@ correspond » ; elles sont maintenant séparées :
|
||||
| `Aucune fenêtre visible sur DISPLAY=:0` | navigateur lancé hors de la session de l'agent |
|
||||
| Liste des fenêtres ouvertes | titre mal renseigné — recopier un fragment de la liste |
|
||||
|
||||
Le bouton ⛶ sur la fiche de l'agent renvoie la touche à la demande, et ⟳ force une sonde
|
||||
immédiate.
|
||||
|
||||
### Wayland
|
||||
|
||||
Ubuntu démarre en session Wayland par défaut, et Firefox y tourne en client Wayland natif.
|
||||
@@ -199,18 +261,14 @@ Une telle fenêtre est **invisible à xdotool** : ni activation, ni envoi de tou
|
||||
symptôme est net — côté X11, seule `mutter guard window` apparaît, la fenêtre technique du
|
||||
compositeur. L'agent reconnaît cette signature et le dit explicitement.
|
||||
|
||||
Deux issues :
|
||||
**La réponse est le mode WebDriver BiDi**, qui ne passe pas par le serveur d'affichage.
|
||||
|
||||
- **Rester en Wayland, passer Firefox sous XWayland.** L'agent pose `MOZ_ENABLE_WAYLAND=0`
|
||||
en lançant le navigateur, ce qui suffit — *à condition qu'aucune instance Firefox ne
|
||||
tourne déjà*. Firefox délègue l'URL à l'instance existante, qui garde ses propres
|
||||
variables d'environnement : ferme toutes ses fenêtres avant de lancer la capture.
|
||||
- **Ouvrir une session Xorg.** Sur l'écran de connexion GDM, roue dentée en bas à droite →
|
||||
« Ubuntu sur Xorg ». Tout redevient pilotable, y compris une fenêtre ouverte à la main.
|
||||
Les contournements d'avant sont conservés ici pour mémoire, mais ils coûtent tous quelque
|
||||
chose et aucun n'est à préférer :
|
||||
|
||||
Si le rappel du plein écran s'avère fragile sur ta VM, l'alternative sans clavier est de
|
||||
lancer le navigateur en mode kiosque (`chromium --kiosk`) : il n'y a alors plus de plein
|
||||
écran à restaurer.
|
||||
- forcer Firefox sous XWayland (`MOZ_ENABLE_WAYLAND=0`) ajoute une copie d'image par trame ;
|
||||
- basculer la session en Xorg fait chuter les performances de capture (voir
|
||||
« Xorg, Wayland et le coût de la capture »).
|
||||
|
||||
## Presets d'enregistrement
|
||||
|
||||
@@ -271,8 +329,9 @@ Sur une VM sans accélération 3D, la méthode de capture pèse lourd :
|
||||
- **Xorg** : la capture d'écran XSHM recopie tout le tampon à chaque image. La capture de
|
||||
fenêtre XComposite est nettement plus économe — à préférer systématiquement.
|
||||
|
||||
Xorg n'est nécessaire que pour le rappel du plein écran par xdotool. Si le cadrage se fait
|
||||
côté OBS, Wayland est le meilleur choix en performance.
|
||||
Xorg n'était nécessaire que pour le rappel du plein écran par xdotool. Le mode de pilotage
|
||||
« WebDriver BiDi » supprime cette contrainte : **Wayland est le bon choix**, en performance
|
||||
comme en simplicité.
|
||||
|
||||
Un preset trop lourd pour la VM fait chuter les images par seconde : la qualité perçue
|
||||
baisse alors malgré un meilleur CRF. Après un changement, surveille « FPS » et les deux
|
||||
@@ -369,7 +428,12 @@ La source « capture de fenêtre » d'OBS mémorise un identifiant de fenêtre X
|
||||
fenêtre du navigateur, ou en ouvrir une nouvelle, invalide cet identifiant : la source
|
||||
devient noire et il faut la repointer à la main.
|
||||
|
||||
L'agent évite donc les deux :
|
||||
En mode **WebDriver BiDi** le problème disparaît : l'agent ne relance jamais de processus,
|
||||
il navigue dans l'onglet qu'il pilote. La fenêtre est ouverte une fois et survit à tout,
|
||||
y compris à un redémarrage de l'agent — celui-ci se rattache au port au lieu de relancer.
|
||||
La seule fois où il faut repointer la source OBS est le passage initial en BiDi.
|
||||
|
||||
En mode **lancement simple**, l'agent évite les deux pièges :
|
||||
|
||||
- **aucun argument** par défaut (`--new-window` est proscrit) : Firefox confie l'URL à la
|
||||
fenêtre déjà ouverte ;
|
||||
@@ -381,8 +445,10 @@ arguments ou leur comportement d'arrêt ont été personnalisés.
|
||||
|
||||
### « Firefox est déjà ouvert »
|
||||
|
||||
Ce dialogue signifie que le processus lancé par l'agent n'a pas trouvé l'instance déjà en
|
||||
cours : il bute alors sur le verrou de profil au lieu de lui confier l'URL.
|
||||
Propre au mode **lancement simple** : ce dialogue signifie que le processus lancé par
|
||||
l'agent n'a pas trouvé l'instance déjà en cours, et bute sur le verrou de profil au lieu de
|
||||
lui confier l'URL. Le mode BiDi ne peut pas le rencontrer — il n'y a qu'une instance, sur
|
||||
un profil qui n'appartient qu'à l'agent.
|
||||
|
||||
Le passage de relais se fait par le **bus de session D-Bus** — le seul mécanisme disponible
|
||||
sous Wayland, le protocole X de remoting n'y existant pas. Or un service systemd « system »
|
||||
@@ -395,13 +461,17 @@ n'hérite pas de ce bus, pas plus qu'il n'hérite du cookie X. L'agent résout d
|
||||
| `XAUTHORITY` | `$XAUTHORITY` s'il existe, puis GDM, Xwayland, `~/.Xauthority` |
|
||||
| `XDG_RUNTIME_DIR` | valeur héritée, sinon `/run/user/<uid>` |
|
||||
| `DBUS_SESSION_BUS_ADDRESS` | valeur héritée, sinon la socket `$XDG_RUNTIME_DIR/bus` |
|
||||
| `WAYLAND_DISPLAY` | valeur héritée, sinon la socket `wayland-<n>` du répertoire d'exécution |
|
||||
|
||||
`agent.cjs --check` affiche les quatre. Si le bus ressort en avertissement, vérifie que
|
||||
`agent.cjs --check` les affiche toutes. Si le bus ressort en avertissement, vérifie que
|
||||
l'agent tourne bien sous **le même compte** que la session graphique : l'utilisateur est
|
||||
choisi par `--user` à l'installation.
|
||||
|
||||
### Éviter l'accumulation d'onglets
|
||||
|
||||
Propre lui aussi au mode **lancement simple** ; en BiDi l'agent navigue toujours dans le
|
||||
même onglet.
|
||||
|
||||
Avec les réglages d'usine de Firefox, un lien venu de l'extérieur ouvre un **nouvel
|
||||
onglet** : chaque cycle d'enregistrement en laisse donc derrière lui, et les anciens
|
||||
continuent de décoder leur page. Sur une VM d'enregistrement, règle une fois pour toutes
|
||||
|
||||
Reference in New Issue
Block a user