# 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 -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 ✅ - [x] Projektstruktur, package.json, docker-compose mit inline-Config - [x] Erste Version (Node-FFmpeg-MJPEG über WebSocket) – verworfen wegen Latenz ### Phase 2 – Umstieg auf go2rtc / WebRTC ✅ - [x] go2rtc als Streaming-Backend (Kamera-Capture + WebRTC) - [x] go2rtc-Config in docker-compose eingebettet (`configs.content`) - [x] Node als Reverse-Proxy (`/api/ws`, `/api/frame.jpeg`, Player-Scripts) - [x] Eigener Viewer mit go2rtc ``-Component (Auto-Fallback) - [x] Stabile Snapshot-API `/api/snapshot/cam{n}` - [x] 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 (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 ) │ └── 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 ```