Music — Internet Radio in Voice Channels
GrumpyMusic streams internet radio (SHOUTcast / Icecast) into a voice channel — either interactively (a user starts it from their voice channel) or passively (the bot lives permanently in a fixed channel and pauses when nobody is listening).
On track changes, the bot shows "🎵 Station · Artist - Title" as the voice channel status below the channel name — visible in the voice list.
Activation
In configs/config.yml:
addons:
music: true
channels:
radio: "VOICE_CHANNEL_ID" # Optional — fallback channel for passive mode
On first start, configs/modules/music.yml is created from the template. Then run /radio reload or restart the bot.
music.yml
configs/modules/music.yml:
enabled: true
autoLeaveSeconds: 60 # Interactive: how long to stay when all listeners leave
defaultVolume: 80 # Volume 0-200 (Discord scale; 100 = original volume)
presets:
- id: technobase
label: TechnoBase.FM
url: https://listen.technobase.fm/tunein-mp3
description: Hands Up & Dance — the classic
color: '#FF1F4A'
- id: hardbase
label: HardBase.FM
url: https://listen.hardbase.fm/tunein-mp3
description: Hardstyle / Hardcore — no mercy
color: '#FF6F00'
- id: housetime
label: HouseTime.FM
url: https://listen.housetime.fm/tunein-mp3
description: House — relaxed to driving
color: '#1E88E5'
- id: trancebase
label: TranceBase.FM
url: https://listen.trancebase.fm/tunein-mp3
description: Trance — epic & uplifting
color: '#7B1FA2'
- id: clubtime
label: ClubTime.FM
url: https://listen.clubtime.fm/tunein-mp3
description: Club & EDM — party sound
color: '#E91E63'
- id: coretime
label: CoreTime.FM
url: https://listen.coretime.fm/tunein-mp3
description: Hardcore & Frenchcore
color: '#B71C1C'
- id: replayfm
label: ReplayFM
url: https://listen.replay.fm/tunein-mp3
description: 90s/2000s Throwback Hits
color: '#00897B'
passive:
enabled: false
channelId: "0" # 0 = falls back to channels.radio from config.yml
stationId: technobase
pauseWhenEmpty: true
Fields
| Field | Default | Meaning |
|---|---|---|
enabled |
true |
Master toggle. Even if addons.music: true, the module can be disabled here. |
autoLeaveSeconds |
60 |
Interactive mode: how long the bot stays when nobody is in the channel (0 = leave immediately). |
defaultVolume |
80 |
Volume 0-200 (Discord scale; 100 = original volume). |
presets |
7 default stations | List of available radio stations (see above). Can be extended freely. |
presets[].id |
— | Unique ID for /radio start (lowercase, no spaces). |
presets[].url |
— | Direct stream URL (Icecast/SHOUTcast — .mp3/.aac). |
presets[].color |
— | Hex color #RRGGBB for the embed color. |
passive.enabled |
false |
Enable passive mode (bot lives permanently in a channel). |
passive.channelId |
"0" |
Voice channel for passive mode. 0 → uses channels.radio from config.yml. |
passive.stationId |
technobase |
Which preset station is played continuously. |
passive.pauseWhenEmpty |
true |
Pauses the stream when nobody is listening — saves CPU and bandwidth. |
Modes
Interactive
A user joins a voice channel and runs /radio start <station> — the bot joins the same channel and plays the stream. Once the channel is empty, autoLeaveSeconds counts down and the bot disconnects automatically.
1. User in #voice-3 → /radio start station: technobase
2. Bot joins #voice-3, plays TechnoBase.FM
3. User leaves → 60s timer starts
4. Nobody returns → bot disconnects, status cleared
Passive
The bot lives permanently in the configured channel and always plays the passive stream. pauseWhenEmpty: true pauses the stream when nobody is listening and resumes when someone joins.
Control:
/radio passive enable channel: <voice-channel> station: technobase
/radio passive disable
/radio passive status
/radio passive enable writes the settings to music.yml and joins the channel immediately.
Commands
| Command | Permission | Function |
|---|---|---|
/radio start <station> |
Everyone (must be in a voice channel) | Start a stream in the current voice channel |
/radio stop |
Everyone | Stop the stream and clear the channel status |
/radio info |
Everyone | Current stream + now playing |
/radio list |
Everyone | List all available stations |
/radio reload |
Manage Server | Reload music.yml |
/radio passive enable channel:<ch> station:<id> |
Manage Server | Enable passive mode |
/radio passive disable |
Manage Server | Disable passive mode, bot disconnects |
/radio passive status |
Manage Server | Current passive mode status |
Voice Channel Status (Now Playing)
On every track change, the bot updates the voice channel status to:
🎵 TechnoBase.FM · Cascada - Everytime We Touch
The status appears below the channel name in the Discord voice list — no additional text message needed. The status is cleared when /radio stop is run.
Permission: The bot needs
SET_VOICE_CHANNEL_STATUS(1<<48) for the channel or server. Without this permission, radio continues to work normally — only the now-playing status is missing.
Track info comes from the Icecast inline metadata stream (icy-metaint header). The bot reads metadata frames in parallel with the audio.
Robustness
GrumpyMusic is designed for unstable streams:
- 1 MB pre-buffer (≈ 60s @ 128 kbps) absorbs CDN jitter — playback stays smooth even if the stream briefly stutters.
- Browser user-agent on HTTP fetch. Some CDNs block ffmpeg's default
Lavf/...UA — the bot presents itself as a normal player. - Exponential backoff on stream errors: 1s → 2s → 4s → 8s → 16s. Maximum 5 attempts in a 60s window, then stop with a log entry.
- Per-guild start lock: If someone runs
/radio startmultiple times quickly, the race condition is locked — no leaked voice connections. - Color-coded embeds: Each station has its own
color— embeds for/radio start,/radio info, etc. are immediately visually identifiable.
Permissions
The bot needs the following in the voice channel:
| Permission | Required? | Reason |
|---|---|---|
View Channel |
✅ | See the channel |
Connect |
✅ | Join the channel |
Speak |
✅ | Send audio |
Set Voice Channel Status (1<<48) |
Optional | Now-playing status — audio works normally without it |
FAQ
What happens if the station URL returns a 403/404?
The bot logs the error, retries 5 times with exponential backoff, then gives up. /radio info shows the last error.
Can I add custom stations?
Yes — add a new block to presets:, then run /radio reload. Important: id must be unique (lowercase, no spaces).
Does it work with YouTube / Spotify? No — GrumpyMusic is explicitly designed for internet radio streams (Icecast/SHOUTcast). No search, no queue, no YouTube integration. For those use cases, SinusBot or a dedicated music bot is a better fit.
What happens on bot restart in passive mode? The bot automatically rejoins the configured channel and restarts the stream — no manual intervention required.
How do I change the passive channel?
Run /radio passive enable channel: <new-channel> station: <id> — the bot disconnects from the old channel and joins the new one.
GrumpyCore Wiki
⚙️ Setup
🔧 Core-Module
🆕 Neue Module
💬 Commands
👥 Staff
GrumpyCore Wiki (English)
⚙️ Setup
🔧 Core Modules
🆕 New Modules
💬 Commands
👥 Staff