Rishav
Rishav

Reputation: 4078

How to play music from a local file

After a long run and trial I managed to connect my bot to a voice channel and disconnect from one as well. However I couldn't find a proper way to play music. I researched and tried to read and came across many different options like ffmpeg, sharplink and lavalink but I don't know how to use them.

There is an exact question on SO How to Play Audio File Into Channel? but it talks in reference with JavaScript and not .NET so I am nowhere.

So, how to play audio (local file) from my bot in a voice channel after having it successfully connected. Version : Discord.Net 2.x nightly

Upvotes: 0

Views: 2607

Answers (1)

Cristian Moraru
Cristian Moraru

Reputation: 375

What you're missing is the audio stream itself, I'll give you an example using ffmpeg because that's what I used and it works.

Full disclosure, the project I'm about to give samples of is my own.

Right, so you already have the voice channel connect/disconnect stuff done, nice work! Now all you're missing is streaming some audio (from a local file as your question indicates).

What you need to do is start a separate process for ffmpeg, using something like this:

private Process CreateStream(string filePath)
{
    return Process.Start(new ProcessStartInfo
    {
        FileName = "ffmpeg.exe",
        Arguments = $"-hide_banner -loglevel panic -i \"{filePath}\" -ac 2 -f s16le -ar 48000 pipe:1",
        UseShellExecute = false,
        RedirectStandardOutput = true
    });
}

Note: ffmpeg.exe should be located in your project's root directory, otherwise just specify a different route in the FileName = "" param.

Edit: You also need to specify it to be copied to your output folder once the project is built. Adding these lines into your .csproj file should do the trick:

<ItemGroup>
    <None Update="ffmpeg.exe">
        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
</ItemGroup>

To send the audio to the voice channel you're connected to, use something like this:

using (Stream output = CreateStream(filePath).StandardOutput.BaseStream)
using (AudioOutStream stream = client.CreatePCMStream(AudioApplication.Music))
{
    try
    {
        await output.CopyToAsync(stream);
    }
    catch (Exception e)
    {
         _logger.LogError(e, "Stopped audio stream");
    }
}

Where client.CreatePCMStream(AudioApplication.Music) is the IAudioClient your bot is connected to.

Ideally you would have some type of AudioService class to do all of this instead of the module responsible to executing the commands.

Here's an example of a module with a dedicated service, from where the code above was copied:

Module & Service

Hope this helps you.

Upvotes: 1

Related Questions