A feature-rich Discord music bot with a web control panel — stream from YouTube with real-time queue management through both Discord slash commands and a browser interface.
- Play music from YouTube (search or direct URLs)
- Playlist support
- Queue management (add, remove, reorder, shuffle)
- Playback controls (play, pause, skip, stop)
- Loop controls
- Web UI with Discord OAuth authentication
- Real-time updates via Socket.io
src/
config/ # Environment config
core/ # musicManager, player, queue (central state)
integrations/ # Spotify & YouTube integrations
persistence/ # SQLite db.js + schema.sql
services/ # playback, resolver, trackResolver, resolutionManager
shared/ # formatTime, queueHelpers
transports/
discord/ # Discord.js client, voice, commands
http/ # Express REST API (middleware, routes)
realtime/ # Socket.io server
utils/ # logger
index.js # Entry point
- Node.js 22+
- A Discord application with bot token
- FFmpeg (for audio processing)
- yt-dlp (for YouTube streaming)
# Linux/macOS (recommended)
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp
chmod a+rx /usr/local/bin/yt-dlp
# Or via pip
pip install yt-dlp
# Verify installation
yt-dlp --versionYT_DLP_PATH is auto-detected (local ./bin/yt-dlp, Docker /app/bin/yt-dlp, or system yt-dlp). Set it manually only for custom paths.
npm installCopy .env.sample to .env and fill in your credentials:
cp .env.sample .envRequired variables:
DISCORD_TOKEN- Your bot token from Discord Developer PortalAPP_ID- Your application IDGUILD_ID- Your Discord server ID (restricts web UI to this server's members)DISCORD_CLIENT_SECRET- OAuth client secret (for web UI)JWT_SECRET- Random string for JWT signingOAUTH_REDIRECT_URI- OAuth callback URL (Discord redirects here after login)WEB_URL- Frontend URL; used for CORS and as the destination the server redirects back to after the OAuth flow completes
Optional variables:
TRUST_PROXY- Reverse-proxy hop count. Leave unset for direct local runs; set to1when running behind a single reverse proxy / Docker so the rate limiter sees the real client IP. It is a hop count, not a boolean — do not set it totrue.LOG_LEVEL-error|warn|info|debug(defaultinfo).YT_DLP_MAX_CONCURRENCY(default 4),YT_DLP_MAX_QUEUE(default 50),YT_DLP_STREAM_TIMEOUT_MS(default 15000) - yt-dlp resource limits.
npm run registernpm start
# or for development with auto-reload:
npm run dev| Command | Description |
|---|---|
/join |
Join your voice channel |
/leave |
Leave the voice channel |
/play <query> |
Play a song (URL or search) |
/pause |
Pause playback |
/resume |
Resume playback |
/skip |
Skip to next track |
/stop |
Stop playback and clear queue |
/queue |
View current queue |
/nowplaying |
Show current track |
/remove <position> |
Remove track from queue |
/shuffle |
Shuffle the queue |
/clear |
Clear the queue |
/loop <off/track/queue> |
Set loop mode |
/webui |
Get web control panel link |
The bot includes a web control panel accessible at http://localhost:5173 (or your configured WEB_URL).
Features:
- Discord OAuth login
- Real-time queue display
- Playback controls
- Search and add songs
- Drag-and-drop queue reordering
GET /api/health- Health checkGET /api/auth/discord- Start OAuth flowGET /api/auth/me- Get current userPOST /api/auth/logout- End sessionGET /api/queue- Get queuePOST /api/queue- Add trackDELETE /api/queue/:position- Remove trackPATCH /api/queue/reorder- Reorder tracksPOST /api/queue/shuffle- Shuffle queueGET /api/queue/search- Search YouTubeGET /api/queue/history- Get play historyGET /api/player- Get player statePOST /api/player/:action- Control playback
# Start with auto-reload
npm run dev
# Register commands globally
npm run registerFor local UI development without configuring Discord OAuth redirect URLs, set:
developerMode=true
When enabled, the API bypasses login and treats you as an authenticated Developer user.
YouTube frequently changes their systems. Keep yt-dlp updated to avoid streaming issues:
# Manual update
yt-dlp -U
# Or delete bin/yt-dlp and run npm run setup to re-download
rm bin/yt-dlp && npm run setup| Error | Cause | Solution |
|---|---|---|
Sign in to confirm you're not a bot |
Rate limited | Add cookies file via YT_DLP_COOKIES |
Video unavailable |
Region/age restriction | Use VPN or cookies |
Unable to extract |
yt-dlp outdated | Run yt-dlp -U |
For age-restricted content or rate limiting issues, export your YouTube cookies:
- Use a browser extension to export cookies to a file
- Set
YT_DLP_COOKIES=/path/to/cookies.txtin your.env
MIT
