Build Discord music bots in TypeScript.

Discord Player gives you queues, playback controls, events, and a plugin system for audio sources, so a play command is a few lines of code.

Get started

Start a v8 projectDev

npm create music-bot@dev

Generates a TypeScript or JavaScript bot with play, pause, skip, and queue commands. Read the guide

Join our official support server

AndrozDev

Get help and share what you build.

Join server
import { Client, GatewayIntentBits } from 'discord.js';
import { Player } from 'discord-player';
import { DefaultExtractors } from '@discord-player/extractor';

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildVoiceStates,
  ],
});

const player = new Player(client);

await player.extractors.loadMulti(DefaultExtractors);

// Inside your /play command
const { track } = await player.play(voiceChannel, query, {
  nodeOptions: { metadata: interaction.channel },
});

v7 is the stable release.

Queues, playback, and events

The same calls work in v7 and v8.
Queue
addTrack, moveTrack, and setRepeatMode change what plays next. History, shuffle, and filters live on the same queue.
Playback
Pause, resume, seek, volume, and skip are on queue.node.
Events
player.events emits queue events such as playerStart, playerFinish, playerError, and emptyQueue. The queue is always the first argument.
import { QueueRepeatMode, type Track } from 'discord-player';

async function manage(guildId: string, track: Track) {
  const queue = player.nodes.get(guildId);

  if (!queue) return; // Nothing has been played in this guild yet

  // Queue
  queue.addTrack(track);
  queue.moveTrack(track, 0);
  queue.setRepeatMode(QueueRepeatMode.QUEUE);

  // Playback
  await queue.node.pause();
  await queue.node.seek(30_000);
  await queue.node.setVolume(70);
  await queue.node.skip();
}

// Events
player.events.on('playerStart', (queue, track) => {
  const channel = queue.metadata as { send(content: string): unknown };

  channel.send(`Now playing **${track.title}**`);
});

player.events.on('playerError', (queue, error) => {
  console.error('Playback failed:', error);
});

What's new in v8Dev

v8 plays audio through Remedia, a native engine that decodes audio and sends it to Discord voice. Your queues, events, and commands keep the same shape.

You choose where Remedia runs.

Embedded

Remedia runs inside your bot process.

const player = new Player({
  nodes: [{ id: 'local', type: 'embedded' }],
  plugins: [directMedia()],
  send,
});

Remote

Remedia runs in remedia-server, on another machine if you like.

const player = new Player({
  nodes: [
    {
      id: 'audio-1',
      type: 'remote',
      url: 'remedias://audio.example.com',
      auth: {
        username: 'bot',
        password: process.env.REMEDIA_PASSWORD!,
      },
    },
  ],
  plugins: [directMedia()],
  send,
});

Migration guideRemote playbackRemote source hosts

Community

30 open-source bots and 14 extractors, built by the community.

Documentation