La integración MQTT de Frigate es la forma en que el NVR Frigate avisa al resto de tu sistema de que ha visto una persona, un coche o un perro, y es la manera más limpia de construir alertas y automatizaciones sobre la detección local de objetos. En esta guía conocerás todos los topics que publica Frigate, qué contiene realmente el payload de los eventos y cómo reenviar solo las detecciones importantes desde tu red local a un broker en la nube para recibirlas en cualquier lugar.
Cómo usa Frigate MQTT
Frigate ejecuta la detección de objetos sobre los flujos de tus cámaras de forma local, normalmente con un detector Coral, Hailo, OpenVINO o una GPU. La grabación y la revisión de clips se hacen en su interfaz web, pero todo lo que se basa en eventos sale por MQTT. Frigate es un cliente MQTT: se conecta al broker que le indiques, publica estados y eventos y se suscribe a unos cuantos topics de comandos para que puedas activar o desactivar a distancia la detección, la grabación o las instantáneas.
Este diseño hace que a Frigate no le importe quién consume los datos. Home Assistant, Node-RED, un script de Python o una app MQTT para el móvil pueden suscribirse a los mismos topics a la vez. Si el modelo pub/sub es nuevo para ti, te ayudará entender qué hace un broker MQTT antes de conectarlo todo.
Configurar la sección MQTT en Frigate
El bloque mqtt del config.yml de Frigate lo dirige a un broker. La mayoría de las instalaciones ejecutan un contenedor Mosquitto local junto a Frigate:
mqtt:
enabled: true
host: mosquitto # nombre del contenedor o IP del broker local
port: 1883
topic_prefix: frigate # todos los topics empiezan por esto
client_id: frigate # debe ser único en el broker
user: frigate
password: "{FRIGATE_MQTT_PASSWORD}"
stats_interval: 60 # segundos entre mensajes frigate/stats
cameras:
driveway:
mqtt:
enabled: true # publicar instantáneas de esta cámara
timestamp: false
bounding_box: true
crop: true
height: 270
quality: 70
Dos ajustes provocan la mayoría de los hilos de soporte. Primero, client_id debe ser único: si dos instancias de Frigate comparten el ID por defecto frigate en un mismo broker, se expulsarán mutuamente en bucle. Segundo, si cambias topic_prefix, todas las automatizaciones que escuchan en frigate/... también deben cambiar.
Referencia de topics MQTT de Frigate
Estos son los topics que más usarás, suponiendo el prefijo por defecto frigate:
| Topic | Payload | Para qué sirve |
|---|---|---|
frigate/available |
online / offline |
Salud del NVR; Frigate lo fija como su Last Will |
frigate/events |
JSON con type, before, after |
Ciclo de vida del objeto rastreado: new, update, end |
frigate/reviews |
JSON con el elemento de revisión | Alertas y detecciones agrupadas (versiones recientes) |
frigate/<camera>/<object> |
Número entero | Cuántos objetos de ese tipo hay a la vista ahora mismo |
frigate/<camera>/<object>/snapshot |
Bytes JPEG | Mejor instantánea del objeto actual |
frigate/<camera>/motion |
ON / OFF |
Estado de movimiento en bruto |
frigate/<camera>/detect/set |
ON / OFF |
Comando: activar o desactivar la detección |
frigate/<camera>/detect/state |
ON / OFF |
Estado actual de la detección |
frigate/stats |
JSON | Velocidad de inferencia del detector, CPU, FPS de la cámara |
Existen pares set/state similares para grabaciones, instantáneas y detección de movimiento. Consulta la documentación oficial de MQTT de Frigate para tu versión, porque las versiones más nuevas añaden topics como los elementos de revisión y las actualizaciones de objetos rastreados.
Leer el payload de frigate/events
Cada objeto rastreado produce una secuencia de mensajes en frigate/events: un new, varios mensajes update a medida que el objeto se mueve o mejora la puntuación, y un end cuando sale. Cada mensaje lleva el estado completo del objeto antes y después del cambio. Un ejemplo recortado:
{
"type": "new",
"before": { "id": "1729076512.48-ab12cd", "label": "person", "top_score": 0.0 },
"after": {
"id": "1729076512.48-ab12cd",
"camera": "driveway",
"label": "person",
"score": 0.82,
"top_score": 0.84,
"false_positive": false,
"start_time": 1729076512.48,
"end_time": null,
"current_zones": ["front_path"],
"entered_zones": ["front_path"],
"has_snapshot": true,
"has_clip": false
}
}
Los campos que importan para las alertas:
after.ides estable durante toda la vida del objeto; úsalo para eliminar duplicados.after.top_scorees la mejor confianza vista hasta el momento, más fiable que lascoreinstantánea.after.false_positivepasa afalsecuando Frigate está seguro de que el objeto es real. Alertar antes de ese momento solo genera ruido.after.entered_zoneste permite alertar solo cuando alguien entra realmente en el camino, no cuando pasa por la calle.type: endconend_timeestablecido cierra el evento y es el momento adecuado para obtener el clip a través de la API HTTP de Frigate.
Un error habitual es disparar con cada update. Una persona que cruza el encuadre puede generar muchas actualizaciones, así que una automatización ingenua envía una ráfaga de notificaciones por una sola visita.
Por qué reenviar los eventos de Frigate a un broker en la nube
El broker local es perfecto dentro de casa o de la instalación, pero no es accesible desde tu móvil con datos móviles sin abrir puertos, y exponer Mosquitto a internet es un problema de seguridad. El patrón más seguro es solo saliente: un pequeño reenviador en la misma red se suscribe al broker local, filtra los eventos y publica un JSON compacto en un broker MQTT en la nube. Tu móvil, un panel remoto o una segunda instalación se suscriben allí. Nada queda escuchando en el router de tu casa.
Reenviar también te permite reducir el payload. Las instantáneas pueden ocupar decenas de kilobytes y el servidor MQTT público gratuito de ConnectMQ acepta como máximo 64 KB por mensaje, así que el reenviador envía solo metadatos y deja las imágenes en el servidor Frigate local.
Podrías apuntar Frigate directamente a un broker remoto cambiando host y port y configurando client_id con el client ID emitido junto con tus credenciales, porque ConnectMQ vincula los client IDs a las credenciales. En la práctica es mejor un filtro intermedio: Home Assistant sigue funcionando en local si se cae internet y solo los eventos relevantes salen de la red.
Reenviador en Python: de Frigate local a ConnectMQ
El script siguiente usa paho-mqtt 2.x. Se suscribe al broker local, reenvía un mensaje cuando una persona o un coche se convierte en una detección fiable y otro cuando termina, replica la disponibilidad de Frigate y retransmite a Frigate un comando remoto para activar o desactivar la detección.
pip install "paho-mqtt>=2.0"
import json
import os
import uuid
import paho.mqtt.client as mqtt
LOCAL_HOST = os.getenv("LOCAL_HOST", "localhost")
LOCAL_USER = os.getenv("LOCAL_USER")
LOCAL_PASS = os.getenv("LOCAL_PASS")
REMOTE_HOST = os.getenv("REMOTE_HOST", "broker.connectmq.com")
REMOTE_PORT = int(os.getenv("REMOTE_PORT", "1883"))
REMOTE_USER = os.getenv("REMOTE_USER") # sin definir para el área pública de pruebas
REMOTE_PASS = os.getenv("REMOTE_PASS")
REMOTE_CLIENT_ID = os.getenv("REMOTE_CLIENT_ID", f"frigate-fwd-{uuid.uuid4().hex[:8]}")
PREFIX = os.getenv("REMOTE_PREFIX", f"connectmq/demo/{uuid.uuid4().hex[:8]}/frigate")
LABELS = {"person", "car"}
MIN_SCORE = float(os.getenv("MIN_SCORE", "0.75"))
forwarded = set() # ids de eventos ya anunciados
# ---------- cliente remoto (nube) ----------
remote = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=REMOTE_CLIENT_ID)
if REMOTE_USER:
remote.username_pw_set(REMOTE_USER, REMOTE_PASS)
if REMOTE_PORT == 8883:
remote.tls_set()
remote.will_set(f"{PREFIX}/forwarder/status", "offline", qos=1, retain=True)
def on_remote_connect(client, userdata, flags, reason_code, properties):
print("remote connected:", reason_code)
client.publish(f"{PREFIX}/forwarder/status", "online", qos=1, retain=True)
client.subscribe(f"{PREFIX}/cmd/+/detect", qos=1)
def on_remote_message(client, userdata, msg):
camera = msg.topic.split("/")[-2]
value = msg.payload.decode().upper()
if value in ("ON", "OFF"):
local.publish(f"frigate/{camera}/detect/set", value)
print(f"relayed detect {value} to {camera}")
remote.on_connect = on_remote_connect
remote.on_message = on_remote_message
# ---------- cliente local (Frigate) ----------
local = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"frigate-fwd-local-{uuid.uuid4().hex[:6]}")
if LOCAL_USER:
local.username_pw_set(LOCAL_USER, LOCAL_PASS)
def on_local_connect(client, userdata, flags, reason_code, properties):
print("local connected:", reason_code)
client.subscribe([("frigate/events", 0), ("frigate/available", 0)])
def on_local_message(client, userdata, msg):
if msg.topic == "frigate/available":
remote.publish(f"{PREFIX}/nvr/status", msg.payload, qos=1, retain=True)
return
event = json.loads(msg.payload)
after = event["after"]
if after["label"] not in LABELS or after.get("false_positive", True):
return
event_id = after["id"]
if event["type"] in ("new", "update"):
if event_id in forwarded or after["top_score"] < MIN_SCORE:
return
forwarded.add(event_id)
state = "started"
elif event["type"] == "end":
if event_id not in forwarded:
return
forwarded.discard(event_id)
state = "ended"
else:
return
summary = {
"id": event_id,
"camera": after["camera"],
"label": after["label"],
"score": round(after["top_score"], 2),
"zones": after.get("entered_zones", []),
"state": state,
"start": after["start_time"],
"end": after.get("end_time"),
}
topic = f"{PREFIX}/{after['camera']}/{after['label']}/event"
remote.publish(topic, json.dumps(summary), qos=1)
print("forwarded", topic, summary["state"], summary["score"])
local.on_connect = on_local_connect
local.on_message = on_local_message
remote.connect(REMOTE_HOST, REMOTE_PORT, keepalive=60)
remote.loop_start()
local.connect(LOCAL_HOST, 1883, keepalive=60)
print("forwarding to", PREFIX)
local.loop_forever()
Ejecútalo en el host de Frigate y observa el lado remoto desde cualquier máquina. Usa el prefijo que imprimió el script:
mosquitto_sub -h broker.connectmq.com -p 1883 -i watcher-7f3a2c \
-t 'connectmq/demo/<your-id>/frigate/#' -v
Pasa por delante de una cámara y deberías ver exactamente dos mensajes por visita: started y ended. Para probar la ruta de comandos, publica OFF en connectmq/demo/<your-id>/frigate/cmd/driveway/detect.
El servidor público gratuito lo puede leer cualquiera que adivine el topic, así que trátalo solo como un entorno de pruebas y prototipos, nunca para datos de producción. Para una casa o instalación real, crea un broker privado y configura REMOTE_PORT=8883 y los valores REMOTE_USER, REMOTE_PASS y REMOTE_CLIENT_ID del portal. No ejecutes el relé de comandos sobre un topic público.
Recibir alertas en el móvil
Como el broker en la nube habla MQTT estándar, cualquier cosa que pueda suscribirse puede avisarte: una app cliente MQTT en tu móvil, un flujo de Node-RED que envía un mensaje push a través del servicio de notificaciones que elijas o una instancia remota de Home Assistant. Si construyes un panel en el navegador, conéctate por WebSocket seguro en el puerto 8084 con la ruta /mqtt. En el portal de ConnectMQ, el explorador de topics en directo muestra cómo llegan los eventos reenviados, algo muy útil mientras ajustas MIN_SCORE y las zonas.
Solución de problemas de Frigate MQTT
- Frigate registra "Unable to connect to MQTT server". Comprueba que
hostse resuelve dentro del contenedor de Frigate; allílocalhostes el propio contenedor, no la máquina anfitriona. - La conexión se cae cada pocos segundos. Dos clientes usan el mismo client ID. Da a Frigate y a cada reenviador un ID distinto.
- No hay eventos, pero la interfaz muestra detecciones. Puede que el objeto no esté en la lista
objects.trackde la cámara o que un ajusterequired_zoneslo esté filtrando. - Demasiadas alertas. Alerta según
top_scoreyentered_zones, ignora losupdatetras el primer reenvío y añade periodos de enfriamiento por cámara si hace falta. - El broker remoto rechaza las instantáneas. Superan el límite de tamaño de mensaje; mantén las imágenes en local y envía enlaces o metadatos.
Para pipelines de detección más avanzados, mira cómo funciona la detección de objetos con YOLO sobre MQTT o cómo construir la detección de personas en un ESP32-CAM, y consulta la guía de IA e IoT para una visión de conjunto.
Recibe alertas remotas de Frigate con ConnectMQ
Un broker privado en la nube es la pieza que falta entre un NVR local y unas alertas en las que puedas confiar cuando estás fuera de casa. ConnectMQ es un broker MQTT gestionado con TLS en el puerto 8883, credenciales generadas y un explorador de topics para depurar. Empieza con el plan Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y después apunta el reenviador a tu nuevo broker.
Preguntas frecuentes
¿Frigate necesita un broker MQTT?
MQTT es opcional para la grabación y la interfaz web, pero la integración con Home Assistant y todas las automatizaciones basadas en eventos dependen de él. La mayoría de los usuarios ejecutan Mosquitto en el mismo host.
¿Qué diferencia hay entre frigate/events y frigate/reviews?
frigate/events describe objetos rastreados individuales a lo largo de su ciclo de vida. Los elementos de revisión agrupan la actividad en alertas y detecciones que coinciden con lo que ves en la interfaz de revisión, lo que suele ser mejor para las notificaciones.
¿Puedo enviar instantáneas de Frigate a un broker en la nube?
Solo si caben en el límite de tamaño de mensaje del broker, que es de 64 KB en el servidor MQTT público gratuito. Enviar metadatos y obtener las imágenes de la API de Frigate bajo demanda suele ser más limpio y más barato.
¿Es seguro exponer mi broker Mosquitto local en su lugar?
No se recomienda. Un reenviador saliente hacia un broker autenticado con TLS evita abrir puertos en tu router y mantiene privado el broker local.



