MediaMTX on caneast-site1-ot2-cam01¶
Status: Tier 3 Platform Document Last Updated: 2026-05-03 WI: WI-400
Overview¶
MediaMTX v1.18.1 runs on caneast-site1-ot2-cam01 as a dedicated RTSP/HLS/WebRTC server. It provides continuous low-latency camera streaming to Frigate NVR and optionally to browsers or Home Assistant directly.
MediaMTX is managed by the cam01-mediamtx Ansible role and runs as a dedicated system user.
Installation¶
Binary: /usr/local/bin/mediamtx (statically linked Go binary)
Config: /etc/mediamtx/mediamtx.yml
Version: 1.18.1 (arm64, pinned with checksum)
Source: https://github.com/bluenviron/mediamtx/releases/download/v1.18.1/mediamtx_v1.18.1_linux_arm64v8.tar.gz
The binary is downloaded by Ansible with SHA256 checksum verification:
sha256:REDACTED
Configuration¶
The rpiCamera source drives the IMX708 (Camera Module 3) directly through MediaMTX's bundled libcamera v0.5.0+59. System libcamera (v0.7.0 on Trixie) is not used at runtime.
logLevel: info
logDestinations: [stdout]
rtsp: true
rtspAddress: :8554
rtmp: false
hls: true
hlsAddress: :8888
hlsAlwaysRemux: false
webrtc: true
webrtcAddress: :8889
srt: false
paths:
cam01:
source: rpiCamera
rpiCameraWidth: 1920
rpiCameraHeight: 1080
rpiCameraFPS: 5
rpiCameraCodec: softwareH264
rpiCameraIDRPeriod: 60
softwareH264 on Pi 5¶
The Pi 5 (BCM2712/RP1) does not expose the VC4-style V4L2 M2M H264 encoder that Pi 4 used.
Setting rpiCameraCodec: hardwareH264 fails with:
softwareH264 uses OpenH264 via MediaMTX's bundled libcamera build. The Pi 5's quad-core
Cortex-A76 handles 1080p at 5fps with minimal CPU load (observed: ~8% on one core).
Systemd Unit¶
The service runs as mediamtx:mediamtx system user (no login shell, no home directory) with
SupplementaryGroups=video to access /dev/media* and /dev/video* devices.
Key settings:
- User=mediamtx, Group=mediamtx, SupplementaryGroups=video
- Restart=on-failure, RestartSec=5
- PrivateTmp=true
Enable and start:
Integration with cam01-capture¶
The cam01-capture service uses Option A camera contention: MediaMTX holds /dev/media*
continuously during streaming. On a door-open event, capture.py releases the camera:
subprocess.run(["sudo", "/usr/bin/systemctl", "stop", "cam01-mediamtx"], ...)
try:
rpicam-still --immediate --output /tmp/cam01_latest.jpg ...
finally:
subprocess.run(["sudo", "/usr/bin/systemctl", "start", "cam01-mediamtx"], ...)
The try/finally guard ensures MediaMTX is always restarted even if capture fails.
Stream gap per door event is approximately 2 seconds.
sudoers Entry¶
/etc/sudoers.d/cam01-mediamtx grants cam01 user passwordless systemctl control:
cam01 ALL=(root) NOPASSWD: /usr/bin/systemctl stop cam01-mediamtx, /usr/bin/systemctl start cam01-mediamtx
Viewing Streams¶
Three paths are available without additional infrastructure:
| Path | URL | Notes |
|---|---|---|
| Frigate web UI | https://frigate.peries.ca | Traefik TLS, continuous + event recording |
| HLS (browser) | http://REDACTED:[REDACTED]/cam01 | Works in any browser, ~2-4s latency |
| WebRTC (browser) | http://REDACTED:[REDACTED]/cam01 | Sub-second latency, LAN only |
| RTSP (VLC/HA) | rtsp://REDACTED:[REDACTED]/cam01 | Home Assistant Frigate integration |
Operational Notes¶
Check service status:
Verify stream is live:
Frigate stats (via Frigate API or UI):
- camera_fps: 5.x confirms MediaMTX is streaming
- skipped_fps: 0.0 confirms Frigate is consuming all frames
If MediaMTX fails to start after capture:
The Restart=on-failure, RestartSec=5 policy handles transient failures automatically.
Check journalctl -u cam01-mediamtx for encoder_create or device busy errors.
Ansible Role¶
The cam01-mediamtx role in ansible/roles/cam01-mediamtx/ manages the full lifecycle:
download, binary install, config deploy, sudoers, systemd enable+start.
Deploy:
References¶
- cam01 Vision Capture Pipeline -- full pipeline architecture
- Frigate NVR on caneast-site1-node4 -- Frigate k3s deployment and configuration
- WI-400 -- cam01 MediaMTX integration and Option A camera contention implementation