Skip to main content

Overview

Discord Player is designed for discord.js but provides compatibility layers for Eris and Oceanic.js through proxy adapters. These adapters create a compatibility interface that makes Eris/Oceanic clients work seamlessly with Discord Player.
The Eris and Oceanic compatibility layers are experimental and create proxy objects to bridge API differences. Some advanced features may not work as expected.

Using with Oceanic.js

Installation

First, install the required packages:
npm install discord-player oceanic.js

Setup

Use the createOceanicCompat function to wrap your Oceanic client:
import { Client } from 'oceanic.js';
import { Player, createOceanicCompat } from 'discord-player';

const client = new Client({
  auth: 'Bot YOUR_TOKEN',
  gateway: {
    intents: ['GUILDS', 'GUILD_VOICE_STATES']
  }
});

// Create compatibility layer
const compatClient = createOceanicCompat(client);

// Use with Discord Player
const player = new Player(compatClient);

await client.connect();

How It Works

The createOceanicCompat function creates a proxy object that:
  1. Intercepts voice state update events
  2. Translates Oceanic.js API to discord.js-compatible format
  3. Proxies user, guild, and channel managers
  4. Sets up voice gateway adapter creators
export function createOceanicCompat(client: Oceanic.Client): Client {
  // Creates proxy intercepting:
  // - client.users (manager proxy)
  // - client.guilds (manager proxy)
  // - client.channels (manager proxy)
  // - voiceStateUpdate events
  // - voice gateway adapters
}

Using with Eris

Installation

npm install discord-player eris

Setup

Use the createErisCompat function to wrap your Eris client:
import Eris from 'eris';
import { Player, createErisCompat } from 'discord-player';

const client = new Eris.Client('Bot YOUR_TOKEN', {
  intents: ['guilds', 'guildVoiceStates']
});

// Create compatibility layer
const compatClient = createErisCompat(client);

// Use with Discord Player
const player = new Player(compatClient);

client.connect();

Event Differences

Eris uses rawWS event while Oceanic uses packet:
// Eris listens to:
client.on('rawWS', (packet) => {
  // Handle VOICE_STATE_UPDATE and VOICE_SERVER_UPDATE
});

// Oceanic listens to:
client.on('packet', (packet) => {
  // Handle VOICE_STATE_UPDATE and VOICE_SERVER_UPDATE
});

Complete Example (Oceanic)

import { Client } from 'oceanic.js';
import { Player, createOceanicCompat } from 'discord-player';

const client = new Client({
  auth: 'Bot YOUR_TOKEN',
  gateway: {
    intents: ['GUILDS', 'GUILD_VOICE_STATES', 'GUILD_MESSAGES']
  }
});

const compatClient = createOceanicCompat(client);
const player = new Player(compatClient);

// Load extractors
await player.extractors.loadDefault();

client.on('ready', () => {
  console.log(`Logged in as ${client.user.username}`);
});

client.on('messageCreate', async (message) => {
  if (message.content === '!play') {
    const channel = message.member?.voiceState?.channelID;
    if (!channel) return;
    
    const voiceChannel = client.getChannel(channel);
    const result = await player.search('Never Gonna Give You Up');
    
    if (!result.hasTracks()) {
      await message.channel.createMessage('No results found!');
      return;
    }
    
    const queue = player.queues.create(message.guildID, {
      metadata: { channel: message.channel }
    });
    
    await queue.connect(voiceChannel);
    queue.addTrack(result.tracks[0]);
    
    if (!queue.isPlaying()) {
      await queue.node.play();
    }
    
    await message.channel.createMessage(`Now playing: ${result.tracks[0].title}`);
  }
});

await client.connect();

Complete Example (Eris)

import Eris from 'eris';
import { Player, createErisCompat } from 'discord-player';

const client = new Eris.Client('Bot YOUR_TOKEN', {
  intents: ['guilds', 'guildVoiceStates', 'guildMessages']
});

const compatClient = createErisCompat(client);
const player = new Player(compatClient);

await player.extractors.loadDefault();

client.on('ready', () => {
  console.log(`Logged in as ${client.user.username}`);
});

