Es ruckelt leider…

Im vorherigen Beitrag zum Thema habe ich Frigate installiert, um Aufnahmen vom Vogelstream lokal speichern zu können. Möglicherweise ist das Overkill sowohl für den Raspberry Pi 4, also auch den tatsächlichen Anforderungen. Es funktioniert prinzipiell, aber leider hat der Stream auf Twitch etwas zum Stottern angefangen. Woran liegt das konkret?

Decode, Encode

Wie ich erst im Nachhinein gelernt habe, muss der eigentlich fertige Videostream (in h264 Codec) noch einmal decodiert und anschließend wieder encodiert werden. Das liegt am Funktionsprinzip von Frigate, welches einerseits Objekt- und Bewegungserkennung vornimmt (dafür muss der Stream bereits zerlegt werden) und andererseits daraus 10 Sekunden Segmente erstellt. Diese Segmente gewährleisten ein schnelles Durchsehen der Aufnahmen auf der Weboberfläche von Frigate. Kurz gesagt: Man entkommt der Transkodiererei nicht. Was also tun?

Auf der Hardware Acceleration Seite der Frigate Doku findet sich ein Abschnitt zu Raspberry Pi 3 und 4. Denn man muss die Hardwarebeschleunigung erst konfigurieren, damit nicht alles über den leicht zu überfordernden Prozessor laufen muss.

Dazu braucht es die folgenden Zeilen in der config.yml von Frigate…

ffmpeg:  hwaccel_args: preset-rpi-64-h264

… sowie für Docker die Erlaubnis die Hardwarebeschleunigung auch zu nutzen:

services:  frigate:    ...    devices:      - /dev/video11:/dev/video11

Falls man nicht einen Raspi 4 (der hat /dev/video11) verwendet kann man mit diesem Befehl in der Kommandozeile überprüfen, wo sich “H264” versteckt:

for d in /dev/video*; do
  echo -e "---\n$d"
  v4l2-ctl --list-formats-ext -d $d
done

Da muss man sich aber durch alle video Devices durchscrollen. Den obigen Befehl kann man mittels grep erweitern und so nur mehr die gewünschten Zeilen anzeigen lassen:

for d in /dev/video*; do
  if v4l2-ctl --list-formats-ext -d "$d" | grep -q "H264"; then
    echo -e "---\n$d"
    v4l2-ctl --list-formats-ext -d "$d" | grep -A 4 "H264"
  fi
done

So wird die Ausgabe viel aufgeräumter:

Wem das noch nicht kompakt genug ist, hier noch die Einzeilerversion…

for d in /dev/video*; do v4l2-ctl --list-formats-ext -d "$d" | grep -q "H264" && echo -e "---\n$d" && v4l2-ctl --list-formats-ext -d "$d" | grep -A 4 "H264"; done

… die noch etwas kompakter ist:

Der Befehl lässt sich natürlich auch für h265 gebrauchen, dann ersetzt man einfach “H264” mit “H265”.

Die gesamte config.yml unter /opt/frigate/config schaut so aus:

mqtt:
  enabled: false

cameras:
  vogl_cam:
    ffmpeg:
      inputs:
        - path: rtsp://192.168.0.7:8554/vogl-cam
      hwaccel_args: preset-rpi-64-h264
    detect:
      enabled: false  # Disable motion detection
    record:
      enabled: true  # Enable 24/7 recordings
      retain:
        days: 30  # Keep recordings for 30 days
        mode: all  # Record continuously
      export:
        timelapse_args: -vf setpts=PTS/60 -r 25

#      clips:
#        enabled: false
    snapshots:
      enabled: false

    motion:
      threshold: 5
      contour_area: 10
      improve_contrast: true
record:
  enabled: true  # Global recording settings
  retain:
    days: 30  # Keep recordings for 30 days
    mode: all  # Record continuously
version: 0.15-1

Als relevanter für die Performance wird sich das Ausschalten der Bewegungserkennung erweisen.

Das Docker-Compose File:

version: "3.9"
services:
  frigate:
    container_name: frigate
    privileged: true # this may not be necessary for all setups
    restart: unless-stopped
    image: ghcr.io/blakeblackshear/frigate:stable
    shm_size: "128mb" # update for your cameras based on calculation above
#    devices:
#      - /dev/bus/usb:/dev/bus/usb # passes the USB Coral, needs to be modified for other versions
#      - /dev/apex_0:/dev/apex_0 # passes a PCIe Coral, follow driver instructions here https://coral.ai/docs/m2/get-started/#2a-on-linux
#      - /dev/dri/renderD128 # for intel hwaccel, needs to be updated for your hardware
    devices:
      - /dev/video11:/dev/video11
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /opt/frigate/config/config.yml:/config/config.yml
      - /srv/ssd/frigate:/media/frigate
      - type: tmpfs # Optional: 1GB of memory, reduces SSD/SD Card wear
        target: /tmp/cache
        tmpfs:
          size: 500000000
    ports:
      - "5000:5000"
      - "8556:8554" # RTSP feeds
      - "8557:8555/tcp" # WebRTC over tcp
      - "8557:8555/udp" # WebRTC over udp
    environment:
      FRIGATE_RTSP_PASSWORD: "password"

Hardwarebeschleunigung überprüfen

Mit ps aux | grep ffmpeg | grep -i "hwaccel" kann man schauen, ob der ffmpeg Prozess beschleunigt arbeitet. Man kann auch direkt auf die Docker Logs zugreifen mit:

docker logs frigate 2>&1 | grep -i "hwaccel\|mmal\|omx"

Und leider nicht:

Ich glaube ich muss den Container leider privilegiert laufen lassen. Das wird zumindest empfohlen, auch wenn das sicherheitstechnisch nicht optimal ist.

Stream stottert nicht mehr

Zu meiner Überraschung haben diese Maßnahmen dennoch ausgereicht, um den Livestream Meisen_aus_Urfahr unterbrechungsfrei laufen lassen zu können. Obwohl die HW-Beschleunigung wohl nicht ganz funktioniert hat (also eigentlich nur beim zweiten Codierungsprozess, der Originalstream aus der Kamera nutzt eh die Grafik-Rechenwerke), sehe ich diese Optimierungen als Erfolg an und das Setup kann einmal so bleiben, wie es ist.