FEAT: Agent vidéo — brancher la capture FFmpeg et le pipeline de snapshots #1

Closed
opened 2026-08-10 21:02:17 +02:00 by nonobis · 1 comment
Owner

🎯 Contexte

Le cœur métier de l'agent n'est pas branché : CameraStreamService (capture FFmpeg par caméra) existe mais n'est pas enregistré dans le DI de src/Heimdall.Agent/Program.cs, et les frames capturées ne sont que comptées (aucune transmission au pipeline d'analyse). L'agent se contente de register + heartbeat + config hub.

📚 Référence spec (MASTER_SPECIFICATION.md v2.0)

Phase 15 — Agent Vidéo (capture + streaming)

  • FFmpeg capture passthrough H264, zerolatency : ffmpeg -rtsp_transport tcp -buffer_size 0 -max_delay 0 -i rtsp://... -g 1 -tune zerolatency -preset ultrafast -c:v copy -f rawvideo pipe:1
  • Snapshot pipeline : intervalle adaptatif — scène vide 1000ms / mouvement 500ms / objet détecté 200ms / CPU > 80% → intervalle doublé
  • BoundedChannel<Snapshot> (backpressure, drop oldest si > 100)
  • Section 6.2 : latence cible < 500ms LAN

🔍 État actuel (vérifié dans le code)

src/Heimdall.Agent/Services/CameraStreamService.cs : process FFmpeg par caméra (-rtsp_transport tcp -i <url> -f image2pipe -vcodec mjpeg -q:v 3 -update 1 -), ArgumentList (anti-injection RTSP), sémaphore max 4 processus, ArrayPool<byte>.Shared, kill sécurisé. Frames seulement comptées — commentaire « will be passed to FrameAnalyzerService in a future phase ». Non enregistré dans le DI.

🧩 À faire

  • Enregistrer CameraStreamService (hosted service ou scoped) dans Program.cs de l'agent
  • Configurer les caméras de l'agent : liste RTSP depuis le Central (settings/config hub) ou config locale
  • Implémenter le channel borné + intervalle adaptatif (1000/500/200ms) + dégradation CPU > 80%
  • Brancher les frames vers FrameAnalyzerService (voir ticket dédié YOLO/ONNX)
  • Backpressure : queue pleine → drop oldest, alert admin
  • Tests : CameraStreamServiceTests existants à étendre (démarrage FFmpeg, reconnexion, kill sécurisé)

🧪 Critères d'acceptation

  • L'agent démarre une capture FFmpeg par caméra configurée
  • Les frames sont transmises à l'analyseur (compteur incrémenté → appel réel)
  • Intervalle adaptatif respecté (1000/500/200ms) selon l'état de la scène
  • make test vert

📁 Fichiers concernés

src/Heimdall.Agent/Services/CameraStreamService.cs, src/Heimdall.Agent/Program.cs, src/Heimdall.Agent/AgentOptions.cs, tests/Heimdall.Agent.Tests/

