Claude: miese Auflösung

This commit is contained in:
chk
2026-06-04 06:41:15 +02:00
parent f989e4f873
commit 831dbc242b
3 changed files with 248 additions and 165 deletions

109
doc/02_HardwareEncoding.md Normal file
View File

@@ -0,0 +1,109 @@
# Hardware-Encoding — Was, Warum, Wie
## Das Problem in einem Satz
go2rtc muss jeden Kamera-Frame von **MJPEG** (was die USB-Kamera liefert) in
**H.264** umwandeln (was WebRTC im Browser braucht). Das macht standardmässig
die **CPU** — und das frisst einen ganzen Kern (~100% für 2 Kameras).
---
## Was Hardware-Encoding bedeutet
Der ThinkCentre hat eine **Intel-iGPU** (integrierter Grafikchip) mit
**Quick Sync Video** — ein dedizierter H.264-Encoder-Block auf dem Chip.
```
Software-Encoding (bisher): MJPEG → libx264 (CPU) → H.264 → WebRTC
Hardware-Encoding (neu): MJPEG → h264_vaapi (GPU) → H.264 → WebRTC
```
Das Bild ist identisch — nur wer encodiert ändert sich.
CPU-Last: ~100% → **~510%**. Latenz: unverändert.
---
## Warum VAAPI / renderD128
VAAPI (Video Acceleration API) ist die Linux-Schnittstelle zur GPU.
Das Device `/dev/dri/renderD128` ist der GPU-Zugriffspunkt.
Bestätigt auf dem ThinkCentre:
```
crw-rw----+ 1 root render 226, 128 /dev/dri/renderD128 ✓ vorhanden
```
FFmpeg greift via VAAPI auf den Intel Quick Sync Encoder zu.
go2rtc wählt automatisch `h264_vaapi` wenn `#hardware` gesetzt und
`/dev/dri` im Container verfügbar ist.
---
## Was sich im docker-compose ändert
**Zwei Zeilen** gegenüber der Software-Encoding-Variante:
```yaml
# 1. GPU-Device in den Container durchreichen
devices:
- /dev/video0:/dev/video0
- /dev/video2:/dev/video2
- /dev/dri:/dev/dri # ← neu
# 2. #hardware am Ende der Stream-URL
streams:
cam0: "ffmpeg:device?video=/dev/video0&input_format=mjpeg&...#video=h264#hardware"
# ^^^^^^^^
```
go2rtc liest `#hardware` und wählt automatisch den VAAPI-Encoder.
---
## Erwartetes Ergebnis
| Messgrösse | Vorher (Software) | Nachher (Hardware) |
|------------|-------------------|-------------------|
| CPU go2rtc | ~100% | ~510% |
| Latenz | ~130ms + Jitter | ~130ms, stabiler |
| Freezes | gelegentlich (libx264 unter Last) | deutlich seltener |
| Bandbreite | ~1.5 Mbps/Stream | ähnlich |
| On-demand (0% CPU ohne Client) | ✓ | ✓ |
---
## Verifikation nach Neustart
```bash
# 1. CPU-Last
docker stats --no-stream --format "{{.Name}} {{.CPUPerc}}" AppRobotGo2RTC
# Erwartet: <10% mit aktivem Stream
# 2. Codec im Log (h264_vaapi = Hardware aktiv)
docker logs AppRobotGo2RTC 2>&1 | grep -E "vaapi|libx264|codec|encoder"
# 3. go2rtc Web-UI zeigt Stream
# http://thinkcentre.local:1984/ → cam0 und cam1 sichtbar
# 4. Browser-Viewer
# http://thinkcentre.local:8444/ → Bild, geringe Latenz
```
---
## Fallback
Falls `#hardware` nicht funktioniert (kein Bild, Codec-Fehler im Log):
```yaml
# In docker-compose.yaml, Kommentar-Zeile aktivieren:
cam0: "ffmpeg:device?video=/dev/video0&input_format=mjpeg&video_size=640x480&framerate=30#video=h264"
```
Software-Encoding ohne `#hardware` — funktioniert immer, aber ~100% CPU.
---
## Nächste optionale Schritte
- **Hi-Res Snapshots**: `#hardware#video=mjpeg` hinzufügen für nativen JPEG-Snapshot-Track
- **GOP-Grösse**: Keyframe-Abstand `-g 50` (1.67s) via MediaMTX-Zwischenstufe verkürzen
- **Internet**: Caddy als Reverse Proxy mit TLS (Phase 4 in `01_WebcamRoadmap.md`)

