5.7 KiB
5.7 KiB
AppRobotWebcam – Roadmap
Ziel
Sauberer, fokussierter Webcam-Service als Docker-Container. Kein Robot-Control, kein ArUco – nur zwei Verantwortlichkeiten:
- Live-Video mit minimaler Latenz (WebRTC via go2rtc)
- 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 ~50–150 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 ✅
- Messvergleich WebRTC ⟷ MJPEG: WebRTC ~130 ms, MJPEG ~200 ms → WebRTC gewinnt
- Entscheid: bei WebRTC bleiben (niedrigere Latenz + besser für Internet)
- Optional: Prüfen ob Kamera natives H.264 liefert (
v4l2-ctl --list-formats) → kein Re-Encode - Optional: Keyframe-Intervall / Encoder-Preset tunen wenn <100 ms gefordert
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/wsdirekt 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.jsgo2rtcPortauf 443 (wss://) setzen, Node GO2RTC_PORT=443. - WebRTC-Candidate:
stun:8555testen; 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 (1–3 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