TypeScript icon, indicating that this package has built-in type declarations

0.8.5 • Public • Published


npm version downloads downloads downloads


This package is still under heavy development, so there might be some breaking changes. We'll try to make breaking changes as less as we can, but if there's any, we're sorry about that.


This is a simple wrapper of @discordjs/voice library.
You can use this package to build a music bot with your discord.js client easily.

We also have our own Classes and wrapper of ytdl, ytsr to help you process data easier, more logical, and faster. The current support sites are Youtube and SoundCloud (under development).

const { Client } = require('discord.js');
const { createMusicManager } = require('@kyometori/djsmusic');
const client = new Client({ intents: ['GUILDS', 'GUILD_VOICE_STATES'] });

client.once('ready', () => {
  console.log('Everything is ready!');

client.on('interactionCreate', interaction => {
  if (!interaction.isCommand()) return;

  if (interaction.commandName === 'join') {
      channel: interaction.member.voice.channel

  if (interaction.commandName === 'play') {
    const url = interaction.options.getString('url');
    interaction.client.music.get(interaction.guild.id).play(url, {
      player: interaction.member


Table of contents


To use this package, you must meet these requirements:

  • discord.js version > 13
  • FFmpeg Dependency. Can be one of those below:
    • FFmpeg (installed and added to environment)
    • ffmpeg-static (npm install)



createMusicManager (Client client, Object options, String property)

Build a music manager on client[property]. If no property supply, it'll automatically use music. The options will be automatically applied to the Manager options.

This is the most important object in this package. For most usage you only need to import this (and some utils below) for your bot.



new ClientMusicManager (Client client, {
    Number defaultMaxQueueSize, // the default maximum size of queue, will be automatically applied to all its `GuildMusicManager`
    Boolean enableQueue,         // whether we should enable the default queue system
    Boolean enableAutoplay,      // if set to `false`, it won't automatically play the next song of the queue
    Boolean enableInlineVolume,  // whether should inline volume be enable
    Boolean disableWarning,      // whether we should show warnings
    Object enableService : {     // determine which service should be enable
      Boolean rawFile,           // ability to play raw file
      Boolean youtube            // ability to play youtube link directly

Every boolean property is set to true except enableInlineVolume due to better performance. If you want to have the feature of 'adjust volumen during playing' you have to set this to true.
In default defaultMaxQueueSize is 99. Can set to Infinity if you don't want a limit.
The enableService is for you to enable or disable some service if you don't want your bot to play that.


  • client : the client that instantiated this
  • connections : (readonly) A Map contains all this manager's GuildMusicManager, mapped by their id.


  • has(Snowflake id) : if we have connection of the guild of given id in our data
  • get(Snowflake id) : get the GuildMusicManager object that handle the guild of given id
  • join({ VoiceChannel channel, Boolean setMute, Boolean setDeaf, Number maxQueueSize }) : join the given voice channel and self mute or deaf if given. Returns a Promise<GuildMusicManager> which is the manager of joined guild.
  • leave(Snowflake id) : leave the guild of given id.


  • join : Emit after your client joined a channel.
    • Params: Guild guild the guild of joined channel.
  • leave : Emit after your client left a channel.
    • Params: Guild guild the guild of left channel.



new GuildMusicManager ({
    Client client,               // client of your bot
    ClientMusicManager manager,  // music manager of your client
    VoiceChannel channel,        // the voice channel joined
    Number maxQueueSize          // the max size of this manager's queue


  • client : the Client that instantiated this
  • guild : the guild of this manager
  • channel : the VoiceChannel that instantiated this
  • manager : the ClientMusicManager that instantiated this
  • voiceState : the voiceState of Client
  • player : the player of this manager
  • queue : the queue of this manager
  • MAX_QUEUE_SIZE : the max size of this manager's queue
  • isPlaying : is this manager's player playing
  • nowPlaying : empty object if nothing is playing, or a Track object when there's something


  • play(String url, Object customMetadata, Boolean force) : The url of music you want to play. If the url is unsupported, it'll throw a UNSUPPORTED_URL_TYPE Error. customMetadata can be access through Track and Track#details. Force is to determine to skip what's playing now or queue this song if there are already something playing. Returns a Promise<[Track, Boolean]>. The Track object is the song you just queue or play, and the Boolean is this song is queued or not (playing directly).
  • next() : Get and remove the first song of the queue. If it's looping, it'll return what's playing now.
  • hasNext() : Does this manager has next song. If current track is looping it always returns true.
  • seek(Number time) : Seek a specific time of current song. Time is in milliseconds. If the number is larger than the total time it'll throw a INVALID_SEEK_TIME Error.
  • getVolume() : get current volume. If it's 2 means the volume is 2x louder than default.
  • setVolume(Number number) : set the volume of current track. You have to enable inline volume in the ClientMusicManager to use this function.
  • setOnStage(Boolean yes) : let the bot be on the stage if set to true, or not if set to false
  • setLoop(Boolean loop) : loop the current track or not, set to true to loop
  • pause() : pause what's playing
  • resume() : unpause what's playing
  • skip() : skip what's playing
  • leave() : leave the voice channel and kill this manager


  • play : emit after a track started playing
    • Params: Track track the track is played
  • leave : emit after client left this guild
    • Params: Guild guild the guild of this manager
  • end : emit when a song is finished playing (same as Track#end)
    • Params: Track next the track that's gonna play after this track. If no then it will be undefined.
  • finish : emit after every song in queue finished playing



new Track({
    audioUrl, // the audio resource url of this track
    manager,  // the GuildMusicManager playing this track
    metadata: {
        title         // title of this track, default unknown
        lengthSeconds // length of this track, default Infinity
        player        // the one choose play this song, required
        details       // Other metadata of this track, default empty object

When track is construct automatically by given Youtube URL in GuildMusicManager, its details property will includes:

  • from : Always 'Youtube'. You can use this to determine where this track is.
  • data : A YoutubeVideoData object. You can find its properties below.


  • manager : the manager that instantiated this.
  • title : the title of this track
  • lengthSeconds : the length of this song, in seconds.
  • player : who pick this song. this is required but can be anything such as 'unknown', a GuildMember Object etc.
  • details : the detail metadata of this track
  • isLooping : whether this track looping or not
  • playedMs : (readonly) how many milliseconds the track played


  • end : emits after this track finish playing



  • isYoutubeLink(String link) : (static) check if the link is a Youtube link.
  • isPlaylistLink(String link) : (static) check if the link is a Youtube playlist link.
  • getVideoData(String link) : (static) get the data of the video. Returns a YoutubeVideoData object if find it, or throw an Error when no data have been found.
  • getPlaylistData(String link, Number page) : (static) get the data of the playlist. page determine how many pages of this playlist should be fetched. Default Infinity. Returns a YoutubePlaylistData object if find it, or throw an Error when no data have been found.
  • searchFirstVideo(String keywords) : (static) Use the keywords to search, and return the first (most related) video. Returns a YoutubeVideoData Object.
  • search(String keywords, Number max, { Boolean disableChannel, Boolean disablePlaylist, Boolean disableVideo }) : (static) Use the keywords to search, and return at most max results. You can use disableSomething to pull the type you don't want from results. In default only video is enable. Returns an Array of YoutubeObjectData, which is one of YoutubeVideoData, YoutubeChannelData, YoutubePlaylistData.



new YoutubeVideoData(rawData) // raw data from ytsr
// you can construct this by passing your own data, but you need `type: 'video'` guard in the data or will cause an Error.


  • type : always 'video'
  • title : title of this video
  • url : youtube url of this video
  • isCrawlable : can this video be crawl.
  • thumbnailUrl : url of this video's thumbnail
  • uploadDate : the date this video uploaded, formatted in yyyy-mm-dd.
  • viewCount : the viewCount of this video.
  • audioUrl : the original audio file url of this video.
  • channel : channel uploaded this video. This is a YoutubeChannelData Object.


  • play(GuildMusicManager manager, Object customMetadata, Boolean force) : Play this video. This behave same as GuildMusicManager#play. Returns same thing with GuildMusicManager#play.
  • fetch() : Fetch this video and fullfill those undefined properties.



new YoutubeChannelData(rawData) // raw data from ytsr
// you can construct this by passing your own data, but you need `type: 'channel'` guard in the data or will cause an Error.


  • type : always 'channel'
  • name : name of this channel
  • channelId : id of this channel
  • url : url to this channel
  • descriptionShort : short description of this channel, if any. Notice that if this is from YoutubeVideoData#channel or YoutubePlaylistData#channel, you have to fetch to get this.
  • avatarUrl : url to avatar of this channel. Notice that if this is from YoutubePlaylistData#channel, you have to fetch to get this.
  • verified : whether this channel is verified or not


  • fetch() : Fetch this channel to get missing properties. Return Promise<YoutubeChannelData>. Notice this use name and channelId to get data. An error will occurred when one missing. Also it will refresh all data of this object if the fetched data is different from your original data (most happened in construct this object manually).



new YoutubePlaylistData(rawData) // raw data from ytsr
// you can construct this by passing your own data, but you need `type: 'playlist'` guard in the data or will cause an Error.


  • type : always playlist.
  • title : the title of this playlist.
  • data : a Array<YoutubeVideoData>, contains all crawlable video inside.
  • url : url of this playlist.
  • firstVideoThumbnailUrl : thumbnail of this playlist's first video
  • channel : channel created this playlist. This is a YoutubeChannelData Object.


  • fetch(Number page) : fetch this playlist and fullfill the properties with its url. The page determine how many pages of the playlist should be fetched. Default Infinity.



  • isSoundCloudLink(String link) : (static) check if the link is a kind of SoundCloud link;
  • getTrackData(String link) : (static) get a track's data by its link. Returns a Promise<SoundCloudTrackData>



new SoundCloudTrackData(rawData) // raw data from soundcloud-scraper
// you can construct this data manually and fetch it to get more informations


  • type : always 'track'
  • id : the id of this track
  • title : the title of this track
  • description : the description of this track
  • lengthSeconds : how long is this track, in seconds
  • thumbnail : thumbnail of this track
  • url : url of this track
  • playCount : the play count of this track
  • genre: the genre of this track


Examples can be found here.

Example usages

These examples assume:

  • <Client> : Your bot's client
  • <Channel> : the target channel
  • <Id> : the target guild id
  • <Url> : the links
  • <User> : the one pick this song
  • <Time> : a time in unit milliseconds
  • <Keywords> : Search keywords

Also we assume your ClientMusicManager is on <Client>.music.

Join and Leave

// join
<Client>.music.join({ channel: <Channel> });

// leave #1

// leave #2


// Normal playing
<Client>.music.get(<Id>).play(<Url>, { player: <User> });

// With promise
    .play(<Url>, { player: <User> })
    .then(([track, queued]) => {
        if (queued) console.log(`${track.title} is queued!`);
        else console.log(`${track.title} is playing!`);

The url parameter of the play method accept following urls:

  • Raw mp3, mp4, wav, ogg, aac, flac files. The url must ended with .(file extension)
  • A Youtube link.

Pause and Resume


Toggle Looping

const manager = <Client>.music.get(<id>);

Seek a time


Get NowPlaying Data

// If anything is playing, this will be a Track object
// Otherwise it's an empty Object

Volume Increase

const manager = <Client>.music.get(<id>);
manager.setVolume(manager.getVolume() + 0.1);

Notice you have to enable inline volume when create your ClientMusicManager to use this feature.

Logging when song is finished

const manager = <Client>.music.get(<Id>);
manager.on('end', next => {
   if (!next) console.log('Finish all queued songs!');
   else console.log('Start playing next song...');

Leave when queue is finished

  .join({ channel: <Channel> })
  .then(manager => {
    manager.once('finish', () => {

This code implements both join and set up leave-when-finished.

Search and play the most related song by keywords

  .then(data => {
    data.play(<Client>.music.get(<Id>), { player: <User> });
  .catch(err => {

For more examples you can look at our examples or look up our Documentation and create features yourself!


Junior HiZollo : My another project which is a Discord bot with music feature. This library is basically rewriting its music (which was also written by me) and make it generic.

Package Sidebar


npm i @kyometori/djsmusic

Weekly Downloads






Unpacked Size

44.8 kB

Total Files


Last publish


  • kyometori