Files
appRobotWebcam/doc/01_WebcamRoadmap.md
2026-06-03 21:07:46 +02:00

5.7 KiB
Raw Blame History

AppRobotWebcam Roadmap

Ziel

Sauberer, fokussierter Webcam-Service als Docker-Container. Kein Robot-Control, kein ArUco nur zwei Verantwortlichkeiten:

  1. Live-Video mit minimaler Latenz (WebRTC via go2rtc)
  2. Standbilder auf Abruf via HTTP REST (/api/snapshot/cam{n})

Das Homing-Projekt holt seine Standbilder über den Snapshot-Endpunkt keine weitere Kopplung.


Architektur (final)

USB Kameras
    │
    ▼
go2rtc  (Capture · H.264-Encode · WebRTC)         ── intern, Port 1984 + UDP 8555
    │
    ▼
Node.js / Express                                 ── öffentlich, Port 8444
    ├── /                eigener Viewer (go2rtc <video-stream>-Component)
    ├── /api/ws          WebRTC-Signaling  → proxied zu go2rtc
    ├── /api/snapshot/*  Standbilder       → proxied zu go2rtc /api/frame.jpeg
    └── /health

Warum go2rtc statt eigenem FFmpeg-Stream: Erste Version (eigener Node-FFmpeg-MJPEG-Stream über WebSocket) hatte spürbare Latenz. go2rtc ist ein spezialisierter Streaming-Server: WebRTC mit ~50150 ms, automatisches Encoding, ICE-Negotiation, robuster Client mit Auto-Fallback (WebRTC→MSE→MJPEG).

Warum Node davor (statt go2rtc direkt):

  • Ein einziger öffentlicher Port (8444); go2rtc-Admin bleibt unerreichbar
  • Stabile Snapshot-Schnittstelle, entkoppelt von go2rtc-Interna
  • Eigener, schlanker Viewer

Stack-Entscheide:

Komponente Wahl Begründung
Streaming go2rtc WebRTC out-of-the-box, niedrige Latenz, internet-tauglich
Webserver Node.js + Express wartbar, user-präferiert
Proxy http-proxy-middleware reicht HTTP + WebSocket transparent durch
Live-Protokoll WebRTC (Fallback MSE/MJPEG) niedrigste Latenz, skaliert über Internet
Snapshot-API HTTP GET → JPEG einfachste Schnittstelle für Consumer
Container docker-compose, configs inline kein Dockerfile-File, Portainer-tauglich

Tasks

Phase 1 Grundgerüst

  • Projektstruktur, package.json, docker-compose mit inline-Config
  • Erste Version (Node-FFmpeg-MJPEG über WebSocket) verworfen wegen Latenz

Phase 2 Umstieg auf go2rtc / WebRTC

  • go2rtc als Streaming-Backend (Kamera-Capture + WebRTC)
  • go2rtc-Config in docker-compose eingebettet (configs.content)
  • Node als Reverse-Proxy (/api/ws, /api/frame.jpeg, Player-Scripts)
  • Eigener Viewer mit go2rtc <video-stream>-Component (Auto-Fallback)
  • Stabile Snapshot-API /api/snapshot/cam{n}
  • Auflösung fest 640×480 → Latenz „akzeptabel" (war vorher das Hauptproblem)

Phase 3 Latenz final tunen (offen)

  • Messvergleich WebRTC ⟷ MJPEG durchführen → siehe 03_Protocoll_roadmap.md
  • Falls nötig: Auflösung 320×240 testen (kleiner = weniger Browser-Last)
  • Falls nötig: Keyframe-Intervall senken (-g 15), zerolatency-Tuning
  • Prüfen ob Kamera natives H.264 liefert (v4l2-ctl --list-formats) → kein Re-Encode

Phase 4 Internet-Härtung (offen, vor Produktiv-Schaltung)

  • TLS via Caddy empfohlen, weil Caddy WebSocket-Proxy nativ und zuverlässig kann. Aktuell verbindet Browser /api/ws direkt zu go2rtc Port 1984. Caddy bündelt beides hinter einer Domain: robot.example.com { handle /api/ws* { reverse_proxy localhost:1984 } handle /api/stream* { reverse_proxy localhost:1984 } handle /video-*.js { reverse_proxy localhost:1984 } handle { reverse_proxy localhost:8444 } } Danach: viewer.js go2rtcPort auf 443 (wss://) setzen, Node GO2RTC_PORT=443.
  • WebRTC-Candidate: stun:8555 testen; bei NAT-Problemen → feste IP/Domain: candidates: [robot.example.com:8555] in go2rtc-Config
  • TURN: nur wenn STUN + UDP 8555 nicht reicht (sehr restriktive NATs)
  • Zugriffsschutz: Basic-Auth am Caddy (13 bekannte User)
  • Firewall: TCP 443 (Caddy) + UDP 8555 (WebRTC) forwarden; 1984 + 8444 intern

Phase 5 Robustheit (optional)

  • Kamera hot-plug: go2rtc-Verhalten bei Device-Verlust prüfen
  • Resource Limits dokumentieren (mem_limit, cpus)
  • JSON-Logging
  • Snapshot-Metadaten / optionaler Webhook nach Snapshot

Abgrenzung zu appRobotVideoControls

Feature appRobotVideoControls appRobotWebcam
Video-Streaming eigener FFmpeg-MJPEG/WS go2rtc / WebRTC
Snapshots komplex (dual-pipe) HTTP REST, einfach
Robot-Control (G-Code) anderes Projekt
ArUco / Homing anderes Projekt
Separates Dockerfile (OpenCV-Build) (inline in compose)

Ports

Dienst Port Exponiert?
Node Viewer + API + Signaling TCP 8444 ja (Firewall)
WebRTC Media UDP 8555 ja (Firewall)
go2rtc HTTP/Debug-UI TCP 1984 nein (nur intern/LAN)

Datei-Struktur

appRobotWebcam/
├── src/
│   └── snapshotService.js   Snapshot-Router (proxied go2rtc /api/frame.jpeg)
├── public/
│   ├── index.html           Viewer (lädt go2rtc <video-stream>)
│   └── viewer.js            baut Kamera-Views, Auto-Fallback WebRTC→MSE→MJPEG
├── doc/
│   ├── 01_WebcamRoadmap.md         (diese Datei)
│   ├── 03_Protocoll_roadmap.md     WebRTC⟷MJPEG-Vergleich (nachzuholen)
│   └── 05_OptionalToDo_roadmap.md  Control-Integration (Optionen)
├── docker-compose.yaml      einzige Deploy-Datei (go2rtc-Config eingebettet)
├── go2rtc.yaml              nur Referenz/lokal (Config ist in compose eingebettet)
├── package.json
└── server.js                Node-Einstiegspunkt