Beatled Server
Source code: github.com/oost/beatled (server/)
The beat server is a C++ application that captures audio, detects beats in real time, and distributes timing data to LED controllers over UDP. It also serves an HTTPS REST API and the React web dashboard.
Architecture
| Module | Description |
|---|---|
beat_detector | Audio capture (PortAudio) and real-time beat detection (BTrack) |
core | State management, configuration, client registry |
server/http | HTTPS REST API (RESTinio + OpenSSL) and static file serving |
server/udp_server | UDP request handler for device registration and time sync |
server/tempo_broadcaster | Per-beat tempo dispatch + on-change PROGRAM push (unicast by default, see --broadcast-mode) |
server/logger | Ring-buffer logger exposed via the /api/log endpoint |
Local Development
# Build and start the HTTPS server with the web client
./beatled.sh server start --start-http
# With UDP server for LED controllers
./beatled.sh server start --start-http --start-udp
# With the per-beat tempo dispatcher running (default mode: unicast,
# with per-client one-way-delay compensation). See Deployment for
# --broadcast-mode={unicast,subnet,limited}.
./beatled.sh server start --start-http --start-udp --start-broadcast
# With CORS for the Vite dev server
./beatled.sh server start --start-http --cors-origin "https://localhost:5173"
# With Bearer token authentication
./beatled.sh server start --start-http --api-token "secret"
# Run server tests
./beatled.sh test server
The server is built with CMake and uses vcpkg for dependency management. The first build will configure CMake and install dependencies automatically.
Prerequisites
- macOS:
brew install pkg-config cmake libtool automake autoconf autoconf-archive - vcpkg: Must be installed and
VCPKG_ROOTset in your environment - A USB microphone for audio capture (or use a virtual audio device for testing)
Custom Test Domain
The default development domain is beatled.test. To use it locally, add an entry to /etc/hosts:
sudo sh -c 'echo "127.0.0.1 beatled.test" >> /etc/hosts'
Or open /etc/hosts in an editor and add the line manually:
127.0.0.1 beatled.test
On a Raspberry Pi, point the domain to the Pi’s IP instead:
192.168.1.100 beatled.test
The .test TLD is reserved by IANA for testing and will never resolve publicly, making it safe for local development.
TLS Certificates
The server requires TLS certificates for HTTPS. Generate self-signed certificates for local development:
# Default domain (beatled.test)
./beatled.sh certs
# Or specify one or more domains
./beatled.sh certs beatled.test localhost 127.0.0.1
This creates certificates in server/certs/ using mkcert. The server expects cert.pem, key.pem, and dh_param.pem.
For iOS Simulator, install the mkcert root CA so the app trusts self-signed certs:
xcrun simctl keychain booted add-root-cert "$(mkcert -CAROOT)/rootCA.pem"
API Authentication
When started with --api-token, the server requires a Bearer token for all API requests:
Authorization: Bearer <token>
Cross-Compilation and Deployment
Cross-compile for Raspberry Pi (ARM64) using Docker:
git submodule update --init --recursive # first time only
./beatled.sh build rpi
./beatled.sh server deploy <username> <host>
See the Deployment page for the full guide covering certificates, service management, and troubleshooting.
Dependencies
Managed via vcpkg (pinned to a specific commit for reproducibility):
| Library | Purpose |
|---|---|
| asio | Async networking |
| restinio | HTTP/HTTPS server |
| nlohmann-json | JSON parsing |
| spdlog / fmt | Logging and formatting |
| portaudio | Audio capture |
| fftw3 | FFT for beat detection |
| openssl | TLS support |
| catch2 | Unit testing |