Docs/Music system
Advanced · Music

How the music system actually works.

A technical breakdown of the single-connection model, the MongoDB bridge that keeps Discord and the dashboard in sync, and exactly what happens in every voice-channel edge case.

01

One connection per server

Ovels keeps exactly one Lavalink player and voice connection per guild. Discord commands and the Music dashboard both target that same player — there is no per-user or per-channel player.

/join connects to your current voice channel. /play and /search do the same, but only when Ovels isn't already active somewhere else in the server. If it is, every control — dashboard included — requires you to join Ovels' current channel or run /leave first.

Channel checks (for /pause, /skip, /volume and similar) don't trust a single cached field. They fall back through the player's last-known channel and your live Discord voice state, the same way /join, /play and the dashboard bridge do, so a brief lag right after a move or reconnect can't falsely block someone standing in the right channel.

02

Real-time sync between the bot and dashboard

The website and bot can run on entirely separate servers. They never talk to each other directly — everything passes through three MongoDB collections:

  • MusicAction — commands the dashboard queues for the bot (play, pause, skip, seek, remove, sync_voice, and so on).
  • MusicPlayerState — the live player snapshot the bot publishes back (track, position, queue, pause state).
  • MusicVoiceState — each member's current Discord voice channel, seeded on bot startup and updated on every voice move.

The bot re-publishes MusicPlayerState immediately after every direct Discord command and player lifecycle event, on top of a continuous ~500ms fallback publisher. The dashboard polls with cache-busting, force-dynamic requests roughly every 250ms, so a track skipped from Discord updates the browser — and a pause clicked on the dashboard reflects back in Discord — without anyone refreshing the page.

If your selected voice channel ever looks stale, the dashboard's voice panel exposes an on-demand check (the sync_voice action) that re-reads your live Discord voice state instead of waiting for the next automatic refresh.

03

What happens when a channel goes empty

The moment Ovels' voice channel has no human members left, playback is paused immediately — within roughly one poll cycle — rather than continuing to play to an empty room for the full grace period. That auto-pause is tagged internally so it's distinguishable from a pause you triggered on purpose.

At the same time, a 120-second idle timer starts. Any human joining or moving into the channel cancels it and resumes playback from exactly where it left off. The timer is fully re-armed on every voice-state change, not reused, so rapid join/leave/move sequences can't accidentally shorten or extend the window. If the channel is still empty when it expires, the player is destroyed and Ovels leaves.

/leave skips all of this — it destroys the connection and clears the timer immediately. /stop only clears the queue; the voice connection stays up and normal idle handling still applies.

04

Recovering from drops and restarts

Three independent recovery layers keep a session alive through normal network hiccups:

  • Lavalink node reconnects — a persistent watchdog checks every 5 seconds and re-arms the connection whenever a configured node drops, continuing indefinitely rather than giving up after a fixed retry count.
  • Lavalink session resuming — the active session ID is persisted and reused on startup; when a resume succeeds, the existing player's track, position, pause state, voice data and queue are resynchronized rather than restarted.
  • Discord voice recovery — if Ovels is unexpectedly dropped from voice (a Discord blip, not a manual disconnect), it retries every 4 seconds for up to 60 seconds using the last known channel before giving up and tearing the player down cleanly.

If Ovels' voice channel is deleted outright, that's detected directly and the player is destroyed instead of retrying against a channel that no longer exists. And if Ovels is removed from a server entirely — kicked, banned, or the server deletes it — the player, its timers, and the guild's MusicPlayerState, MusicVoiceState and any pending MusicAction documents are all cleaned up immediately, rather than lingering with no way to ever receive another voice event.

05

Seeking, queue edits and permissions

Seeking is validated against the track's actual duration, and is blocked entirely on live streams rather than being silently accepted and passed through. The dashboard's Now Playing progress bar is a real interactive seek control, not a decorative one.

Tracks can be removed from the middle of the queue with /remove <position> or the ✕ button on the dashboard's queue list — both splice the live Lavalink queue by position rather than requiring a full requeue.

Members without full server-management access can still use the dashboard's Music page if an administrator grants the Ovels Music Controller role via /musicrole setup. Revoking that access from the dashboard deletes the actual Discord role, not just the dashboard's stored reference to it.

Looking for commands?This page covers behavior, not syntax. See the Music command reference for every option and cooldown.
Edge case reference

Scenario by scenario.

The specific outcome for every voice-channel situation Ovels is built to handle.

A listener leaves mid-song but others remain+

Nothing happens — playback continues normally.

The last listener leaves mid-song+

Playback pauses within about one poll cycle, and the 120-second idle timer starts. Anyone rejoining resumes it automatically; staying empty for the full 120 seconds disconnects Ovels.

Ovels is dragged to another channel or disconnected by Discord itself+

Up to 60 seconds of voice-recovery retries happen before the player is torn down.

Ovels' voice channel is deleted while connected or idle+

Detected immediately — the player is destroyed instead of retrying forever.

Ovels is kicked or banned from the server entirely+

The player, its timers, and the server's stored music state are all cleaned up right away.

A dashboard action arrives after the player was already destroyed+

It's caught and reported back as an error instead of crashing the request.

You try to seek past the end of a track, or on a live stream+

Rejected — seeking is validated against the real track duration and disabled outright on streams.