client.on('messageCreate', async (message) => {
  if (message.content === '!play') {
    const member = message.member;
    if (!member?.voiceState?.channelID) return;
    
    const voiceChannel = client.getChannel(member.voiceState.channelID);
    const result = await player.search('Never Gonna Give You Up');
    
    if (!result.hasTracks()) {
      await client.createMessage(message.channel.id, 'No results found!');
      return;
    }
    
    const queue = player.queues.create(message.guildID, {
      metadata: { channel: message.channel }
    });
    
    await queue.connect(voiceChannel);
    queue.addTrack(result.tracks[0]);
    
    if (!queue.isPlaying()) {
      await queue.node.play();
    }
    
    await client.createMessage(
      message.channel.id,
      `Now playing: ${result.tracks[0].title}`
    );
  }
});

client.connect();

API Translation

The compatibility layer translates between discord.js and Eris/Oceanic APIs:

User Manager

// discord.js style
client.users.cache.get(id);
client.users.resolve(resolvable);
client.users.resolveId(resolvable);

// Works with Eris/Oceanic after compat
compatClient.users.cache.get(id);
compatClient.users.resolve(resolvable);
compatClient.users.resolveId(resolvable);

Guild Manager

// discord.js style
client.guilds.cache.get(id);
client.guilds.resolve(resolvable);

// Works with Eris/Oceanic after compat
compatClient.guilds.cache.get(id);
compatClient.guilds.resolve(resolvable);

Channel Manager

// discord.js style
client.channels.cache.get(id);
client.channels.resolve(resolvable);

// Works with Eris/Oceanic after compat
compatClient.channels.cache.get(id);
compatClient.channels.resolve(resolvable);

Voice Channels

The proxy adds discord.js-compatible methods to voice channels:
// These methods are added by the compat layer
channel.isVoiceBased(); // Returns true for voice/stage
channel.isVoice();      // Returns true for voice channels
channel.isStage();      // Returns true for stage channels

Voice Adapter

The compatibility layer creates voice gateway adapters:
// For Oceanic
function oceanicVoiceAdapterCreator(guild, client) {
  return (methods) => {
    return {
      sendPayload(payload) {
        if (guild.shard.status !== 'ready') return false;
        guild.shard.send(payload.op, payload.d);
        return true;
      },
      destroy() {
        // Cleanup
      }
    };
  };
}

// For Eris
function erisVoiceAdapterCreator(guild, client) {
  return (methods) => {
    return {
      sendPayload(payload) {
        if (guild.shard.status !== 'ready') return false;
        guild.shard.sendWS(payload.op, payload.d);
        return true;
      },
      destroy() {
        // Cleanup
      }
    };
  };
}

Detecting Client Type

You can check which library is being used:
import { getCompatName, isErisProxy, isOceanicProxy } from 'discord-player';

const compatName = getCompatName(client);
console.log(compatName); // 'Eris', 'Oceanic', or null

if (isErisProxy(client)) {
  console.log('Using Eris compatibility layer');
}

if (isOceanicProxy(client)) {
  console.log('Using Oceanic compatibility layer');
}

Limitations

Some features may not work perfectly with the compatibility layers:
  • Some discord.js-specific events may not be fully supported
  • Type definitions may show discord.js types even when using Eris/Oceanic
  • Advanced voice features may behave differently
  • Custom client extensions may not be proxied

Comparison

discord.js

  • Native support
  • Full feature set
  • Best compatibility

Oceanic.js

  • Via compatibility layer
  • Most features work
  • Some limitations

Eris

  • Via compatibility layer
  • Most features work
  • Some limitations

Best Practices

The compatibility layers are experimental. Test all features thoroughly in your specific use case.
If you encounter issues with the compatibility layers, report them with details about your setup.
For the best experience and full feature support, use discord.js as the primary library.
Ensure both Discord Player and your chosen library are up to date for best compatibility.

Checking Compatibility

You can check if a client is compatible:
import { isErisClient, isOceanicClient } from 'discord-player';

if (isErisClient(client)) {
  console.log('This is an Eris client');
}

if (isOceanicClient(client)) {
  console.log('This is an Oceanic client');
}

Getting Started

Basic setup with discord.js

Player API

Learn about the Player class

Build docs developers (and LLMs) love