IoT e IA

Eventos MQTT de Frigate explicados: topics, payloads y alertas remotas

Aprende qué publica Frigate NVR por MQTT, cómo leer el payload de frigate/events y cómo reenviar a un broker en la nube solo las detecciones importantes para recibir notificaciones remotas.

Diagrama de Frigate MQTT con cámaras de seguridad, un NVR que detecta a una persona y un mensaje de evento que viaja a un broker MQTT en la nube
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

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:

  1. after.id es estable durante toda la vida del objeto; úsalo para eliminar duplicados.
  2. after.top_score es la mejor confianza vista hasta el momento, más fiable que la score instantánea.
  3. after.false_positive pasa a false cuando Frigate está seguro de que el objeto es real. Alertar antes de ese momento solo genera ruido.
  4. after.entered_zones te permite alertar solo cuando alguien entra realmente en el camino, no cuando pasa por la calle.
  5. type: end con end_time establecido 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

  1. Frigate registra "Unable to connect to MQTT server". Comprueba que host se resuelve dentro del contenedor de Frigate; allí localhost es el propio contenedor, no la máquina anfitriona.
  2. 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.
  3. No hay eventos, pero la interfaz muestra detecciones. Puede que el objeto no esté en la lista objects.track de la cámara o que un ajuste required_zones lo esté filtrando.
  4. Demasiadas alertas. Alerta según top_score y entered_zones, ignora los update tras el primer reenvío y añade periodos de enfriamiento por cámara si hace falta.
  5. 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.

Artículos relacionados

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.