Unifi Video NVR Camera Motion MQTT Gifs

Inspired by this post , I have developed a python script (and dockerized it) to poll motion detection events from Unifi Video NVR attached cameras.
When a new “lastRecordingId” is detected (and recording is not still in progress), the related video is downloaded, a gif is generated and sent to an MQTT topic.

This project is not based on Unifi Video video directories changes like the inspiring project, but on undocumented NVR APIs.

Check out the README file on the github page.

Hope someone will find it useful.

Buy Me A Coffee

Check out also my similar project for Synology cameras.

1 Like

This looks really cool, going to try it soon. However, the documentation is a bit difficult to understand. Could you expand on making it more easy to follow for beginners?

For example, I’m not sure how to use this exactly. Once the Docker image is running, what is the next step?

How do you get the JSON based config file passed in on the command line from Docker?

Do the gifs get “posted” to MQTT with the local URL or something? How do you automatically send the gifs to your phone via a notify action in Home Assistant?

Would be really helpful if the steps were more clearly laid out and easier to follow. I definitely want to give your script a try @fabtesta, hopefully you can help out.

I try to recap in simple steps.

Follow the documentation to make sure the configuration is well setup

This is a sample docker-compose snippet

unifi-nvr-api-motion-mqtt-gifs:
    container_name: unifi_nvr_api_motion_mqtt_gifs
    image: fabtesta/unifi-nvr-api-motion-mqtt-gifs:latest
    volumes:
      - ./unifi-nvr-api-motion-mqtt-gifs:/config
      - ./unifi-nvr-api-motion-mqtt-gifs:/data
      - /tmp/gifs:/gifs
    restart: always

You can place your config json in “unifi-nvr-api-motion-mqtt-gifs” folder relative to compose file.

Gifs are save under “ffmpeg_working_folder” configured path. The name of the gif is published to camera configured topic.
Now you should setup a sensor in home-assistant to detect gif name changes.

- platform: mqtt
  name: "Sample Camera Gif"
  state_topic: "cameras/gifs/sample"

Now it’s up to your automation to send the gif where you need to.
Example: telegram bot

- alias: "Telegram - Camera Motion - Gif"
  trigger:
    - platform: state
      entity_id: sensor.sample_camera_gif
  action:
    - service: telegram_bot.send_document
      data_template:
        message: 'Sample Camera Motion'
        target:
          - !secret telegram_chat_id
        file: /camera_gifs/{{ states.sensor.sample_camera_gif.state }}
        caption: 'Sample Camera Motion'

Remember that the path “/camera_gifs/{{ states.sensor.sample_camera_gif.state }}” is the same of first container gifs bind mount, so the HA container container must include the same volume:

hass:
    container_name: hass
    ....
    volumes:
      - ./config:/config
      - /tmp/gifs:/camera_gifs <---- SAME SOURCE FOLDER OF FIRST CONTAINER
    ....

Finally don’t forget to whitelist the bind mounted directory to HA instance in your configuration.yml (homeassistant section)

whitelist_external_dirs:
    - /camera_gifs

What if I just want to use this integration for a motion event?
Since there is no easy way I can find to get motion events from Unifi cameras.

Yes you can, but has some latency because of the api polling delay, video download and gif creation.
It’s much easier to watch unifi nvr log files to detect immediately the motion events.
There are some bash scripts around.

Something like this.
Change the motion log path and cameras ids accordingly.
Instead of sending mqtt message, you can do anything you want with bash.

Prerequisite: inotify-tools

#!/bin/bash

# Unifi Video Vars
UNIFI_MOTION_LOG=/var/log/unifi-video/motion.log

# MQTT Vars
MQTT_SERVER="127.0.0.1"
MQTT_PORT="1883"
MQTT_TOPIC_BASE="unifi-cameras/motion"

# Camera Defs
CAM1_NAME="UVC_G3_1"
CAM1_ID="FCECDAD9A6E8"
CAM2_NAME="UVC_G3_2"
CAM2_ID="FCECDAD9A6E9"
CAM3_NAME="UVC_G3_3"
CAM3_ID="FCECDAD9A6E0"

# --------------------------------------------------------------------------------
# Script starts here

while inotifywait -e modify $UNIFI_MOTION_LOG; do
  LAST_MESSAGE=`tail -n1 $UNIFI_MOTION_LOG`
  LAST_CAM=`echo $LAST_MESSAGE | awk -F '[][]' '{print $2}'`
  LAST_EVENT=`echo $LAST_MESSAGE | cut -d ':' -f 5 | cut -d ' ' -f 1`

  if echo $LAST_CAM | grep -n1 $CAM1_ID; then
    # Camera 1 triggered
	  if [[ $LAST_EVENT == "start" ]]; then
	    echo "Motion started on $CAM1_NAME"
	    mosquitto_pub -h $MQTT_SERVER -t $MQTT_TOPIC_BASE/$CAM1_NAME -m "ON" &
	  else
	    echo "Motion stopped on $CAM1_NAME"
	    mosquitto_pub -h $MQTT_SERVER -t $MQTT_TOPIC_BASE/$CAM1_NAME -m "OFF" &
	  fi
  fi

  if echo $LAST_CAM | grep -n1 $CAM2_ID; then
    # Camera 2 triggered
	  if [[ $LAST_EVENT == "start" ]]; then
	    echo "Motion started on $CAM2_NAME"
	    mosquitto_pub -h $MQTT_SERVER -t $MQTT_TOPIC_BASE/$CAM2_NAME -m "ON" &
	  else
	    echo "Motion stopped on $CAM2_NAME"
	    mosquitto_pub -h $MQTT_SERVER -t $MQTT_TOPIC_BASE/$CAM2_NAME -m "OFF" &
	  fi
  fi

  if echo $LAST_CAM | grep -n1 $CAM3_ID; then
    # Camera 3 triggered
	  if [[ $LAST_EVENT == "start" ]]; then
	    echo "Motion started on $CAM3_NAME"
	    mosquitto_pub -h $MQTT_SERVER -t $MQTT_TOPIC_BASE/$CAM3_NAME -m "ON" &
	  else
	    echo "Motion stopped on $CAM3_NAME"
	    mosquitto_pub -h $MQTT_SERVER -t $MQTT_TOPIC_BASE/$CAM3_NAME -m "OFF" &
	  fi
  fi
done
1 Like

I like the idea! Where do you place this file, and what should it be named?

It’s a bash script. You can name it whatever you want and run it on startup.