 
Low-latency audio node written in Rust. It exposes a HTTP API to create/manage audio players and a WebSocket that streams raw PCM for clients (e.g., Discord bots). An example Discord.js client is included in examples/discord-js-bot.
Features
- HTTP API for creating/controlling players
- WebSocket PCM stream (48 kHz, stereo, 16-bit, 20 ms frames)
- Optional resolving/downloading for YouTube/Spotify/SoundCloud links via yt-dlp
- Allow/block URL patterns via regex
- Lightweight EQ and volume filters
- Minimal authentication via static password header
- First-run auto-download of yt-dlpandffmpeginto a user cache (~/.resonix/bin) keeping the executable slim
- Automatic cleanup of downloaded/transcoded temp audio files when not looping; best‑effort cleanup on shutdown
Early preview. APIs may evolve. See License (BSD-3-Clause).
- Build
- Install Rust (stable). Then build:
- Windows PowerShell
- cargo build --release
 
 
- Windows PowerShell
- Configure (optional)
- Copy Resonix.tomlto your working directory and tweak values (lowercaseresonix.tomlis also supported). See Configuration below.
- Run
- Start the server binary from the repository root. Default bind: 0.0.0.0:2333.
- Try it
- Create a player for a URL, then connect a WS client to stream PCM.
Base URL: http://<host>:<port> (default http://127.0.0.1:2333). If a password is set in config, include header: Authorization: <password>.
Endpoints
- 
POST /players→ Create player- Request JSON: { "id": string, "uri": string }
- Behavior: Validates against allow/block patterns. If resolver is enabled, attempts to resolve page URLs (YouTube/Spotify/SoundCloud) to a direct audio file before playback.
- Responses: 201 { "id": string },403(blocked),409(exists),400(bad input)
 
- Request JSON: 
- 
POST /players/{id}/play→ Resume playback- Response: 204or404
 
- Response: 
- 
POST /players/{id}/pause→ Pause playback- Response: 204or404
 
- Response: 
- 
PATCH /players/{id}/filters→ Update filters- Request JSON: { "volume"?: number(0.0..5.0), "eq"?: [{ "band": 0..4, "gain_db": number }] }
- Response: 204or404
 
- Request JSON: 
- 
DELETE /players/{id}→ Stop and remove player- Response: 204or404
 
- Response: 
- 
GET /resolve?url=<encoded>→ Resolve to a direct audio file (if resolver enabled)- Responses: 200 <path-or-url>,400on errors,400if resolver disabled
 
- Responses: 
WebSocket stream
- URL: ws://<host>:<port>/players/{id}/ws
- Frames: binary, interleaved little-endian i16 PCM
- Sample rate: 48,000 Hz
- Channels: 2 (stereo)
- Frame size: 960 samples/channel (20 ms), 3,840 bytes per packet
- A single silent priming frame is sent first
 
The server loads configuration from resonix.toml (lowercase) or Resonix.toml in the current working directory. Environment variables can override some resolver options.
TOML sections and keys
- 
[server]- host(string) → default- "0.0.0.0"
- port(u16) → default- 2333
- password(string, optional) → if set, all requests must include header- Authorization: <password>
 
- 
[logging]- clean_log_on_start(bool) → truncate- .logs/latest.logon startup; default- true
 
- 
[resolver]- enabled(bool) → default- false
- ytdlp_path(string) → default- "yt-dlp"(can be overridden by- YTDLP_PATHenv)
- ffmpeg_path(string, optional) → default- "ffmpeg"(can be overridden by- FFMPEG_PATHenv)
- timeout_ms(u64) → default- 20000
- preferred_format(string) → default- "140"(m4a)
- allow_spotify_title_search(bool) → default- true(resolves Spotify URLs via title search)
 
- 
[spotify]- client_id(string, optional) → Either the literal client id OR the NAME of an env var containing it.
- client_secret(string, optional) → Either the literal client secret OR the NAME of an env var containing it.
- Behavior: If set to a string that matches an existing environment variable, that env var’s value is used. Otherwise the string is treated as the literal credential. If not provided, defaults to reading SPOTIFY_CLIENT_IDandSPOTIFY_CLIENT_SECRETfrom the environment.
 
- 
[sources]- allowed(array of regex strings) → if empty, all allowed unless blocked
- blocked(array of regex strings) → takes priority over allowed
 
Environment overrides
- RESONIX_RESOLVE=1|true→ enable resolver
- YTDLP_PATH=...→ explicit path to- yt-dlp
- FFMPEG_PATH=...→ explicit path to- ffmpeg
- RESOLVE_TIMEOUT_MS=...→ override timeout
- SPOTIFY_CLIENT_ID/- SPOTIFY_CLIENT_SECRET→ fallback env vars if- [spotify]section is omitted.- You can also set custom env var names and reference them from the config, e.g.: client_id = "MY_APP_SPOTIFY_ID"and then setMY_APP_SPOTIFY_IDin your.envor environment.
 
- You can also set custom env var names and reference them from the config, e.g.: 
- (legacy) RESONIX_EMBED_EXTRACT_DIRis ignored now; tools are stored in~/.resonix/bin(runtime exportRESONIX_TOOLS_DIRshows the resolved directory)
Runtime export (informational)
- On startup the resolved paths are placed into RESONIX_YTDLP_BIN/RESONIX_FFMPEG_BINenv vars for child processes spawned by the node. Normally you do not need to set these manually.
On startup Resonix checks for yt-dlp and ffmpeg.
Resolution order (per tool):
- Explicit env (YTDLP_PATH/FFMPEG_PATH)
- Config (resolver.ytdlp_path/resolver.ffmpeg_path)
- Auto-managed download to ~/.resonix/bin(created if missing)
If only one tool is missing, only that one is downloaded. Existing executables are left untouched. Delete a file to force re-download of the latest release.
macOS: ffmpeg is not auto-downloaded (install via Homebrew: brew install ffmpeg).
Notes
- The resolver downloads temporary audio files using yt-dlp. Ensure sufficient disk space and legal use in your jurisdiction.
- For sources needing remux/extraction, ffmpegis required.
- Cleanup: If loop mode is not enabled (neither tracknorqueue), Resonix deletes any temporary audio file it created for the finished track. On process shutdown, Resonix also best‑effort removes leftover temp files with theresonix_prefix from the OS temp directory.
See examples/discord-js-bot for a minimal Discord.js bot that connects to the node over WebSocket and plays a URL.
Prereqs
- Rust toolchain, cargo
- Optional: yt-dlpin PATH for resolver;ffmpegrecommended (used by yt-dlp to extract consistent audio formats)
Common tasks
- Format: cargo fmt(configured viarustfmt.toml)
- Build debug: cargo build
- Build release: cargo build --release
Project layout
- src/→ application code
- src/api/handlers.rs→ HTTP/WS handlers
- src/middleware/auth.rs→ simple auth middleware (Authorization header equals password)
- src/config/→ config loading and effective config
- src/audio/→ decoding, DSP, player
- Resonix.toml→ example configuration
Basic flags:
- --version,- -V,- -version→ print version and exit
- --init-config→ create- Resonix.tomlin the current directory (fails if it already exists) and exit
If no flag is passed, the server starts normally.
Report vulnerabilities via GitHub Security Advisories (see SECURITY.md). Do not open public issues for sensitive reports.
BSD 3-Clause. See LICENSE.