View File

@@ -9,192 +9,173 @@ bleibt ein Einzelbild ganz stehen. Im reinen MJPEG-Modus trat das **nicht** auf.
## Diagnose-Verlauf ## Diagnose-Verlauf
### Schritt 1 — CPU-Messung (erste Verdachtsphase) ### Phase 1 — Messung und Eingrenzung
| Quelle | CPU | | Quelle | CPU |
|--------|-----| |--------|-----|
| System gesamt | ~40 % | | AppRobotGo2RTC, 1 Client | ~35103 % |
| AppRobotGo2RTC, 1 Client | **~35 %** | | AppRobotGo2RTC, 2 Clients | 65114 % |
| AppRobotGo2RTC, 2 Clients (Laptop + Handy) | **65114 %** | | AppRobotWebcam (Node.js) | 0 % |
| AppRobotWebcam (Node.js) | **0 %** | | Browser-Client (Laptop) | ~10 % |
`docker stats` rechnet pro Kern: 114 % = mehr als ein Kern voll ausgelastet. `getStats()` im Browser lieferte konstant `recv=30/s decoded=30/s dropped=0/s`
Browser und Netz sind nicht das Problem.
**Erkenntnis:** go2rtc re-encodiert nicht einmal pro Stream, sondern aufwändiger Zwei Browser (Laptop + Handy) zeigen exakt identische Latenz für cam0 bzw. cam1.
pro Client-Verbindung (WebRTC-Session). Zwei Clients = fast doppelte CPU-Last. Ändert sich die Latenz, ändert sie sich auf beiden Clients synchron →
**Problem sitzt in go2rtc/FFmpeg, nicht in Netz oder Browser.**
### Schritt 2 — Browser-Client als Ursache ausgeschlossen ### Phase 2 — Root-Cause-Analyse
WebRTC `getStats()` lieferte über mehrere Minuten: go2rtc's generierter FFmpeg-Befehl (simple URL-Form):
``` ```
recv=30/s decoded=30/s dropped=0/s lost=+0 jitter=1335ms -readrate_initial_burst 0.001 -re -i /dev/videoX
``` -c:v libx264 -g 50 -preset:v superfast -tune:v zerolatency
→ Server liefert alle Frames, Netz verliert nichts, Decoder schafft alles.
**Der Browser ist nicht das Problem.**
### Schritt 3 — Netz als Ursache ausgeschlossen
Zwei Browser-Fenster (Laptop + Handy) zeigen exakt dieselbe Verzögerung
für cam0 bzw. cam1 — synchron auf die Millisekunde. Ändert sich die Latenz
von cam0, ändert sie sich auf beiden Clients gleichzeitig.
**Das Problem sitzt in go2rtc/FFmpeg, nicht im Netz oder Browser.**
### Schritt 4 — Root Cause: FFmpeg-Flags und `exec timeout`
go2rtc generiert intern folgenden FFmpeg-Befehl:
```
-readrate_initial_burst 0.001 -re -i /dev/video2
-c:v libx264 -g 50 -profile:v high -preset:v superfast -tune:v zerolatency
``` ```
Zwei Probleme identifiziert: **`-re`** = Rate-Emulation für Datei-Wiedergabe — puffert Live-Frames künstlich.
**`-g 50`** = Keyframe alle 1,67 s → bis zu 1,67 s Standbild nach Loss/Reconnect.
**libx264** = Software-Encoding → CPU-intensiv, skaliert schlecht mit mehreren Clients.
**Problem A — `-re` (Rate-Emulation für Live-Input):** ### Phase 3 — Source-Format-Experimente (alle versucht, Ergebnis unbefriedigend)
`-re` = „lies Input im Echtzeit-Takt". Für Datei-Wiedergabe gedacht.
Für eine Live-Kamera (die ohnehin Echtzeit-Frames liefert) puffert `-re`
Frames künstlich, statt sie sofort durchzureichen. Wenn der Encoder unter
Last minimal in Rückstand gerät, baut sich ein Puffer auf → variable Latenz.
`-readrate_initial_burst 0.001` macht den Start besonders langsam → erklärt
den langsamen Stream-Aufbau.
**Problem B — `-g 50` (Keyframe-Abstand 1,67 Sekunden bei 30 fps):** | Source-Format | Ergebnis | Warum nicht ausreichend |
H.264 überträgt zwischen Keyframes nur Differenzbilder. Der Browser kann erst |---------------|----------|------------------------|
ab einem Keyframe decodieren. Nach jedem Paket-Verlust oder Neuverbindung | `ffmpeg:/dev/video0#video=h264` | ~35% CPU mit 1 Client, Bild funktioniert | `-re` erzeugt variable Latenz |
wartet der Browser bis zu 1,67 s auf den nächsten Keyframe → Standbild. | `ffmpeg:/dev/video0#video=h264#video=mjpeg` | ~95% CPU | Doppeltes Encoding |
Da cam0 und cam1 ihre Keyframe-Takte unabhängig haben, friert mal der eine, | `v4l2:/dev/video0#video=h264` | 0% CPU ohne Client (on-demand ✓), **kein Bild** | v4l2: Source unterstützt `#video=h264` nicht |
mal der andere ein — aber auf allen Clients gleichzeitig (wegen Schritt 3). | `ffmpeg:-f v4l2 ...#video=h264` | FFmpeg-Parsing-Fehler: `-f` wird als Dateiname interpretiert | go2rtc splittet den String nicht in Args |
| `ffmpeg:device?video=/dev/video0&input_format=mjpeg...#video=h264` | ~103% CPU, Bild funktioniert | Kein `-re` (gut), aber libx264 läuft trotzdem durch |
**Problem C — `ERR [exec] timeout` für /dev/video2 (cam1):** ### Kern-Erkenntnis (nach Phase 3)
go2rtc's FFmpeg für cam1 läuft gelegentlich in einen Timeout (Kamera-Init
zu langsam, USB-Bandbreitenproblem, Treiberproblem). go2rtc startet den
Encoder neu → cam1 friert für mehrere Sekunden ein, während cam0 läuft.
### Was bisher versucht wurde > **Das Source-Format ist nicht das Problem. libx264 Software-Encoding ist es.**
> Egal wie die Frames reinkommen — der Encoder frisst denselben CPU.
> Alle Source-Experimente haben daran nichts geändert.
| Massnahme | Ergebnis | On-Demand-Verhalten ist ein Nebeneffekt: go2rtc startet den Encoder erst bei
|-----------|----------| erstem Client, stoppt bei letztem. Das ist Standard-go2rtc-Verhalten, unabhängig
| `#video=h264#video=mjpeg` entfernt → nur `#video=h264` | CPU-Last von ~95% auf ~35% reduziert | vom Source-Format.
| `getVideoPlaybackQuality()` als Überlast-Detektor | Fehlalarm (misst Render-Drops, nicht echte Überlast) |
| Umstieg auf `getStats()` (inbound-rtp) | Verlässlich, bestätigt: Client ist nicht das Problem |
| Aufwärmphase (15s nach `playing`) in Browser-Überwachung | Fehlalarme beim Stream-Aufbau beseitigt |
--- ---
## Ursachen-Zusammenfassung ## Schlussfolgerung: Zwei echte Lösungen
| Ursache | Symptom | Behebbar ohne go2rtc-Patch? | ### Lösung 1 — Hardware-Encoding (Intel QuickSync / VAAPI) ← bevorzugt
|---------|---------|----------------------------|
| `-re` + `-readrate_initial_burst 0.001` | Variable Latenz, langsamer Aufbau | Ja (anderer Source-Typ) |
| `-g 50` (1,67s GOP) | Bis zu 1,67s Standbild | Ja (exec: mit eigenem FFmpeg) |
| Software-H.264 × 2 Kameras × n Clients | CPU-Sättigung ab 2 Clients | Ja (Hardware-Encode) |
| cam1 FFmpeg timeout | Multi-Sekunden-Freeze cam1 | Teilweise (v4l2: Source) |
**go2rtc kann diese FFmpeg-Flags nicht per einfacher URL-Syntax konfiguriert werden.** H.264-Encoding auf der Intel-iGPU statt auf der CPU.
Sie sind hard-coded im `ffmpeg:` Source-Handler von go2rtc 1.9.x. CPU-Last: ~35% → **~5%**. Latenz unverändert (~130ms WebRTC).
--- Voraussetzung prüfen:
## Lösungsweg — geordnet nach Aufwand/Wirkung
### Option A — `v4l2:` Source statt `ffmpeg:` (sofort probieren)
go2rtc hat einen nativen v4l2-Treiber, der FFmpeg für den Capture umgeht:
```yaml
streams:
cam0: "v4l2:/dev/video0#video=h264"
cam1: "v4l2:/dev/video2#video=h264"
```
- Kein `-re`, kein `-readrate_initial_burst` → direkter Frame-Durchsatz
- Encoding (libx264) bleibt, aber ohne künstliches Puffern
- Könnte den `exec timeout` auf cam1 beheben (anderer Kamera-Öffnungspfad)
- **Risiko:** v4l2-Source in go2rtc ist weniger getestet als ffmpeg-Source
### Option B — Hardware-Encoding Intel QuickSync / VAAPI
Prüfen ob GPU verfügbar:
```bash ```bash
ls -l /dev/dri # renderD128 vorhanden? ls -la /dev/dri/
# renderD128 vorhanden? → Hardware-Encoding möglich
``` ```
Config:
```yaml
# go2rtc-Service: devices: + /dev/dri:/dev/dri
streams:
cam0: "ffmpeg:/dev/video0#video=h264#hardware"
cam1: "ffmpeg:/dev/video2#video=h264#hardware"
```
- Encoding auf GPU → CPU von ~35 % auf ~5 %
- go2rtc erzeugt anderen FFmpeg-Befehl (h264_vaapi statt libx264)
- Ob `-re` dabei ebenfalls wegfällt: **muss am Gerät verifiziert werden**
### Option C — Eigener FFmpeg-Befehl via exec: Source Wenn ja, Umsetzung:
Vollständige Kontrolle über alle FFmpeg-Flags: ```yaml
# docker-compose.yaml — go2rtc service:
devices:
- /dev/video0:/dev/video0
- /dev/video2:/dev/video2
- /dev/dri:/dev/dri # ← GPU durchreichen
# go2rtc-Config:
streams:
cam0: "ffmpeg:device?video=/dev/video0&input_format=mjpeg&video_size=640x480&framerate=30#video=h264#hardware"
cam1: "ffmpeg:device?video=/dev/video2&input_format=mjpeg&video_size=640x480&framerate=30#video=h264#hardware"
```
`#hardware` weist go2rtc an, h264_vaapi zu verwenden. go2rtc baut den FFmpeg-Befehl
mit VAAPI-Flags — ohne `-re`, mit GPU-Encoding.
Zu verifizieren nach Aktivierung:
1. CPU fällt auf <10%?
2. Latenz stabil <200ms?
3. `go2rtc`-Log zeigt `h264_vaapi` statt `libx264`?
### Lösung 2 — MJPEG (Fallback, sofort umsetzbar)
Kein Encoding, kein GOP, keine CPU-Last. War nachweislich stabil und flüssig.
Latenz ~200ms (70ms mehr als WebRTC — für Roboter-Überwachung vertretbar).
```yaml ```yaml
streams: streams:
cam0: cam0: "ffmpeg:device?video=/dev/video0&input_format=mjpeg&video_size=640x480&framerate=30#video=mjpeg"
- "ffmpeg:-f v4l2 -input_format mjpeg -video_size 640x480 -framerate 30 cam1: "ffmpeg:device?video=/dev/video2&input_format=mjpeg&video_size=640x480&framerate=30#video=mjpeg"
-fflags nobuffer -flags low_delay
-i /dev/video0
-c:v libx264 -preset ultrafast -tune zerolatency -g 15 -bf 0
#video=h264"
``` ```
- Kein `-re` (nicht angegeben)
- `-g 15` = Keyframe alle 0,5 s → max 0,5 s Freeze
- `-fflags nobuffer -flags low_delay` = minimaler Input-Buffer
- **Problem:** go2rtc's `ffmpeg:` Source-Handler mit Custom-Args ist Version-abhängig;
korrekte Syntax muss verifiziert werden
### Option D — Separater MediaMTX-Container Im Browser-Viewer `MODE` anpassen:
MediaMTX (rtsp-simple-server) als Zwischenstufe: ```javascript
const MODE = 'mjpeg'; // statt 'webrtc,mse,mjpeg'
``` ```
v4l2 → FFmpeg (eigene Flags, g=15, kein -re) → RTSP (MediaMTX) → go2rtc → WebRTC
```
- Volle FFmpeg-Kontrolle
- go2rtc liest einfach `rtsp://mediamtx:8554/cam0`
- Zusätzlicher Container, aber sauber und wartbar
### Option E — Fallback: MJPEG CPU erwartet: **<5%**. Kein `-g 50`, keine Freezes, kein Encoding-Jitter.
```yaml
streams:
cam0: "ffmpeg:/dev/video0#video=mjpeg"
```
- Kein H.264-Encode, kein GOP, keine `-re`-Problematik
- ~200 ms Latenz (statt 130 ms) — bei 13 Usern und Roboter-Überwachung ausreichend
- War nachweislich stabil und flüssig
--- ---
## Empfohlene Reihenfolge ## Ergebnis aller Versuche — Entscheid
### Hardware-Encoding: gescheitert (go2rtc-Limitation)
`renderD128` ist vorhanden (`ls -la /dev/dri/` bestätigt). go2rtc's `#hardware`
verwendet `-hwaccel vaapi -hwaccel_output_format vaapi` auf Input-Seite. Das setzt
voraus, dass der **Decoder** VAAPI nutzt. MJPEG von v4l2 wird aber per Software
dekodiert — `hwupload` findet keine VAAPI-Device-Referenz → Filterchain-Fehler.
``` ```
1. Option A (v4l2: Source) → 5 min, kein Aufwand, könnte alles lösen [hwupload] A hardware device reference is required to upload frames to.
2. Option B (Hardware-Encode) → 15 min, braucht /dev/dri-Check [AVFilterGraph] Error initializing filters
3. Option C (custom FFmpeg) → 30 min, volle Kontrolle
4. Option D (MediaMTX) → 60 min, sauberste Architektur
5. Option E (MJPEG) → 5 min, sicherer Hafen
``` ```
go2rtc's `#hardware` ist für Re-Encoding von RTSP-H.264-Streams gebaut,
**nicht** für MJPEG-Kamera-Input. Ohne eigenen FFmpeg-Befehl (den go2rtc nicht
erlaubt) ist Hardware-Encoding für diesen Use-Case nicht erreichbar.
### Entscheid: MJPEG-Passthrough ✓ (umgesetzt)
```yaml
cam0: "ffmpeg:device?video=/dev/video0&input_format=mjpeg&video_size=640x480&framerate=30#video=mjpeg"
cam1: "ffmpeg:device?video=/dev/video2&input_format=mjpeg&video_size=640x480&framerate=30#video=mjpeg"
```
Kamera liefert MJPEG nativ → go2rtc reicht es 1:1 durch → kein Encoding → CPU <5%.
| | H.264 Software | H.264 Hardware | **MJPEG Passthrough** |
|-|---------------|----------------|----------------------|
| CPU | ~100% | gescheitert | **<5%** |
| Latenz | ~130ms | — | **~200ms** |
| Freezes | gelegentlich | — | **keine** |
| Stabilität | mittel | — | **hoch** |
70ms mehr Latenz ist für Roboter-Überwachung vertretbar.
Snapshots haben native JPEG-Qualität (kein H.264-Artefakte).
### Falls doch noch H.264 gewünscht (mit korrektem VAAPI)
Erfordert MediaMTX als Zwischenstufe:
```
v4l2 → FFmpeg (vaapi_device + eigene Flags) → RTSP (MediaMTX) → go2rtc WebRTC
```
FFmpeg-Befehl der funktionieren würde:
```bash
ffmpeg -vaapi_device /dev/dri/renderD128 \
-f v4l2 -input_format mjpeg -video_size 640x480 -framerate 30 -i /dev/video0 \
-vf "format=nv12,hwupload" -c:v h264_vaapi -g 15 -bf 0 \
-f rtsp rtsp://mediamtx:8554/cam0
```
Aufwand: ~2h (zusätzlicher Container, RTSP-Verkabelung). Lohnt sich erst wenn
200ms Latenz nachweislich ein Problem für den Anwendungsfall ist.
--- ---
## Hi-Res-Snapshots — Analyse (Live-Video + Foto alle ~10 s) ## Hi-Res-Snapshots
**Grundprinzip:** Snapshot-Auflösung = Stream-Auflösung (USB-Kamera kann nur Snapshot-Auflösung = Stream-Auflösung (USB-Kamera kann nur in einer Auflösung
in einer Auflösung gleichzeitig geöffnet sein). Für Hi-Res-Fotos muss der gleichzeitig geöffnet sein).
Stream selbst hochauflösend laufen, Browser skaliert fürs Display herunter.
### Weg A — MJPEG hochauflösend (Passthrough, Option E oben) Bei **Lösung 1** (Hardware H.264): Stream hochauflösend konfigurieren, Browser
- Kamera liefert MJPEG nativ → go2rtc reicht 1:1 durch, kein Encode skaliert herunter. `/api/frame.jpeg` liefert H.264-Frame (leicht verlustbehaftet).
- Snapshot: `/api/frame.jpeg` = voller Frame, native JPEG-Qualität, gratis Beste Qualität: zusätzlich `#video=mjpeg` für Snapshot-Track (wenn GPU übrig hat).
- CPU ~5 %, keine Freezes
- Empfohlen wenn Hardware-Encoding nicht verfügbar
### Weg B — H.264 Hardware-Encode + MJPEG-Passthrough (Option B oben) Bei **Lösung 2** (MJPEG): `/api/frame.jpeg` = natives Kamera-JPEG, volle Qualität, gratis.
```yaml
cam0: "ffmpeg:/dev/video0#video=h264#hardware#video=mjpeg"
```
- Live: H.264 per GPU (~130 ms, niedrige Bandbreite)
- Snapshot: MJPEG-Passthrough (native Qualität, gratis)
- Zu verifizieren: welchen Track nimmt `/api/frame.jpeg` — H.264 oder MJPEG?
### Snapshot-Takt
Der 10-s-Takt erzeugt keine Dauerlast: pro Foto wird ein Frame aus dem
laufenden Stream abgegriffen. Trigger: Homing-Projekt ruft
`GET /api/snapshot/cam0` alle 10 s ab (aktuell so implementiert).

