Skip to content

Voice sending

Matthew Carey edited this page Nov 15, 2020 · 1 revision

Starting from version 1.5.0, discordrb supports sending audio data into a voice channel, which can for example be used to make music playing bots.

Connection

First of all, you need to connect to a voice channel. This is done using bot.voice_connect(channel), where channel is a Channel object. (It will fail if the channel is not a voice channel.) The call returns a VoiceBot object which is used to do the actual sending; after connecting, the VoiceBot for the particular server can also be accessed using bot.voice(server).

You can connect to multiple voice channels by calling voice_connect multiple times, but note that you can't connect to two voice channels on the same server at once. For convenience, there's a MessageEvent#voice method which means that in message events and commands you can do event.voice to get the voice bot for the current server. This is the notation I'll be using in this tutorial, though remember that you can use bot.voice(server) with any server to get the same results on that server.

Playing

You can play a file using event.voice.play_file:

event.voice.play_file('/home/user/Music/file.mp3')

This call will block until the playback has finished, either by simply reaching the end of the file or by being prematurely interrupted due to something else being played. play_file will also allow URLs to be played (note that it will attempt to read the entire URL/file before starting playback, which may cause overhead for large files).

Another possibility is play_io, which plays from an arbitrary IO object:

event.voice.play_io(open('http://example.com/file.mp3'))

Like play_file it will block until the playback has finished, either by failing to read any more data or by an EOF in the stream.

Playback control

event.voice.pause and event.voice.continue will pause and continue the playback, respectively. Note that these calls are not instant, but may have a delay of up to 0.1 seconds depending on timing. event.voice.stop_playing will stop the playback completely with a possible delay of 0.02 seconds.

Volume

event.voice.volume can be set (only set) to an arbitrary float. The default is 1; 0 is completely silent, 2 is twice the volume as 1 and 0.5 is half the volume as 1. This applies to both future playbacks, as well as the current stream.

Play time

The event.voice.stream_time property returns the approximate current time (in seconds) for which the playback has been running. Due to the network latency adjustments, this isn't guaranteed to be continuous either - if you do two calls in rapid succession and there's a particularly bad network delay, the second call might return a value less than the first.

Troubleshooting

Here's a number of things to check if you can successfully connect to a voice channel, but no audio plays:

  • Does the file/URL you're trying to play actually exist? Try play_io instead with an open call to test whether that might be the problem.
  • Old version of ffmpeg: for an unknown reason, old versions of ffmpeg (happened with 0.8.10, possibly later ones) cause playback to exit immediately. Updating it should fix it.
  • 64-bit Ruby on Windows: the precompiled version of libopus is for 32 bit only, so unless you manually compile the source for 64-bit, you need to use 32-bit Ruby.
  • If you're running your bot on c9.io, there may be some issues with the ports, causing voice not to work at all. Nobody has found a solution yet; if you have, please report it here.