Feat : Streamers page revamp
All checks were successful
release / build (push) Successful in 27s
release / verify-windows (push) Successful in 1m26s

This commit is contained in:
jeanotx32
2026-08-12 15:28:56 +02:00
parent d8846aac9a
commit 96b364bd66
15 changed files with 1625 additions and 131 deletions

View File

@@ -36,6 +36,9 @@ IP publique nécessaire, et obs-websocket reste sur `127.0.0.1`.
dédiée, dès qu'il est en direct depuis assez longtemps.
- [Presets d'enregistrement](#presets-denregistrement) appliqués à OBS depuis l'interface,
réglables VM par VM : de « Économe » à « Sans perte ».
- [Frise des diffusions](#frise-des-diffusions) : l'historique des streams de chaque profil
suivi, avec en surimpression ce qui en a été capturé — par profil sur sa fiche, ou tous
ensemble dans l'onglet « Timeline ».
## Prérequis
@@ -546,6 +549,55 @@ Le délai d'amorçage n'est pas une précaution de style : un modèle qui sort d
repasse « public » quelques secondes avant de se remettre en place. Déclencher sur la
première lecture produirait des fichiers de dix secondes.
## Frise des diffusions
Deux vues sur le même historique : la fiche d'un profil (clic sur sa vignette, onglet
**Streamers**) montre la sienne ; l'onglet **Timeline** les empile toutes, une voie par
profil.
Les diffusions publiques s'y lisent en bleu, et **les portions réellement capturées se
superposent en rouge**, sur la même piste. C'est le point de la vue : ce qui intéresse n'est
pas « quand ai-je enregistré » dans l'absolu mais quelle part de chaque diffusion a été
gardée — deux pistes séparées obligeraient l'œil à faire l'alignement lui-même. La vue
globale rend visibles les chevauchements : deux streamers en direct en même temps sur une
seule VM, et ce qui, faute de machine libre, est passé à côté.
### Ce qui est enregistré, et comment
| Table | Écrite par | Une ligne = |
| --- | --- | --- |
| `stream_sessions` | la veille, sur transition d'état | une diffusion publique observée |
| `recording_spans` | le hub, sur changement de statut d'un agent | un intervalle réellement capturé |
Deux tables et non une : un enregistrement démarre en général après le début du stream,
peut s'arrêter avant sa fin, et une même diffusion peut en compter plusieurs. Une pause OBS
(show privé) ne coupe pas l'intervalle — elle n'écrit rien mais ne ferme pas le fichier, et
la diffusion publique s'est de toute façon interrompue pendant ce temps.
Le rattachement d'une capture à un profil passe par le pseudo sur lequel la veille de l'agent
est calée — c'est `startTargetRecording()` qui l'y pose. Une capture lancée à la main depuis
l'onglet Agents, sans ce calage, reste sans profil et n'apparaît sur aucune voie.
**Une capture dont on n'a jamais vu la fin** (VM éteinte en plein enregistrement, serveur
redémarré) est refermée par un balayage périodique — à sa dernière preuve de vie, pas à
l'heure du balayage. Sans cela une VM disparue une semaine passerait pour avoir enregistré
une semaine. La colonne `last_seen_at`, réécrite à chaque statut reçu, sert exactement à ça,
et la tolérance de 60 s laisse un agent qui redémarre retrouver son intervalle plutôt que
d'en ouvrir un second.
Supprimer un profil suivi efface son historique (`ON DELETE CASCADE`) : ne plus suivre
quelqu'un, c'est aussi l'oublier.
### « Cette VM enregistre » n'est pas « ce profil est enregistré »
Plusieurs profils peuvent être assignés à la même VM, mais elle n'en capture qu'un à la
fois. L'interface distingue donc les deux, partout où un état d'enregistrement paraît :
- le profil réellement capturé porte « ⏺ enregistrement en cours » et le bouton **Arrêter** ;
- les autres profils de la même VM affichent « VM occupée : *nom du profil capturé* », avec
le bouton **Enregistrer** désactivé — ils ne sont pas enregistrés, et la fiche détaillée
l'explique en toutes lettres.
## Capture de fenêtre OBS et réutilisation
La source « capture de fenêtre » d'OBS mémorise un identifiant de fenêtre X11. Fermer la
@@ -622,7 +674,8 @@ Toutes les routes hors `/api/login` exigent `Authorization: Bearer <jeton de ses
| `GET` | `/api/agents` | Liste des agents et de leur état |
| `POST` | `/api/agents` | Provisionne un agent, renvoie son jeton **une seule fois** |
| `PATCH` | `/api/agents/:id` | Nom, notes, paramètres OBS, auto-connexion, surveillance, navigateur, preset |
| `PATCH` | `/api/watchlist/:id` | Libellé, agent assigné, notifications, automatisme |
| `PATCH` | `/api/watchlist/:id` | Libellé, agent assigné, notifications, automatisme, favori |
| `GET` | `/api/timeline?days=&targetId=` | Diffusions et captures ; sans `targetId`, tous les profils |
| `POST` | `/api/agents/:id/token` | Régénère le jeton (coupe la session en cours) |
| `DELETE` | `/api/agents/:id` | Supprime l'agent |
| `POST` | `/api/agents/:id/command` | `{ action, params }`, attend le résultat de l'agent |