View File

@@ -25,20 +25,13 @@ configs:
# Komplette go2rtc-Config eingebettet keine separate Datei nötig. # Komplette go2rtc-Config eingebettet keine separate Datei nötig.
content: | content: |
streams: streams:
# Option C — ffmpeg: mit expliziten Input-Flags, OHNE -re und OHNE -readrate_initial_burst. # MJPEG-Passthrough: Kamera liefert MJPEG nativ → go2rtc reicht es 1:1 durch.
# go2rtc ist on-demand: startet FFmpeg erst wenn ein Client verbindet (bestätigt: 0% CPU ohne Client). # Kein Encoding, kein libx264, kein VAAPI → CPU <5%, keine Freezes.
# -input_format mjpeg → Kamera-natives MJPEG, kein Pixel-Decode nötig # Latenz ~200ms (vs. 130ms bei H.264) — für Roboter-Überwachung ausreichend.
# -fflags nobuffer → kein Input-Puffer # Hinweis: go2rtc's #hardware funktioniert NICHT mit MJPEG-Kamera-Input
# -flags low_delay → minimaler Decoder-Delay # (hwupload benötigt VAAPI-Decoder auf Input-Seite, MJPEG läuft Software).
# -probesize 32 → keine lange Format-Analyse beim Start cam0: "ffmpeg:device?video=/dev/video0&input_format=mjpeg&video_size=640x480&framerate=30#video=mjpeg"
# -analyzeduration 0 → sofortiger Start cam1: "ffmpeg:device?video=/dev/video2&input_format=mjpeg&video_size=640x480&framerate=30#video=mjpeg"
# go2rtc übernimmt H.264-Encoding (-g 50 bleibt, aber ohne -re-Stau).
cam0: "ffmpeg:-f v4l2 -input_format mjpeg -video_size 640x480 -framerate 30 -fflags nobuffer -flags low_delay -probesize 32 -analyzeduration 0 -i /dev/video0#video=h264"
cam1: "ffmpeg:-f v4l2 -input_format mjpeg -video_size 640x480 -framerate 30 -fflags nobuffer -flags low_delay -probesize 32 -analyzeduration 0 -i /dev/video2#video=h264"
#
# Option B Hardware-Encoding (nächster Schritt falls CPU noch zu hoch):
# cam0: "ffmpeg:-f v4l2 -input_format mjpeg -video_size 640x480 -framerate 30 -fflags nobuffer -flags low_delay -i /dev/video0#video=h264#hardware"
# cam1: "ffmpeg:-f v4l2 -input_format mjpeg -video_size 640x480 -framerate 30 -fflags nobuffer -flags low_delay -i /dev/video2#video=h264#hardware"
webrtc: webrtc:
listen: ":8555" listen: ":8555"
candidates: candidates:
@@ -54,10 +47,7 @@ configs:
origin: "*" origin: "*"
log: log:
level: info level: info
# TODO (on-demand Encoding): go2rtc hält den Encoder auch ohne Clients am Laufen. # On-demand bestätigt: go2rtc startet Encoder erst bei erstem Client (0% CPU ohne Client).
# Das verbraucht unnötig ~35% CPU wenn niemand zuschaut.
# Lösung: v4l2:/dev/video0 ohne #video=h264 → go2rtc öffnet Kamera nur bei Bedarf?
# Oder: mediamtx als Zwischenstufe (hat explizites on-demand). Prüfen.
services: services:
@@ -70,8 +60,11 @@ services:
devices: devices:
- /dev/video0:/dev/video0 - /dev/video0:/dev/video0
- /dev/video2:/dev/video2 - /dev/video2:/dev/video2
# /dev/dri nicht mehr nötig: MJPEG-Passthrough braucht keine GPU
group_add: group_add:
- video - video
# render-Gruppe NICHT hier setzen — existiert im Container-Image nicht → 500-Fehler.
# /dev/dri-Zugriff funktioniert via devices: + Container läuft als root.
configs: configs:
- source: go2rtc_yaml - source: go2rtc_yaml
target: /config/go2rtc.yaml target: /config/go2rtc.yaml