0004 – go2rtc as media server, streams only in memory
Status: accepted
Context
Section titled “Context”Cameras speak different protocols (Tapo protocol, RTSP, ONVIF), have a limited number of connections and often an audio return channel (backchannel) only through manufacturer-specific ways. Several consumers (audio, vision, live view, snapshots) need the same streams.
Decision
Section titled “Decision”go2rtc (1.9.14) as its own container. The core registers streams at runtime through the
API and consumes them by RTSP (ffmpeg) or HTTP. Audio output: the core provides a live WAV
stream paced in real time, which go2rtc pulls into the camera’s backchannel. Streams with
credentials are created only in memory (PATCH /api/streams). The configuration file
is read-only and contains no cameras.
Alternatives
Section titled “Alternatives”- Directly from the core with ffmpeg/PyAV: every camera connected several times, no Tapo backchannel.
- Frigate/MediaMTX: Frigate brings its own vision pipeline; MediaMTX cannot do the Tapo backchannel.
Consequences
Section titled “Consequences”- One camera connection, many consumers. Exception: the speaker gets its own short-lived
stream
<stream>_talkper conversation, because a Tapo camera only plays the talk session opened last (AUDIO.md). - go2rtc forgets the streams on a restart. A watchdog in the core compares the registered
streams with those in go2rtc every 5 s and restores missing ones. Tested: after
docker compose restart go2rtcsnapshots of the C200 worked again after 2 s, the microphones kept running. Before (without the watchdog) the camera stayed unreachable permanently. This was only discovered while checking this ADR. - The core paces the output itself and therefore knows the output time of every frame. This is the basis of the echo handling (0005).
- Found during testing: a
PUTon/api/streamswrites the source with credentials intogo2rtc.yaml. Therefore onlyPATCHis used.