Voice Overview
Discord allows you to connect to voice channels and stream audio in real-time. With NetCord, you can create powerful voice bots that can play music, record conversations, and process voice data. This guide covers the essentials of working with Discord voice channels, including connecting, streaming audio and recording.
Required Dependencies
Before you get started, ensure that you've installed the necessary native dependencies. Follow the installation guide to set them up.
Resulting Project
By the end of the voice section, you will have a fully functional music bot that can join voice channels, play audio, and record voice of connected users. Of course you don't need to follow it exactly, for example if you skip Receiving Voice, then your bot won't be able to record. Same for Sending Voice. You likely don't want to skip Voice Connection, as without it your bot won't be able to connect to voice channels, even if you implement the playback and recording.
Below you can see the setup of the project. It will be needed in the following guides of this section. Note that the project is just a demonstration of how to use the library, you can implement the features in your own way. The important part is that you understand the concepts and how to use the library to achieve your goals.
Program.cs
using System.Collections.Concurrent;
using System.Diagnostics;
using Microsoft.Extensions.Hosting;
using NetCord;
using NetCord.Gateway;
using NetCord.Gateway.Voice;
using NetCord.Hosting.Gateway;
using NetCord.Hosting.Services.ApplicationCommands;
using NetCord.Logging;
using NetCord.Rest;
using NetCord.Services.ApplicationCommands;
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddApplicationCommands(o =>
{
o.ResultHandler = ApplicationCommandResultHandler<ApplicationCommandContext>.Ephemeral;
})
.AddDiscordGateway(o => o.Intents = GatewayIntents.Guilds | GatewayIntents.GuildVoiceStates);
var host = builder.Build();
ConcurrentDictionary<ulong, VoiceInstance?> voiceInstances = [];
await host.RunAsync();
VoiceInstance.cs
using NetCord.Gateway.Voice;
internal sealed class VoiceInstance(VoiceClient client) : IDisposable
{
private static readonly int JobTypeCount = Enum.GetValues<VoiceJobType>().Length;
public VoiceClient Client => client;
private readonly CancellationTokenSource _cancellationTokenSource = new();
private readonly byte[] _jobStatuses = new byte[JobTypeCount];
public Job? TryEnterJob(VoiceJobType type)
{
return Interlocked.CompareExchange(ref _jobStatuses[(int)type], 1, 0) is 0
? new(this, type, _cancellationTokenSource.Token)
: null;
}
public void Dispose()
{
var tokenSource = _cancellationTokenSource;
tokenSource.Cancel();
tokenSource.Dispose();
client.Dispose();
}
public readonly record struct Job(VoiceInstance Instance,
VoiceJobType JobType,
CancellationToken CancellationToken) : IDisposable
{
public void Dispose()
{
Interlocked.Exchange(ref Instance._jobStatuses[(int)JobType], 0);
}
}
}
internal enum VoiceJobType
{
Playing = 0,
Recording = 1,
}
Glossary
- PCM: Pulse-code modulation, a raw audio format.
- Opus: An audio codec used by Discord for voice communication. It provides high-quality audio at low bitrates allowing for efficient streaming.
- Bitrate: The amount of data transmitted per second in an audio stream. Note that bitrate is not the same as audio quality, as it also depends on the codec and other factors. For example, lossless codecs preserve the original audio at a bitrate that is lower than the bitrate of PCM.
Terms of Service Compliance
When working with Discord voice, ensure your bot complies with Discord's Terms of Service. It is quite easy to violate the terms when working with voice, so be sure to review the guidelines and best practices for voice bots.
See Also
- Connecting to Voice - Voice connection lifecycle and management
- Sending Voice - Stream audio to voice channels
- Receiving Voice - Receive voice from users
- Gateway Intents - Configure required intents
- Discord Documentation: Voice
- Microsoft Learn: Overview of synchronization primitives