Feat : pause now showing in another color
All checks were successful
release / build (push) Successful in 28s
release / verify-windows (push) Successful in 1m27s

This commit is contained in:
jeanotx32
2026-08-13 14:42:14 -04:00
parent 830b27470c
commit b45ad4bca3
9 changed files with 244 additions and 29 deletions

View File

@@ -813,8 +813,9 @@ Deux vues sur le même historique : la fiche d'un profil (clic sur sa vignette,
**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
Les diffusions publiques s'y lisent en bleu, **les portions capturées se superposent en
rouge**, et **les passages en pause en jaune** par-dessus le rouge — la capture tournait, mais
n'écrivait rien. Le tout 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
@@ -854,12 +855,26 @@ une fois écrit, il est servi avec un cache immuable.
| 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é |
| `recording_spans` | le hub, sur changement de statut d'un agent | un intervalle de capture ouvert |
| `recording_pauses` | le hub, sur changement de statut d'un agent | une pause à l'intérieur d'un intervalle |
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.
Plusieurs 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é, flux hors-ligne) ne coupe pas l'intervalle** — elle n'écrit rien
mais ne ferme pas le fichier. La découper en deux intervalles ferait passer les morceaux pour
deux captures distinctes, alors qu'il n'y en a qu'une, et qu'un seul fichier. Elle est donc
relevée à part, **en surimpression**, et apparaît en jaune par-dessus le rouge de la capture :
la barre se lit d'un coup d'œil comme « la capture tournait ici, mais n'écrivait rien ». Les
totaux annoncés déduisent ces pauses — les y inclure surestimerait ce qui est réellement
dans le fichier.
Deux invariants tiennent ce relevé : les ouvertures et fermetures de pause sont **idempotentes**
(le hub les rejoue à chaque cycle de statut, toutes les 2 s, et elles n'agissent qu'aux
transitions), et **aucune pause ne survit à l'intervalle qui la porte**. Ce second point est
réparé après coup plutôt que supposé : une VM disparue en pleine pause voit son intervalle
refermé par le balayage périodique, sans passer par le chemin qui referme les pauses — sans
cette réparation, la frise resterait jaune jusqu'à maintenant.
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
@@ -966,7 +981,7 @@ Toutes les routes hors `/api/login` exigent `Authorization: Bearer <jeton de ses
| `POST` | `/api/tags` | Crée l'étiquette, ou renvoie celle qui porte déjà ce nom |
| `PATCH` | `/api/tags/:id` | Renomme (409 si le nom est déjà pris) |
| `DELETE` | `/api/tags/:id` | Supprime, et la retire de tous les profils |
| `GET` | `/api/timeline?days=&targetId=` | Diffusions et captures ; sans `targetId`, tous les profils |
| `GET` | `/api/timeline?days=&targetId=` | Diffusions, captures et pauses ; sans `targetId`, tous les profils |
| `GET` | `/api/timeline/sessions/:id/preview` | Vignette conservée d'une diffusion (jeton accepté en query) |
| `POST` | `/api/agents/:id/token` | Régénère le jeton (coupe la session en cours) |
| `DELETE` | `/api/agents/:id` | Supprime l'agent |