Sonde de presence video : la camera muette devient un evenement capteur

Le domaine connaissait deja CAMERA_OFFLINE, classe CRITICAL, mais rien ne
l'emettait. CameraLivenessProbe interroge l'API du serveur media et comble
ce trou.

Elle passe par le meme port IngestSensorEventUseCase que l'endpoint REST
et le simulateur : trois producteurs de natures tres differentes, un seul
contrat d'entree, et le meme trajet Kafka -> agregat ensuite. Si l'alarme
est desarmee, une coupure video ne reveille personne - c'est l'agregat qui
tranche, pas la sonde.

Le seuil est la partie qui compte. Sur un lien 4G le flux tombe
regulierement sans que personne n'ait touche au telephone : tunnel,
bascule d'antenne, congestion. Alerter des la premiere sonde ratee
produirait plusieurs CRITICAL par jour, et on apprend vite a ignorer des
alertes qui crient pour rien - y compris le jour ou elles ont raison.
Trois sondes consecutives, soit une minute d'absence reelle. Six tests
couvrent ce comportement, dont la remise a zero du compteur au retour du
flux.

Utilisateur d'API dedie cote MediaMTX, restreint au reseau Docker interne.

41 tests au vert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Adam Belkacemi 2026-09-12 18:24:45 +02:00
parent 5e4dfee665
commit d017ba4958
12 changed files with 446 additions and 4 deletions

View file

@ -234,15 +234,45 @@ d'entreprise.
| **Lecture** | publique — le flux est une vitrine, c'est assumé |
| **Publication** | authentifiée — sans ça, n'importe qui sur Internet pousserait sa propre vidéo sur le flux `biblio` |
### La caméra muette est un événement comme un autre
Le domaine connaissait déjà `CAMERA_OFFLINE`, classé `CRITICAL` — un capteur
qui se tait alors que l'alarme est armée, c'est soit une batterie morte, soit
quelqu'un qui l'a trouvé derrière les livres. Rien ne l'émettait jamais.
`CameraLivenessProbe` comble ce trou : elle interroge l'API du serveur média et
traduit une absence prolongée en événement capteur.
Elle passe par le **même port** `IngestSensorEventUseCase` que l'endpoint REST
et le simulateur. Trois producteurs d'événements de natures totalement
différentes — un téléphone, un simulateur, une sonde de supervision — un seul
contrat d'entrée, et le même trajet Kafka → agrégat ensuite. Si l'alarme est
désarmée, une coupure vidéo ne réveille personne : c'est l'agrégat qui tranche,
pas la sonde.
**Le seuil est la partie qui compte.** Sur un lien 4G, le flux tombe
régulièrement sans que personne n'ait touché au téléphone : tunnel, bascule
d'antenne, congestion. Alerter dès la première sonde ratée produirait plusieurs
`CRITICAL` par jour — et la seule chose qu'on apprend à vivre avec des alertes
qui crient pour rien, c'est à les ignorer, y compris le jour où elles ont
raison. Il faut donc trois sondes consécutives, soit une minute d'absence
réelle.
### Brancher un vrai téléphone
Application : **IP Camera Lite** (iOS), menu *Live Push*.
**Larix Broadcaster** (iOS/Android, gratuite, sans filigrane) : elle gère SRT,
la reconnexion automatique et le débit adaptatif. C'est ce qu'il faut sur un
lien mobile. IP Camera Lite sait aussi pousser, mais elle est conçue pour le
mode *pull* — lequel ne peut pas fonctionner depuis l'extérieur.
```
SRT srt://<serveur>:8890?streamid=publish:biblio:iphone:<mot-de-passe>
RTMP rtmp://<serveur>:1935/biblio?user=iphone&pass=<mot-de-passe>
SRT srt://<serveur>:8890 · streamid = publish:biblio:iphone:<mot-de-passe>
RTMP rtmp://<serveur>:1935/biblio?user=iphone&pass=<mot-de-passe>
```
Réglages pour la 4G : **H.264, 640×360, 15 fps, 400–600 kbps, latence SRT
2000 ms, audio coupé**. À 500 kbps, compter **~225 Mo par heure** — un flux
permanent dépasse 5 Go par jour, ce qui n'a de sens que sur le WiFi du studio.
Le mot de passe est généré au déploiement dans le `.env` du serveur
(`STREAM_PUBLISH_PASSWORD`) et n'existe nulle part dans ce dépôt.