Pre-Flight Checklist
| # | Check | Comando | Esperado |
| 1 | CSI conectada | libcamera-hello --list-cameras | Available cameras: 1 |
| 2 | vchiq permisos | ls -la /dev/vchiq | crw-rw---- video group |
| 3 | GPU memory | vcgencmd get_mem gpu | gpu=128M (mínimo) |
| 4 | dtoverlay | grep camera /boot/config.txt | camera_auto_detect=1 |
| 5 | Puerto 8554 libre | ss -tlnp | grep 8554 | (vacío) |
| 6 | RAM disponible | free -m | awk '/Mem/{print $7}' | ≥ 500 MB |
| 7 | Binario descargado | ./mediamtx --version | v1.x.x |
| 8 | USB fallback | v4l2-ctl --list-devices | Detectar /dev/video0 si USB |
Instalación del Binario
VERSION="1.11.1"
wget -q "https://github.com/bluenviron/mediamtx/releases/download/v${VERSION}/mediamtx_v${VERSION}_linux_armv7.tar.gz"
tar xzf mediamtx_v${VERSION}_linux_armv7.tar.gz
sudo mv mediamtx /usr/local/bin/
sudo mv mediamtx.yml /etc/mediamtx/mediamtx.yml
chmod +x /usr/local/bin/mediamtx
Go produce binarios estáticos: sin dependencias de runtime. Verificar que armv7 es compatible con RPi 3B (BCM2837 ARMv8 ejecuta ARMv7 en 32-bit OS).
Detección CSI / USB
CONFIG_DIR="/etc/mediamtx"
if libcamera-hello --list-cameras 2>/dev/null | grep -q "Available cameras: [1-9]"; then
echo "[detect] CSI camera detected → rpiCamera source"
cp "$CONFIG_DIR/mediamtx-csi.yml" "$CONFIG_DIR/mediamtx.yml"
elif [ -e /dev/video0 ]; then
echo "[detect] USB camera detected → ffmpeg exec source"
cp "$CONFIG_DIR/mediamtx-usb.yml" "$CONFIG_DIR/mediamtx.yml"
echo "[detect] WARN: go2rtc es mejor opción para USB"
else
echo "[detect] ERROR: No camera found"
exit 1
fi
Si se detecta USB, considerar no arrancar MediaMTX y activar go2rtc (Arq. 3) en su lugar. MediaMTX con USB necesita ffmpeg intermediario → pierde ventaja.
Unidad systemd
[Unit]
Description=MediaMTX RTSP/HLS/WebRTC Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=mediamtx
Group=video
ExecStartPre=/usr/local/bin/hardware_detect.sh
ExecStart=/usr/local/bin/mediamtx /etc/mediamtx/mediamtx.yml
Restart=on-failure
RestartSec=5
MemoryMax=80M
CPUQuota=40%
StandardOutput=journal
StandardError=journal
SupplementaryGroups=video
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/run/mediamtx
[Install]
WantedBy=multi-user.target
sudo useradd -r -s /usr/sbin/nologin -G video mediamtx
sudo systemctl daemon-reload
sudo systemctl enable --now mediamtx
Docker (alternativa)
services:
mediamtx:
image: bluenviron/mediamtx:latest
restart: unless-stopped
network_mode: host
volumes:
- /etc/mediamtx/mediamtx.yml:/mediamtx.yml:ro
devices:
- /dev/vchiq:/dev/vchiq
- /dev/video0:/dev/video0
group_add:
- video
mem_limit: 80m
cpus: 0.4
network_mode: host es necesario para que los puertos RTSP/HLS/WebRTC funcionen sin port mapping complejo. El dispositivo /dev/vchiq da acceso al coprocesador VideoCore para rpicam nativo.
Estrategia de Fallback
┌─────────────────────────────────────────────┐
│ hardware_detect.sh │
│ │
│ ¿CSI detectada? │
│ SÍ → MediaMTX (rpiCamera) ← ÓPTIMO │
│ NO → ¿USB detectada? │
│ SÍ → go2rtc (V4L2) ← MEJOR USB │
│ NO → ERROR (sin cámara) │
│ │
│ Fallback de servicio: │
│ MediaMTX crash (3×) → go2rtc (RTSP in) │
│ go2rtc crash (3×) → µStreamer (MJPEG) │
│ todo falla → snapshot cron │
└─────────────────────────────────────────────┘
Encadenar servicios con OnFailure= en systemd para activar la siguiente arquitectura automáticamente.
Monitoreo
| Métrica | Comando / Endpoint | Umbral alarma |
| Paths activos | curl -s localhost:9997/v3/paths/list | jq '.items | length' | = 0 (sin streams) |
| Sesiones WebRTC | curl -s localhost:9997/v3/webrtcsessions/list | jq '.items | length' | Informativo |
| RAM proceso | ps -o rss= -p $(pgrep mediamtx) | awk '{print $1/1024"M"}' | > 60 MB |
| CPU | top -bn1 -p $(pgrep mediamtx) | awk 'NR>7{print $9}' | > 30% |
| GPU temp | vcgencmd measure_temp | > 70°C |
| Servicio activo | systemctl is-active mediamtx | != active |
| HLS accesible | curl -so /dev/null -w '%{http_code}' localhost:8888/solar-cam/ | != 200 |
Presupuesto de Recursos
| Componente | RAM | CPU idle | CPU stream |
| MediaMTX (rpicam CSI) | ~15–30 MB | ~1% | ~5% |
| Oasis (Node.js) | ~80 MB | ~2% | ~3% |
| Mumble audio (opcional) | ~15 MB | ~1% | ~3% |
| node-datachannel | ~20 MB | ~0% | ~5% |
| Sistema (Bookworm) | ~120 MB | — | — |
| TOTAL | ~250–265 MB | ~4% | ~16% |
| Disponible en 1 GB: ~735–750 MB libres |
Arq. 2 es la más ligera con vídeo real (vs ~490 MB de Arq. 5, ~350 MB de Arq. 3). La diferencia: rpicam nativo no necesita ffmpeg residente para vídeo CSI.
deploy
systemd
Docker
vchiq
hardware_detect
fallback
monitoreo
API v3
rpicam
250 MB