-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Description
Implement a comprehensive music playback module for NerpyBot with a single-command slash interface and interactive button-based controls via persistent now-playing embed. The bot will automatically join the user's voice channel and display an interactive embed with playback controls as buttons instead of separate slash commands.
Slash Commands
Playback Initiation
/play <song_url|playlist_url>- Only slash command. Play a song or entire playlist by URL. Automatically joins the user's current voice channel. If a song is already playing, adds to queue. Sends the now-playing embed with interactive controls to the channel.
Playlist Management (slash command group)
/playlist list- Display all user-created playlists/playlist show [playlist name]- Display all songs in a specific playlist/playlist create [playlist name] [from._playing]- Create a new playlist/playlist add [playlist name] [song_url]- Add a song to a playlist/playlist remove [playlist name] [song_url]- Remove a song from a playlist
Now Playing Embed & Interactive Controls
The bot sends an embed to the channel containing:
Embed Content
- Song Title
- Artist Name
- Album Artwork
- Track Duration
- Progress Bar (e.g.,
[=====>-----] 2:30 / 5:00) - Requested By (user who played the song)
Interactive Buttons
- ⏯️ Play/Pause - Toggle playback (button label changes based on state)
- ⏭️ Skip - Skip to next track in queue
- ⏹️ Stop - Stop playback and clear queue
- 📋 Playlist - Show current queue as paginated list
Button Behavior
- Buttons update in real-time as state changes (pause button becomes play button when paused, etc.)
- Only users with appropriate permissions can interact with buttons
- Embed auto-updates as the song progresses (every ~5-10 seconds)
Acceptance Criteria
-
/playaccepts both song URLs and playlist URLs - Bot automatically joins user's current voice channel
- Now-playing embed displays all required metadata
- Interactive buttons correctly control playback (no slash commands for control)
- Progress bar updates in real-time
- Button states reflect current playback state (pause vs play, etc.)
- Playlists persist across bot restarts (database storage)
- Users can create, view, and manage their own playlists
- Appropriate error handling for invalid songs, API errors, and permission issues
- Unit tests cover core functionality
Architecture Changes
Remove/Deprecate
/skip,/pause,/resume,/stop,/nowplaying(replaced by buttons)/queuegroup (replaced by/playlistgroup + buttons)- Slash-command-based playback control
Add
- Persistent interactive embed with button handlers
- Embed auto-update loop (progress tracking)
- Button permission checks (mute_members for stop/skip)
- Now-playing state tracking per guild
Nice-to-Have
-
Premature streaming - Begin playback as soon as sufficient buffer data is available (e.g., 10-30 seconds) rather than waiting for full download to complete. Continue downloading remaining audio in background. Significantly reduces perceived latency.
-
Download progress in embed - Display download progress while buffering (e.g., "Downloading... 45%" or a progress bar). Updates in real-time as data is fetched.
-
Estimated download time - Calculate and display estimated time-to-play based on current download speed and file size. Updates as speed fluctuates. Example: "~12 seconds remaining" or "Buffering... 3s"
-
Maximum song duration limit (configurable, e.g., 10 minutes)
-
Playlist sharing between users
-
Search suggestions for ambiguous song queries
-
Reaction-based emoji voting to skip (alternative to buttons)
Technical Notes
Architecture
- Integrate with existing
voicecontrolmodule (may consolidate) - Update
Audioclass to expose pause/resume methods via discord.py VoiceClient - Add button interaction handlers to Music cog
- Leverage
discord.pyView/Button system for interactive embeds - Use existing
NerpyPy/utils/download.pyand audio utilities where possible
Streaming Optimization (for premature streaming)
- Modify
download()inutils/download.py— Return a file-like object that supports reading before the full file is downloaded (rather than blocking until complete) - Add progress tracking — Expose download progress (bytes downloaded / total bytes) to calculate ETA and fill the embed's progress bar
- Update
Audio._play()inutils/audio.py— Instead of waiting forsong.fetch_buffer()to complete, start playing once minimum buffer threshold is reached - Update now-playing embed — While downloading, show "Buffering..." state with progress indicator; once playing, show the regular progress bar
This leverages yt-dlp's streaming capability and discord.py's audio buffering to provide near-instant playback for YouTube streams.