View Source Voice Usage
This cheat sheet covers basic use of the Discord Voice API through the Nostrum.Voice
module.
Playing Audio
Playing immediately with a try_play
function
def try_play(guild_id, url, type, opts \\ []) do
case Voice.play(guild_id, url, type, opts) do
{:error, _msg} ->
# Wait for handshaking to complete
Process.sleep(100)
try_play(guild_id, url, type, opts)
_ ->
:ok
end
end
iex> Voice.join_channel(guild_id, channel_id)
iex> try_play(guild_id, "./song.mp3", :url)
Playing immediately using Nostrum.Voice.ready?/1
def play_when_ready(guild_id, url, type, opts \\ []) do
if Voice.ready?(guild_id) do
Voice.play(guild_id, url, type, opts)
else
# Wait for handshaking to complete
Process.sleep(25)
play_when_ready(guild_id, url, type, opts)
end
end
iex> Voice.join_channel(guild_id, channel_id)
iex> play_when_ready(guild_id, "https://youtu.be/b4RJ-QGOtw4", :ytdl)
Playing immediately by using events
alias Nostrum.Struct.Event.VoiceReady
alias Nostrum.Voice
def handle_event({:VOICE_READY, %VoiceReady{guild_id: guild_id} = _event, _v_ws_state}) do
Voice.play(guild_id, "~/loud_noise.mp3", :url, volume: 10)
end
Once the voice handshake has completed, audio will begin playing
without the need for polling functions like try_play/4
or play_when_ready/4
as shown in the other examples
iex> Voice.join_channel(guild_id, channel_id)
# Playback will start automatically when ready
Audio FFmpeg options
Volume
Half volume
Voice.play(guild_id, "~/final_mix.wav", :url,
volume: 0.5
)
Extreme clipping
Voice.play(guild_id, "~/boost_this.m4a", :url,
volume: 100
)
Normal volume with inverted phase
Voice.play(guild_id, "~/music.mp3", :url,
volume: -1.0
)
Start position and duration
Start at 37.8 seconds
Voice.play(guild_id, "https://youtu.be/b4RJ-QGOtw4", :ytdl,
start_pos: "0:37.8"
)
Play the first at 15.3 seconds from the beginning
Voice.play(guild_id, "https://youtu.be/b4RJ-QGOtw4", :ytdl,
duration: "15.3"
)
Play for 80 seconds (equivalently 1:20) starting from 90 seconds (equivalently 1:30) in
Voice.play(guild_id, "~/music.mp3", :url,
start_pos: "90",
duration: "80"
)
Advanced audio filtering
Cutoff filters
Low-pass filter at 1200 Hz, high-pass filter at 300 Hz
Voice.play(guild_id, "https://youtu.be/0ngcL_5ekXo", :ytdl,
filter: "lowpass=f=1200",
filter: "highpass=f=300"
)
Sample rate
Play at half tempo and pitch (assumes a 48kHz sample rate)
Voice.play(guild_id, "https://youtu.be/0ngcL_5ekXo", :ytdl,
filter: "asetrate=48000*0.5"
)
Play at 30% higher tempo and pitch. Realtime must be set to false
for ffmpeg to keep up with faster-than-normal playback.
Voice.play(guild_id, "https://youtu.be/0ngcL_5ekXo", :ytdl,
realtime: false,
filter: "asetrate=48000*1.3"
)
Heavily distorted and effected lo-fi FX chain
Voice.play(guild_id, "https://youtu.be/Hd_giv-wcJU", :ytdl,
volume: 3,
start_pos: "0:55",
filter: "asetrate=48000*0.73",
filter: "vibrato=d=0.05:f=698.46",
filter: "vibrato=f=1:d=0.8",
filter: "lowpass=f=1200",
filter: "aphaser=in_gain=0.4:out_gain=0.5:delay=3.0:decay=0.3:speed=0.3:type=t"
)