

Melodix — Self-hosted Discord music bot & CLI player
Presented by Señor Mega.
Powered by Go, FFmpeg, and questionable engineering decisions.
Melodix is a music player you can run as a Discord bot (plays in voice channels) or as a CLI app (plays on your machine). Same playback engine for both: YouTube, SoundCloud, and internet radio with various parsers.
Table of contents
Features
- Discord bot — Slash commands, voice channel playback, one bot for many servers.
- Voice — Uses Discord’s current voice protocol (DAVE), maintained for today’s Discord clients.
- CLI player — Same engine as the bot: play, next, stop, queue, status. No Discord token required.
- Sources — YouTube (link or search query), SoundCloud, internet radio (direct stream URLs). Input is auto-detected from URL or you can set source and parser explicitly.
- Parsers and resilience — Multiple parsers per track (yt-dlp, kkdai, ffmpeg); automatic fallback if one fails; recovery stream retries on early termination (e.g. network hiccup).
- Queue and controls — One queue per guild (Discord) or per process (CLI). Play, skip, stop, clear.
- Limitations — Cannot play YouTube live streams or region-locked videos. Not every radio stream format is supported. Playback may occasionally pause or vary slightly when retrying with a different stream method.
Try Melodix without installing
- Official Discord server — Join the The Megabyte Order Discord server, go to a voice channel and use the slash commands at the
#bot-music-spam text channel.
- Pre-built binaries — Download a release. Each archive includes melodix-discord (bot) and melodix-cli (terminal player) binaries. For the bot, create an app in the Developer Portal and run the Discord binary; for local playback, run the CLI binary (no Discord token needed).
Commands
- /about — Discover the origin of this bot
- /help — Get a list of available commands
- /help category — View commands grouped by category
- /help group — View commands grouped by group
- /help flat — View all commands as a flat list
🎵 Music
- /music — Control music playback
- /music play — Play a music track
- /music next — Skip to the next track
- /music stop — Stop playback and clear queue
⚙️ Settings
- /commands — Manage or inspect commands
- /commands log — Review recent commands called by users
- /commands status — Check which command groups are enabled or disabled
- /commands toggle — Enable or disable a group of commands
- /commands update — Re-register or update slash commands
- /maintenance — Bot maintenance commands
- /maintenance ping — Check bot latency
- /maintenance download-db — Download the current server database as a JSON file
- /maintenance status — Retrieve statistics about the guild
Music examples: Play by search query or by link. You must be in a voice channel to use /music play.
/music play Never Gonna Give You Up
/music play https://www.youtube.com/watch?v=dQw4w9WgXcQ
/music play http://stream-uk1.radioparadise.com/aac-320
How-to’s
- How to add Melodix to your Discord server — Use the OAuth2 invite link (see Discord bot — Step 1); replace
YOUR_APPLICATION_ID with your app ID, open the URL, choose your server, and authorize. Then use slash commands. To self-host the bot, see Running Melodix yourself.
- How to play your first track — (Discord) Join a voice channel, then run
/music play with a link or search term (e.g. /music play Never Gonna Give You Up).
- How to self-host the bot — Install FFmpeg (and optionally yt-dlp) on your PATH, create a bot in the Discord Developer Portal, set
DISCORD_TOKEN in .env, and run the Discord binary. Full steps: Discord bot — Step 2.
- How to run the CLI player — Build with
go build -o melodix-cli ./cmd/cli or use the melodix-cli binary from releases. No Discord token needed. Commands: play, next, stop, queue, status, quit. See CLI player.
- How to try without installing — Join the official support server and use the bot in a voice channel, or download a release and run the binaries. See Try Melodix without installing.
Running Melodix yourself
You can run the Discord bot (voice channels) or the CLI player (local playback). Both use the same sources and queue logic.
What you need (both modes)
For the Discord bot you also need a Discord bot token from the Discord Developer Portal.
Discord bot — Step 1: Create the bot in Discord
- Open the Discord Developer Portal and create a new application. Note the Application ID (in the “General Information” section).
- Go to the Bot section and create a bot. Copy the token (you will use it as
DISCORD_TOKEN).
- Under Privileged Gateway Intents, enable:
- Presence Intent
- Server Members Intent
- Message Content Intent
-
Invite the bot to your server using this URL (replace YOUR_APPLICATION_ID with your Application ID from step 1):
https://discord.com/oauth2/authorize?client_id=YOUR_APPLICATION_ID&scope=bot&permissions=3238912
This link only requests the permissions the bot needs: View Channel, Send Messages, Embed Links, Read Message History, Manage Messages, Connect to Voice Channel, Speak.
- Open the URL in your browser, choose your server, and authorize. Grant the requested permissions when asked.
Create a .env file in the folder where you run the bot (or set the same variables in your environment):
# Required for the Discord bot
DISCORD_TOKEN=your-discord-bot-token
Optional variables (you can add these to .env if needed):
| Variable |
Description |
Default |
STORAGE_PATH |
Path for bot data (e.g. command state). |
./data/datastore.json |
INIT_SLASH_COMMANDS |
Set to true to register slash commands on every startup. |
false |
DEVELOPER_ID |
Your Discord user ID for developer-only commands. |
(none) |
DISCORD_GUILD_BLACKLIST |
Comma-separated guild IDs the bot will leave. |
(none) |
Run the Discord bot:
- From source:
go build -o melodix-discord ./cmd/discord then run the binary. Ensure DISCORD_TOKEN is set (e.g. in .env).
- From a release: Use the
melodix-discord (or melodix-discord.exe) binary from the releases archive.
- With Docker: See docker/README.md for Docker and Docker Compose instructions.
After the bot is running and invited to your server, use slash commands in any channel. For music, be in a voice channel and use /music play with a link or search term.
CLI player
The CLI player uses the same playback engine but runs in your terminal and plays through your speakers. No Discord token or server setup required.
Run the CLI player:
- From source:
go build -o melodix-cli ./cmd/cli then run the binary.
- From a release: Use the
melodix-cli (or melodix-cli.exe) binary from the releases archive.
CLI commands (at the > prompt):
| Command |
Description |
play <url or query> [source] [parser] |
Add and play (e.g. play https://youtube.com/... or play Never Gonna Give You Up). |
next |
Skip to the next track. |
stop |
Stop playback and clear the queue. |
queue |
Show now playing and the queue. |
status |
Show current track and queue length. |
quit |
Exit. |
Example:
> play Never Gonna Give You Up
> queue
> next
> quit
How it works
- Discord app — The bot connects to Discord, registers slash commands, and handles interactions. For music, it resolves the user’s voice channel, gets or creates a player for the guild, and forwards play/next/stop to that player.
- CLI app — Uses the same player and resolver; a speaker sink instead of a Discord voice sink; same queue and controls.
- Shared core — The pkg/music library provides the player, resolver, stream opening, and sink abstraction. Both the Discord bot and the CLI are thin layers on top.
flowchart TB
User["User"]
DiscordBot["Discord bot"]
CLI["CLI"]
MusicPlayer["Player (pkg/music)"]
Resolver["Resolver"]
Sink["Sink (Discord VC or speaker)"]
User -->|"slash / play"| DiscordBot
User -->|"play command"| CLI
DiscordBot --> MusicPlayer
CLI --> MusicPlayer
MusicPlayer --> Resolver
MusicPlayer --> Sink
Music package overview
The playback pipeline in pkg/music works as follows:
- Resolve — User input (URL or search) goes to the resolver. Sources (YouTube, SoundCloud, radio) match the input and return track metadata (URL, title, list of available parsers). No streaming yet.
- Enqueue — The player enqueues one or more tracks (metadata only). If nothing is playing, the caller typically calls PlayNext.
- PlayNext — Player pops the next track, calls startTrack: opens a RecoveryStream (which wraps TrackStream), starts a playback goroutine that will get a sink and stream PCM.
- Get sink — The playback goroutine asks the sink provider for an AudioSink (Discord: join voice channel and return a sink that encodes PCM to Opus and sends to the VC; CLI: return the speaker sink). If getting the sink fails (e.g. timeout or no permission), playback errors and the queue does not spin.
- Open stream — RecoveryStream opens a TrackStream by trying the track’s parsers in order (e.g. ytdlp-link, kkdai-link, ffmpeg-link). Each parser produces PCM (48 kHz, stereo, 16-bit). If the stream dies early, RecoveryStream can retry with the same or next parser (up to a limit).
- Stream to sink — The player feeds the PCM ReadCloser to AudioSink.Stream. The sink runs until the stream ends or a stop signal is received (Discord: Opus encode and send; CLI: play to speaker).
- Next or stop — When the stream ends, the player can auto-advance to the next track (PlayNext) or stop; Stop(true) clears the queue and releases the sink (e.g. leave VC).
flowchart LR
Resolver["Resolver"]
Player["Player"]
SinkProvider["SinkProvider"]
RecoveryStream["RecoveryStream"]
TrackStream["TrackStream"]
AudioSink["AudioSink"]
Resolver -->|"track metadata"| Player
Player -->|"GetSink"| SinkProvider
SinkProvider -->|"AudioSink"| Player
Player -->|"open"| RecoveryStream
RecoveryStream -->|"PCM stream"| TrackStream
Player -->|"Stream"| AudioSink
Subpackages: player, resolver, sink, sources, parsers, stream. See also pkg/music/README.md for using the library standalone.
Support
For help or questions, use the The Megabyte Order — official Melodix Discord server.
FAQ
- Why does play sometimes take a few seconds? — The bot resolves the input (URL or search) and then opens an audio stream using one of the parsers (yt-dlp, kkdai, ffmpeg). The first time for a track can take a moment; playback then starts.
- Can I use only the music library without Discord? — Yes. The pkg/music library is a standalone Go package. Use the speaker sink and resolver for a CLI or custom app; see pkg/music/README.md and pkg/music/examples/cli_speaker.
- Why is FFmpeg required? — The parsers use FFmpeg to decode various audio formats (YouTube, radio streams, etc.) into PCM that the bot can send to Discord or play locally.
- Why does the bot say it cannot join the voice channel? — The bot needs Connect and Speak permission in that channel. Check the channel (or server) permissions for the bot role.
Troubleshooting
- Bot does not join the voice channel — Ensure the bot has Connect and Speak permission in the channel. If the bot still does not join, check logs for voice-join timeout or permission errors.
- No audio / track never starts — Ensure FFmpeg (and optionally yt-dlp) is on your PATH. Check parser logs for stream open failures. For region-locked or live YouTube content, playback may not be supported.
- CLI: no sound — The CLI uses the speaker sink (ebitengine/oto). Ensure your audio device is available and not muted; on some systems you may need to allow the app to use the microphone/speaker.
Contributing
Contributions are welcome. Open an issue or pull request on GitHub. For larger changes, discuss in the Melodix Discord server first.
License
Melodix is licensed under the MIT License.