Skip to content

feat: Music playback system with playlist management and interactive controls #229

@karaktaka

Description

@karaktaka

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

  • /play accepts 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)
  • /queue group (replaced by /playlist group + 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 voicecontrol module (may consolidate)
  • Update Audio class to expose pause/resume methods via discord.py VoiceClient
  • Add button interaction handlers to Music cog
  • Leverage discord.py View/Button system for interactive embeds
  • Use existing NerpyPy/utils/download.py and audio utilities where possible

Streaming Optimization (for premature streaming)

  1. Modify download() in utils/download.py — Return a file-like object that supports reading before the full file is downloaded (rather than blocking until complete)
  2. Add progress tracking — Expose download progress (bytes downloaded / total bytes) to calculate ETA and fill the embed's progress bar
  3. Update Audio._play() in utils/audio.py — Instead of waiting for song.fetch_buffer() to complete, start playing once minimum buffer threshold is reached
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions