Sounds
Overview
The Sounds module provides a per-account audio library. Sounds are uploaded once and can be played directly in browser sources without leaving the dashboard. Extensions can bundle their own sounds and reference them via config fields, and automations can trigger playback in response to stream events.
Sounds are stored in the account's library and played back via the sounds:{accountId} WebSocket channel. Browser sources subscribed to this channel receive sound:play and sound:stop commands and execute them locally, keeping audio latency minimal.
Upload limits
Upload limits are enforced per plan:
| Limit | Free | Pro | Enterprise |
|---|---|---|---|
| Max sounds | 10 | 100 | Configurable |
| Max sound file size | 2 MB | 10 MB | Configurable |
| Max total sound storage | 20 MB | 500 MB | Configurable |
Supported audio formats: MP3, WAV, OGG, FLAC.
Playback in browser sources
Browser sources (layers) that subscribe to sounds:{accountId} receive real-time playback commands. When a sound is played from the dashboard or via automation, the server publishes a sound:play event to the channel and all subscribed browser sources execute the audio locally.
Playback commands include:
sound:play— start playing a specific sound at an optional volume (0.0–1.0).sound:stop— stop playback of a specific sound.
Commands can be targeted to a specific overlay by key or broadcast to all connected browser sources.
Targeting
When triggering sound playback, you can either broadcast to all browser sources or send to a specific overlay:
- All browser sources (default) — every browser source subscribed to the account's sounds channel receives the command.
- Specific overlay — pass the overlay key as the
targetparameter. Only the browser source for that overlay executes the playback.
This is useful when you have multiple overlays (e.g. a gameplay overlay and a facecam overlay) and want sounds to play from one specific source.
RBAC
| Permission | Description | Owner | Admin | Mod | Viewer |
|---|---|---|---|---|---|
sounds:read | View the sound library | x | x | x | x |
sounds:create | Upload new sounds | x | x | ||
sounds:edit | Rename and update sounds | x | x | ||
sounds:delete | Delete sounds from the library | x | x | ||
sounds:play | Trigger and stop sound playback | x | x | x |
Extension-bundled sounds
Extensions can ship their own sounds in the dist/sounds/ directory. When an extension is installed, its bundled sounds are registered in the account's sound library and can be referenced in config fields of type sound.
The lumio deploy command automatically detects audio files placed in dist/sounds/ and includes them in the upload. Bundled sounds are scoped to the extension install — uninstalling the extension removes its sounds from the library.
To reference a bundled sound in lumio.config.json, use a config field of type sound:
{
"config_schema": {
"alertSound": {
"type": "sound",
"label": "Alert sound",
"default": null
}
}
}
The SchemaEditor renders a dropdown picker that lists all sounds in the account's library (including extension-bundled sounds). The stored value is a sound ID (UUID string).
API
GraphQL
| Operation | Permission | Description |
|---|---|---|
sounds(offset, limit, search) | sounds:read | List sounds with pagination and search |
sound(id) | sounds:read | Get a single sound |
updateSound(id, input) | sounds:edit | Rename a sound |
deleteSound(id) | sounds:delete | Delete a sound |
playSound(id, volume, target) | sounds:play | Trigger playback |
stopSound(id, target) | sounds:play | Stop playback |
See GraphQL for the full schema.
REST
| Method | Path | Permission | Description |
|---|---|---|---|
GET | /v1/sounds | sounds:read | List sounds |
GET | /v1/sounds/{id} | sounds:read | Get single sound |
POST | /v1/sounds | sounds:create | Upload sound (multipart) |
PATCH | /v1/sounds/{id} | sounds:edit | Update metadata |
DELETE | /v1/sounds/{id} | sounds:delete | Delete sound |
POST | /v1/sounds/{id}/play | sounds:play | Trigger playback |
POST | /v1/sounds/{id}/stop | sounds:play | Stop playback |
GET | /v1/sounds/{id}/stream | sounds:read | Stream audio bytes |
See REST API for request/response shapes.
WebSocket
Subscribe to sounds:{accountId} to receive real-time playback commands. Requires sounds:read permission and the feature:sounds flag.
See WebSocket for the channel protocol.
Key files
| Path | Description |
|---|---|
apps/api/src/routes/sounds.rs | REST endpoints (list, get, upload, update, delete, play, stop, stream) |
apps/api/src/graphql/sounds.rs | GraphQL queries and mutations |
apps/api/src/db/sounds.rs | Database operations |
apps/api/migrations/20260528000007_sounds.up.sql | Schema migration |