This project hosts a lightweight Node.js web app that connects to your UniFi Protect Alarm Manager, allowing you to send and trigger custom AI voice messages (TTS) through your Protect speakers.
Each time you trigger an automation, the system updates the message text on your alarm automation, saves it, and triggers it instantly through the Integration v1 API.
⸻
• 🎙️ Custom AI Text-to-Speech messages on UniFi Protect speakers
• 🔐 Automatic login using your Protect username and password
• ⚙️ Edits and triggers alarms through Integration v1
• 🔁 Cache-busting system ensures new audio plays every time
• 🧩 Supports multiple buttons for different horns/alarms
• 🖥️ Simple local web interface (Node.js + Express)
• 🚀 Simple Web API to call
⸻
• Node.js v18+
• Access to your UniFi Protect NVR
• Runs on local network (same as your Protect NVR)
• A valid local Protect username/password with admin rights
• A Protect Integration API key
• One or more Alarm Automations with a Webhook trigger and Play Text on Speaker action
⸻
1. Clone the Repository
git clone https://github.com/JTylerH/unifi-aihorn-dynamic-tts
cd unifi-aihorn-dynamic-tts
npm install2. Create Your .env File
Create a file named .env in the project root:
NVR=https://<your_protect_console_ip>
PROTECT_USER=<your_local_username>
PROTECT_PASS=<your_local_password>
PROTECT_API_KEY=<your_integration_api_key>
PORT=5173GET PROTECT_USER & PROTECT_PASS
To configure a UniFi local-only user, navigate to Admins & Users in your UniFi Network Application or UniFi OS, click the add icon (+), and then select "Restrict to local access only" before filling in the username, password, and role.
GET PROTECT_API_KEY
To configure a UniFi local network API key, perform the following steps:
- Access the UniFi Network Application: Log into your UniFi Network application via its web interface. This can be done by navigating to the IP address or hostname of your UniFi controller, followed by the port (e.g., https://your_unifi_ip:8443).
- Navigate to Integrations: Once logged in, go to Settings > System > Integrations.
- Generate the API Key: Within the Integrations section, locate the API Key generation area. You will likely be prompted to give the API key a name or description for identification purposes. Click the button to generate the API key.
⸻
- Configure Your Alarm Automation
- In the Protect web UI, go to Alarms → Automations.
- Create or edit an automation for your horn or speaker.
- Add a Webhook condition.
- Add an Action → Play Text on Speaker and select your speaker.
- Save the automation.
⸻
4. Get Your Automation ID
When editing an alarm, look at your browser’s URL:
https://<your_console_ip>/protect/alarms/edit/68c45eb203dec703e41j1643
The last part (68c45eb203dec703e41j1643) is your Automation ID.
You’ll use this ID for your buttons in the API or JSON setup file.
⸻
5. For API Only Usage (continue to step 7 and come back here)
curl -X POST http://localhost:5173/api/say \
-H "Content-Type: application/json" \
-d '{
"message": "Attention players! We will be closing in 30 minutes.",
"automation_uuid": "68e45ab203dec703e41f1643"
}'⸻
6. Creating Trigger Buttons
To edit the buttons open /public/setup/alarms.json and add one line per Automation UUID. The program starts with 3 buttons. You will need to update them with your Automation UUIDs.
Example:
[
{ "id": "a1", "label": "Airhorn 1", "automation_uuid": "68e45ab203dec703e41f1643" },
{ "id": "a2", "label": "Airhorn 2", "automation_uuid": "68e535e40106c703e4226b67" },
{ "id": "a3", "label": "All Horns", "automation_uuid": "68e5374102b8c703e422724e" }
]Each button sends its automation_uuid to the Node.js backend, which updates and triggers that alarm’s TTS message.
⸻
7. Start the Server Locally
npm startOpen your browser to: 👉 http://localhost:5173
Type your custom message, click a button, and your speaker will play your new AI-generated TTS message!
⸻
You can add and edit snippets in /public/setup/snippets.json
[
{ "id": "s1", "text": "Attention please — maintenance in progress." },
{ "id": "s2", "text": "Welcome! Please check in at the front desk." }
]Click a snippet to load it into the message field. Hold Shift while clicking to append.
⸻
1. Login to UniFi Protect (session + CSRF token stored)
2. Retrieve automation details using automation_uuid
3. Extract speaker deviceId + webhook UUID
4. Update the automation’s Play Text on Speaker message
5. Save (cache-bust) → re-enable → trigger webhook
6. The new message plays instantly through the linked speaker
⸻
• The app must run on the same network as your Protect NVR (for local API access).
• API keys and credentials should stay local only.
• Never expose this app to the internet without authentication.
⸻
This Node.js web app acts as a Custom TTS controller for your UniFi Protect AI Horns — dynamically updating and triggering alarms with fresh messages using the Protect Integration v1 API.
It’s designed for instant, local, reliable performance — great for event alerts, voice notifications, or just for fun airhorn-style announcements 🎺