Skip to content
MrCakeSlayer edited this page Sep 24, 2022 · 1 revision

Before you can play anything using your discord bot, you need to retrieve a track.

Lavalink (more specific: lavaplayer) supports a lot of providers, here is a list of them:

  • YouTube
  • SoundCloud
  • Bandcamp
  • Vimeo
  • Twitch streams
  • Local files
  • HTTP URLs

[Source: lavaplayer#README.md]

Track information

Printing out track information

// get YouTube track by video id
var track = await audioService.GetTrackAsync("dQw4w9WgXcQ");

// RickAstleyVEVO
Console.WriteLine(track.Author);

// Rick Astley - Never Gonna Give You Up
Console.WriteLine(track.Title);

// https://www.youtube.com/watch?v=dQw4w9WgXcQ
Console.WriteLine(track.Source);

// 3:53:33
Console.WriteLine(track.Duration);

// false
Console.WriteLine(track.IsLiveStream);

// true
Console.WriteLine(track.IsSeekable);

// dQw4w9WgXcQ
Console.WriteLine(track.TrackIdentifier);

// YouTube
Console.WriteLine(track.Provider);

// QAAAjQIAJVJpY2sgQXN0bGV5IC0gTmV2ZXIgR29ubmEgR2l2ZSBZb3UgVXAADlJpY2tBc3RsZXlWRVZPAAAAAAADPCAAC2RRdzR3OVdnWGNRAAEAK2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9ZFF3NHc5V2dYY1EAB3lvdXR1YmUAAAAAAAAAAA
Console.WriteLine(track.Identifier);

See: LavalinkTrack.cs for source.

Lavalink provides information about the track:

Name Description
Author The name of the author that created the media.
Title The title of the media (/ YouTube Video).
Source The source URI the track is from.
Duration The duration/length of the track.
IsLiveStream A value indicating whether the track is a live stream. (for example a live YouTube-Video).
IsSeekable A value indicating whether the player seek functions can be used on the track.
TrackIdentifier A unique track identifier (for example the Video ID of YouTube videos)
Provider The audio provider source (e.g. YouTube / SoundCloud)
Identifier The base64-encoded track identifier / serialized version of the track.

Getting tracks

Example usage of GetTrackAsync

// the following searches for "Coldplay - Adventure of a Lifetime" on YouTube
await audioService.GetTrackAsync("Coldplay - Adventure of a Lifetime", SearchMode.YouTube);

// the following searches for "Coldplay - Adventure of a Lifetime" on SoundCloud
await audioService.GetTrackAsync("Coldplay - Adventure of a Lifetime", SearchMode.SoundCloud);

// gets a track for "http://thisisnotarealldymp3stream.com/track.mp3"
await audioService.GetTrackAsync("http://thisisnotarealldymp3stream.com/track.mp3");

If you want to retrieve a track from an HTTP stream, for example, you can do that using ILavalinkRestClient (or any implementations, for example, LavalinkNode, LavalinkCluster).

Task<LavalinkTrack> GetTrackAsync(string query, SearchMode mode = SearchMode.None, bool noCache = false, CancellationToken cancellationToken = default);

Parameters

Name Description
query The lavaplayer track query (also supports searching)
mode The search mode; prefixes the query with the corresponding search prefix.
noCache If enabled force downloads the track even if it is in the cache.
cancellationToken A cancellation token used to propagate notification that the asynchronous operation should be canceled.

Returns

The result of the function is a task that represents the asynchronous operation. The task result is the loaded track; or null if an error occurred while loading the track (see logging) or if no tracks were found by the specified query.

What's behind SearchMode

Search modes

public enum SearchMode
{
    None,
    YouTube,
    SoundCloud
}

// See: https://github.com/angelobreuer/Lavalink4NET/blob/master/src/Lavalink4NET/Rest/SearchMode.cs

Search mode simply prefixes the query with 'ytsearch:' (Search on YouTube) or 'scsearch:' (Search on SoundCloud). This will make lavaplayer search for tracks.

Decoding tracks

Decoding a track

using Lavalink4NET.Decoding;

// From Track Identifier to Track

// decode track
var track = TrackDecoder.DecodeTrack("QAAAjQIAJVJpY2sgQXN0bGV5IC0gTmV2ZXIgR29ubmEgR2l2ZSBZb3UgVXAADlJpY2tBc3RsZXlWRVZPAAAAAAADPCAAC2RRdzR3OVdnWGNRAAEAK2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9ZFF3NHc5V2dYY1EAB3lvdXR1YmUAAAAAAAAAAA");

// RickAstleyVEVO
Console.WriteLine(track.Author);

// [...]

// From Track to Track Identifier

var trackIdentifier = track.Author;

Lavalink4NET supports lavaplayer track decoding. This is useful for example when having to store the tracks in a database for example. If it is hard to save the whole track information including title, author, and so on... So it is easier to just store the base64 track identifier returned by lavalink.

Attaching data to tracks

Lavalink4NET (2.1.0) supports attaching additional data to tracks using the context property on the track object.

Assigning data to the track

public sealed class TrackContext
{
    public ulong RequesterId { get; set; }

    public string OriginalQuery { get; set; }
}

var query = "Coldplay - Adventure of a Lifetime";
var track = await client.GetTrackAsync(query, SearchMode.YouTube);

track.Context = new TrackContext
{
    OriginalQuery = query,
    RequesterId = user.Id,
};

Accessing data of the track

var context = (TrackContext)player.CurrentTrack.Context!;
var requester = await client.GetUserAsync(context.RequesterId);
await user.SendMessageAsync($"The track was added by {requester}.");

NOTE When a lavalink player is moved to another lavalink node, the track context is discarded!

Getting playlists

Lavalink4NET supports fetching playlists from URIs, like for example YouTube playlists.

var response = await client.LoadTracksAsync("playlist..");

if (response.PlaylistInfo is null)
{
    // Link is not a playlist
    // ...
}
else
{
    var playlistName = response.PlaylistInfo.Name;

    // Link is a playlist
}

Retrieving artwork for a track

Lavalink4NET supports retrieving artwork for a track. At the moment, only YouTube, Vimeo, and SoundCloud are supported. Resolution for custom track providers can be implemented when overriding the corresponding methods of the ArtworkService class.

The following code snippet shows how to resolve the artwork for a YouTube track.

// This service should be distributed using DI, or at least made a singleton
using var artworkService = new ArtworkService();

var track = await audioService.GetTrackAsync("Coldplay - Adventure of a Lifetime", SearchMode.YouTube);
var artworkUri = await artworkService.ResolveAsync(track);