Stream live SiriusXM radio into a Discord voice channel, controlled from a media-player embed.
DiscordXM logs into your SiriusXM account, proxies the HLS audio stream locally, and pipes it into Discord voice through FFmpeg. A persistent player message gives your server channel browsing by genre, prev/next/stop buttons, and live now-playing metadata with album art.
- Live streaming — all 400+ SiriusXM channels, up to 256kbps AAC
- Media-player embed — genre dropdown, paginated channel picker, ⏮ ⏭ ⏹ buttons
- Now-playing metadata — song, artist, album, show, and album art, refreshed automatically
- Slash commands —
/playwith channel autocomplete,/channelssearch - Gapless channel switching — change channels without the bot leaving voice
- Python 3.11+
- FFmpeg on your PATH
- A Discord application with a bot token
- An active SiriusXM streaming subscription (US or Canada)
git clone https://github.com/biceroy/DiscordXM.git
cd DiscordXM
py -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
copy .env.example .env # then fill it in
.venv\Scripts\python.exe -m bot.mainOn Linux/macOS, substitute python3 -m venv .venv and .venv/bin/python.
-
Create an application at the Discord Developer Portal and add a bot.
-
Copy the bot token into
.env. -
Invite the bot with the
botandapplications.commandsscopes and the Connect, Speak, Send Messages, and Embed Links permissions:https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot%20applications.commands&permissions=3164160
Slash commands sync to your server the moment the bot joins.
All configuration lives in .env (see .env.example):
| Variable | Required | Description |
|---|---|---|
DISCORD_TOKEN |
yes | Bot token from the Discord Developer Portal |
SXM_USERNAME |
yes | SiriusXM account username |
SXM_PASSWORD |
yes | SiriusXM account password |
SXM_REGION |
no | US (default) or CA |
SXM_QUALITY |
no | SMALL (64k), MEDIUM (128k), or LARGE (256k, default) |
PROXY_PORT |
no | Local HLS proxy port, default 9999 (loopback only) |
FAVORITE_CHANNELS |
no | Comma-separated channel names/numbers pinned to the ⭐ Favorites dropdown |
| Command | Description |
|---|---|
/play <channel> |
Join your voice channel and play a channel (autocompletes by name or number) |
/player |
Post the media-player embed with dropdowns and buttons |
/channels [search] |
Browse or search the channel lineup |
/stop |
Stop playback and leave voice |
The player embed refreshes about every 20 seconds when the song or show changes. Metadata can trail the audio by 10–30 seconds because of HLS buffering.
SiriusXM API ──> sxm client (auth, channel data, now-playing)
│
├── local HLS proxy (127.0.0.1:9999)
│ │
│ └── FFmpeg ──> discord.py voice ──> your server
│
└── player embed (buttons, dropdowns, album art)
Authentication and stream decryption come from the sxm library. The bot runs the proxy in-process, FFmpeg reads the local playlist, and discord.py sends the Opus audio to voice. One process, no external services.
- Voice connection times out — VPNs commonly break Discord's UDP voice traffic. Disconnect the VPN or split-tunnel Discord. The bot retries each connection once automatically.
- SiriusXM login fails — verify your credentials in the SiriusXM web player first. SiriusXM occasionally changes their unofficial API; the Music Assistant SiriusXM provider uses the same library and is a good place to find current fixes.
- No audio but the bot joins — confirm
ffmpegruns from the same terminal, and test the proxy directly withpython scripts/smoke_test.py octane.
This project uses SiriusXM's unofficial web API and is not affiliated with or endorsed by SiriusXM. It requires your own paid subscription and is intended for personal use in a single private server. Don't redistribute streams.