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
### Schritt 1 — CPU-Messung (erste Verdachtsphase)
### Phase 1 — Messung und Eingrenzung
| Quelle | CPU |
|--------|-----|
| System gesamt | ~40 % |
| AppRobotGo2RTC, 1 Client | **~35 %** |
| AppRobotGo2RTC, 2 Clients (Laptop + Handy) | **65114 %** |
| AppRobotWebcam (Node.js) | **0 %** |
| AppRobotGo2RTC, 1 Client | ~35103 % |
| AppRobotGo2RTC, 2 Clients | 65114 % |
| 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
pro Client-Verbindung (WebRTC-Session). Zwei Clients = fast doppelte CPU-Last.
Zwei Browser (Laptop + Handy) zeigen exakt identische Latenz für cam0 bzw. cam1.
Ä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
```
→ 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
-readrate_initial_burst 0.001 -re -i /dev/videoX
-c:v libx264 -g 50 -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):**
`-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.
### Phase 3 — Source-Format-Experimente (alle versucht, Ergebnis unbefriedigend)
**Problem B — `-g 50` (Keyframe-Abstand 1,67 Sekunden bei 30 fps):**
H.264 überträgt zwischen Keyframes nur Differenzbilder. Der Browser kann erst
ab einem Keyframe decodieren. Nach jedem Paket-Verlust oder Neuverbindung
wartet der Browser bis zu 1,67 s auf den nächsten Keyframe → Standbild.
Da cam0 und cam1 ihre Keyframe-Takte unabhängig haben, friert mal der eine,
mal der andere ein — aber auf allen Clients gleichzeitig (wegen Schritt 3).
| Source-Format | Ergebnis | Warum nicht ausreichend |
|---------------|----------|------------------------|
| `ffmpeg:/dev/video0#video=h264` | ~35% CPU mit 1 Client, Bild funktioniert | `-re` erzeugt variable Latenz |
| `ffmpeg:/dev/video0#video=h264#video=mjpeg` | ~95% CPU | Doppeltes Encoding |
| `v4l2:/dev/video0#video=h264` | 0% CPU ohne Client (on-demand ✓), **kein Bild** | v4l2: Source unterstützt `#video=h264` nicht |
| `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):**
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.
### Kern-Erkenntnis (nach Phase 3)
### 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 |
|-----------|----------|
| `#video=h264#video=mjpeg` entfernt → nur `#video=h264` | CPU-Last von ~95% auf ~35% reduziert |
| `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 |
On-Demand-Verhalten ist ein Nebeneffekt: go2rtc startet den Encoder erst bei
erstem Client, stoppt bei letztem. Das ist Standard-go2rtc-Verhalten, unabhängig
vom Source-Format.
---
## Ursachen-Zusammenfassung
## Schlussfolgerung: Zwei echte Lösungen
| Ursache | Symptom | Behebbar ohne go2rtc-Patch? |
|---------|---------|----------------------------|
| `-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) |
### Lösung 1 — Hardware-Encoding (Intel QuickSync / VAAPI) ← bevorzugt
**go2rtc kann diese FFmpeg-Flags nicht per einfacher URL-Syntax konfiguriert werden.**
Sie sind hard-coded im `ffmpeg:` Source-Handler von go2rtc 1.9.x.
H.264-Encoding auf der Intel-iGPU statt auf der CPU.
CPU-Last: ~35% → **~5%**. Latenz unverändert (~130ms WebRTC).
---
## 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:
Voraussetzung prüfen:
```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
Vollständige Kontrolle über alle FFmpeg-Flags:
Wenn ja, Umsetzung:
```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
streams:
cam0:
- "ffmpeg:-f v4l2 -input_format mjpeg -video_size 640x480 -framerate 30
-fflags nobuffer -flags low_delay
-i /dev/video0
-c:v libx264 -preset ultrafast -tune zerolatency -g 15 -bf 0
#video=h264"
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"
```
- 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
MediaMTX (rtsp-simple-server) als Zwischenstufe:
Im Browser-Viewer `MODE` anpassen:
```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
```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
CPU erwartet: **<5%**. Kein `-g 50`, keine Freezes, kein Encoding-Jitter.
---
## 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
2. Option B (Hardware-Encode) → 15 min, braucht /dev/dri-Check
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
[hwupload] A hardware device reference is required to upload frames to.
[AVFilterGraph] Error initializing filters
```
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
in einer Auflösung gleichzeitig geöffnet sein). Für Hi-Res-Fotos muss der
Stream selbst hochauflösend laufen, Browser skaliert fürs Display herunter.
Snapshot-Auflösung = Stream-Auflösung (USB-Kamera kann nur in einer Auflösung
gleichzeitig geöffnet sein).
### Weg A — MJPEG hochauflösend (Passthrough, Option E oben)
- Kamera liefert MJPEG nativ → go2rtc reicht 1:1 durch, kein Encode
- Snapshot: `/api/frame.jpeg` = voller Frame, native JPEG-Qualität, gratis
- CPU ~5 %, keine Freezes
- Empfohlen wenn Hardware-Encoding nicht verfügbar
Bei **Lösung 1** (Hardware H.264): Stream hochauflösend konfigurieren, Browser
skaliert herunter. `/api/frame.jpeg` liefert H.264-Frame (leicht verlustbehaftet).
Beste Qualität: zusätzlich `#video=mjpeg` für Snapshot-Track (wenn GPU übrig hat).
### Weg B — H.264 Hardware-Encode + MJPEG-Passthrough (Option B oben)
```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).
Bei **Lösung 2** (MJPEG): `/api/frame.jpeg` = natives Kamera-JPEG, volle Qualität, gratis.

View File

@@ -25,20 +25,13 @@ configs:
# Komplette go2rtc-Config eingebettet keine separate Datei nötig.
content: |
streams:
# Option C — ffmpeg: mit expliziten Input-Flags, OHNE -re und OHNE -readrate_initial_burst.
# go2rtc ist on-demand: startet FFmpeg erst wenn ein Client verbindet (bestätigt: 0% CPU ohne Client).
# -input_format mjpeg → Kamera-natives MJPEG, kein Pixel-Decode nötig
# -fflags nobuffer → kein Input-Puffer
# -flags low_delay → minimaler Decoder-Delay
# -probesize 32 → keine lange Format-Analyse beim Start
# -analyzeduration 0 → sofortiger Start
# 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"
# MJPEG-Passthrough: Kamera liefert MJPEG nativ → go2rtc reicht es 1:1 durch.
# Kein Encoding, kein libx264, kein VAAPI → CPU <5%, keine Freezes.
# Latenz ~200ms (vs. 130ms bei H.264) — für Roboter-Überwachung ausreichend.
# Hinweis: go2rtc's #hardware funktioniert NICHT mit MJPEG-Kamera-Input
# (hwupload benötigt VAAPI-Decoder auf Input-Seite, MJPEG läuft Software).
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"
webrtc:
listen: ":8555"
candidates:
@@ -54,10 +47,7 @@ configs:
origin: "*"
log:
level: info
# TODO (on-demand Encoding): go2rtc hält den Encoder auch ohne Clients am Laufen.
# 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.
# On-demand bestätigt: go2rtc startet Encoder erst bei erstem Client (0% CPU ohne Client).
services:
@@ -70,8 +60,11 @@ services:
devices:
- /dev/video0:/dev/video0
- /dev/video2:/dev/video2
# /dev/dri nicht mehr nötig: MJPEG-Passthrough braucht keine GPU
group_add:
- 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:
- source: go2rtc_yaml
target: /config/go2rtc.yaml