## 🎯 Contexte Le cœur métier de l'agent n'est pas branché : `CameraStreamService` (capture FFmpeg par caméra) existe mais **n'est pas enregistré dans le DI** de `src/Heimdall.Agent/Program.cs`, et les frames capturées ne sont que comptées (aucune transmission au pipeline d'analyse). L'agent se contente de register + heartbeat + config hub. ## 📚 Référence spec (MASTER_SPECIFICATION.md v2.0) **Phase 15 — Agent Vidéo (capture + streaming)** - FFmpeg capture passthrough H264, zerolatency : `ffmpeg -rtsp_transport tcp -buffer_size 0 -max_delay 0 -i rtsp://... -g 1 -tune zerolatency -preset ultrafast -c:v copy -f rawvideo pipe:1` - Snapshot pipeline : intervalle **adaptatif** — scène vide 1000ms / mouvement 500ms / objet détecté 200ms / CPU > 80% → intervalle doublé - `BoundedChannel<Snapshot>` (backpressure, drop oldest si > 100) - Section 6.2 : latence cible < 500ms LAN ## 🔍 État actuel (vérifié dans le code) `src/Heimdall.Agent/Services/CameraStreamService.cs` : process FFmpeg par caméra (`-rtsp_transport tcp -i <url> -f image2pipe -vcodec mjpeg -q:v 3 -update 1 -`), `ArgumentList` (anti-injection RTSP), sémaphore max 4 processus, `ArrayPool<byte>.Shared`, kill sécurisé. Frames seulement comptées — commentaire « will be passed to FrameAnalyzerService in a future phase ». Non enregistré dans le DI. ## 🧩 À faire - [ ] Enregistrer `CameraStreamService` (hosted service ou scoped) dans `Program.cs` de l'agent - [ ] Configurer les caméras de l'agent : liste RTSP depuis le Central (settings/config hub) ou config locale - [ ] Implémenter le channel borné + intervalle adaptatif (1000/500/200ms) + dégradation CPU > 80% - [ ] Brancher les frames vers `FrameAnalyzerService` (voir ticket dédié YOLO/ONNX) - [ ] Backpressure : queue pleine → drop oldest, alert admin - [ ] Tests : `CameraStreamServiceTests` existants à étendre (démarrage FFmpeg, reconnexion, kill sécurisé) ## 🧪 Critères d'acceptation - [ ] L'agent démarre une capture FFmpeg par caméra configurée - [ ] Les frames sont transmises à l'analyseur (compteur incrémenté → appel réel) - [ ] Intervalle adaptatif respecté (1000/500/200ms) selon l'état de la scène - [ ] `make test` vert ## 📁 Fichiers concernés src/Heimdall.Agent/Services/CameraStreamService.cs, src/Heimdall.Agent/Program.cs, src/Heimdall.Agent/AgentOptions.cs, tests/Heimdall.Agent.Tests/
Author
Owner

Implémenté dans b652d8a (Fixes #1).

  • Pipeline capture : CameraStreamService enregistré dans le DI + SnapshotPipelineService (hosted) qui synchronise les captures avec les caméras assignées (clés camera..* dans la config agent, appliquées à chaud via le ConfigReceiverService ; fallback local Agent:Cameras)
  • Découpage du flux MJPEG en frames JPEG (JpegFrameSplitter, marqueurs SOI/EOI)
  • Intervalle adaptatif spec Phase 15 : vide 1000ms / mouvement 500ms / objet 200ms, doublé si CPU > 80% (AdaptiveSnapshotInterval + SceneStateTracker + FrameMotionDetector proxy, pixel diff réel en Phase 16)
  • Channel borné 100 snapshots (DropOldest) : backpressure + compteur de drops + log rate-limité (visible admin via remontée logs agent)
  • Frames réellement transmises à FrameAnalyzerService (AnalyzedFrameCount)
  • Central : GET /api/settings/agent/{id} embarque les caméras assignées (name/rtsp/sub_rtsp/enabled)
  • Tests : 526 verts (Agent 170 + Application 356), dont ~60 nouveaux (splitter, intervalle, tracker, motion, store, pipeline, handler config)

Restant (tickets dédiés) : inférence YOLO/ONNX réelle (RunInference stub), pixel-diff Motion Gate Phase 16, purge logs #53.

Implémenté dans b652d8a (Fixes #1). - Pipeline capture : CameraStreamService enregistré dans le DI + SnapshotPipelineService (hosted) qui synchronise les captures avec les caméras assignées (clés camera.<id>.* dans la config agent, appliquées à chaud via le ConfigReceiverService ; fallback local Agent:Cameras) - Découpage du flux MJPEG en frames JPEG (JpegFrameSplitter, marqueurs SOI/EOI) - Intervalle adaptatif spec Phase 15 : vide 1000ms / mouvement 500ms / objet 200ms, doublé si CPU > 80% (AdaptiveSnapshotInterval + SceneStateTracker + FrameMotionDetector proxy, pixel diff réel en Phase 16) - Channel borné 100 snapshots (DropOldest) : backpressure + compteur de drops + log rate-limité (visible admin via remontée logs agent) - Frames réellement transmises à FrameAnalyzerService (AnalyzedFrameCount) - Central : GET /api/settings/agent/{id} embarque les caméras assignées (name/rtsp/sub_rtsp/enabled) - Tests : 526 verts (Agent 170 + Application 356), dont ~60 nouveaux (splitter, intervalle, tracker, motion, store, pipeline, handler config) Restant (tickets dédiés) : inférence YOLO/ONNX réelle (RunInference stub), pixel-diff Motion Gate Phase 16, purge logs #53.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nonobis/Heimdall#1
No description provided.