Audio player library for Discord.Net using FFmpeg and Youtube-dl
This project is still in development and not production ready
This is a basic example on how to use AudioPlayer
.
// Initialize AudioPlayer
AudioPlayer audioPlayer = new AudioPlayer();
// Set player's audio client
// This is required for AudioPlayer to create an audio stream to Discord
SocketVoiceChannel voiceChannel = (Context.User as SocketGuildUser)?.VoiceChannel;
var audioClient = await voiceChannel.ConnectAsync();
audioPlayer.SetAudioClient(audioClient);
To play an audio, we need to load an AudioTrack instance. To do this, we can use TrackLoader
class:
string query = "Tuturu Ringtone";
bool wellFormedUri = Uri.IsWellFormedUriString(query, UriKind.Absolute);
List<AudioTrack> tracks = await TrackLoader.LoadAudioTrack(query, fromUrl: wellFormedUri);
// Pick the first entry and use AudioPlayer.StartTrack to play it on Thread Pool
AudioTrack firstTrack = tracks.ElementAt(0);
// Fire & forget
player.StartTrackAsync(firstTrack, interrupt: true).ConfigureAwait(false);
// OR
// await track to finish playing
await player.StartTrackAsync(firstTrack, interrupt: true);
AudioPlayer implements IAudioEvent and currently there are 3 audio events that can be subscribed:
- OnTrackStartAsync
- OnTrackEndAsync
- OnTrackErrorAsync
For example, a track scheduler:
public class TrackScheduler
{
public Queue<AudioTrack> SongQueue { get; set; }
private AudioPlayer player;
public TrackScheduler(AudioPlayer player)
{
SongQueue = new Queue<AudioTrack>();
this.player = player;
this.player.OnTrackStartAsync += OnTrackStartAsync;
this.player.OnTrackEndAsync += OnTrackEndAsync;
}
public Task Enqueue(AudioTrack track)
{
if (player.PlayingTrack != null)
{
SongQueue.Enqueue(track);
}
else
{
// fire and forget
player.StartTrackAsync(track).ConfigureAwait(false);
}
return Task.CompletedTask;
}
public async Task NextTrack()
{
AudioTrack nextTrack;
if (SongQueue.TryDequeue(out nextTrack))
await player.StartTrackAsync(nextTrack);
else
player.Stop();
}
private Task OnTrackStartAsync(IAudioClient audioClient, IAudioSource track)
{
Console.WriteLine("Track start! " + track.Info.Title);
return Task.CompletedTask;
}
private async Task OnTrackEndAsync(IAudioClient audioClient, IAudioSource track)
{
Console.WriteLine("Track end! " + track.Info.Title);
await NextTrack();
}
}
Note:
- AudioTrack is PCM AudioSource
- Opus AudioSource is not yet supported
Contributions are very very welcome :]
- Demo for music state management / queue system, at ExampleMusicBot or at Demo
Looking for a constructive feedback, feedback about best practices would really help me out. If you find a flaw in my logic, please open an issue or a PR and we'll sort things out.