Handling Audio

This library uses Node Streams to handle playing and recieving audio. It's simple.

Warning: Encoder

You need ffmpeg or avconv in order to do any audio encoding. Make sure it's installed and added to your system's PATH. This does not apply to just joining the voice channel and capturing speaking events (on Node or the Browser).

  1. Join a Voice Channel with joinVoiceChannel()
  2. Get the context for that Voice Channel with getAudioContext()
  3. pipe() / write() data to, or pipe() / read() data from, the stream argument.

Let's assume

//Node's internal fs module
var fs = require('fs');

var voiceChannelID = "66192955798458368";
var izy = "66186356581208064";

Playing audio

The simplest way to get started is:

//Let's join the voice channel, the ID is whatever your voice channel's ID is.
client.joinVoiceChannel(voiceChannelID, function(error, events) {
  //Check to see if any errors happen while joining.
  if (error) return console.error(error);

  //Then get the audio context
  client.getAudioContext(voiceChannelID, function(error, stream) {
    //Once again, check to see if any errors exist
    if (error) return console.error(error);

    //Create a stream to your file and pipe it to the stream
    //Without {end: false}, it would close up the stream, so make sure to include that.
    fs.createReadStream('myFile.mp3').pipe(stream, {end: false});

    //The stream fires `done` when it's got nothing else to send to Discord.
    stream.on('done', function() {
       //Handle
    });
  });
});

While that should be enough for anyone to just play an audio file, some users may have more advanced needs like receiving audio, or capturing speaking packets. The lib can handle both of those easily.

Capturing speaking events

client.joinVoiceChannel(voiceChannelID, function(error, events) {
  if (error) return console.error(error);

  //This can be done on both Node and the Browser using the same code
  events.on('speaking', function(userID, SSRC, speakingBool) {
    //This will log either "[userID] is speaking" or "[userID] is done speaking"
    console.log("%s is %s", userID, (speakingBool ? "speaking" : "done speaking") );
  });
});

Receiving audio

Audio received back to you is decoded from Opus to S16LE PCM (in the back-end). Unless getAudioContext() is called with a certain option, there is no decoding or storing done (for performance reasons), so you have to specify.

In order to activate receiving, we have to turn the first argument into an Object then include the maxStreamSize key. The value for this key will be how many kilobytes of audio data that you want the library to keep before pushing the earliest data out. FIFO (First In First Out).

client.joinVoiceChannel(voiceChannelID, function(error, events) {
  if (error) return console.error(error);

  //Let's use a maxStreamSize of 50MiB
  client.getAudioContext({channelID: voiceChannelID, maxStreamSize: 50 * 1024}, function(error, stream) {
    //You can access a Member's stream
    //Members are Readable Streams
    if (stream.members[izy]) {
      //Will give you all of the PCM data saved for this user.
      stream.members[izy].read();
    }

    //The stream variable is also a Stream, a Duplex.
    //You can use Stream methods on it. It contains
    //the last 50MiB (maxStreamSize) of mixed audio
    //data (from everyone speaking).
    stream.pipe(fs.createWriteStream('./everyone.wav'));

    //Any time any new audio is recieved
    //'incoming' will be emitted with the
    //decoded audio buffer, if you'd rather
    //use this method
    stream.on('incoming', function(SSRC, buffer) {});
  });
});

getAudioContext

getAudioContext() is a method that gets a stateful audio instance of a voice session in the back-end. You can call it as many times as you want, the stream variable will be equivalent to accessing client._vChannels[voiceChannelID].audio, if it exists. This means if you intend to receive audio, but have already instanced an audio context without maxStreamSize, you have to leave the audio channel and re-join, then use getAudioConext() with maxStreamSize.

results matching ""

    No results matching ""