-
-
Save Joe4evr/773d3ce6cc10dbea6924d59bbfa3c62a to your computer and use it in GitHub Desktop.
using System.Threading.Tasks; | |
using Discord.Commands; | |
public class AudioModule : ModuleBase<ICommandContext> | |
{ | |
// Scroll down further for the AudioService. | |
// Like, way down | |
private readonly AudioService _service; | |
// Remember to add an instance of the AudioService | |
// to your IServiceCollection when you initialize your bot | |
public AudioModule(AudioService service) | |
{ | |
_service = service; | |
} | |
// You *MUST* mark these commands with 'RunMode.Async' | |
// otherwise the bot will not respond until the Task times out. | |
[Command("join", RunMode = RunMode.Async)] | |
public async Task JoinCmd() | |
{ | |
await _service.JoinAudio(Context.Guild, (Context.User as IVoiceState).VoiceChannel); | |
} | |
// Remember to add preconditions to your commands, | |
// this is merely the minimal amount necessary. | |
// Adding more commands of your own is also encouraged. | |
[Command("leave", RunMode = RunMode.Async)] | |
public async Task LeaveCmd() | |
{ | |
await _service.LeaveAudio(Context.Guild); | |
} | |
[Command("play", RunMode = RunMode.Async)] | |
public async Task PlayCmd([Remainder] string song) | |
{ | |
await _service.SendAudioAsync(Context.Guild, Context.Channel, song); | |
} | |
} |
using System.Collections.Concurrent; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Threading.Tasks; | |
using Discord; | |
using Discord.Audio; | |
public class AudioService | |
{ | |
private readonly ConcurrentDictionary<ulong, IAudioClient> ConnectedChannels = new ConcurrentDictionary<ulong, IAudioClient>(); | |
public async Task JoinAudio(IGuild guild, IVoiceChannel target) | |
{ | |
IAudioClient client; | |
if (ConnectedChannels.TryGetValue(guild.Id, out client)) | |
{ | |
return; | |
} | |
if (target.Guild.Id != guild.Id) | |
{ | |
return; | |
} | |
var audioClient = await target.ConnectAsync(); | |
if (ConnectedChannels.TryAdd(guild.Id, audioClient)) | |
{ | |
// If you add a method to log happenings from this service, | |
// you can uncomment these commented lines to make use of that. | |
//await Log(LogSeverity.Info, $"Connected to voice on {guild.Name}."); | |
} | |
} | |
public async Task LeaveAudio(IGuild guild) | |
{ | |
IAudioClient client; | |
if (ConnectedChannels.TryRemove(guild.Id, out client)) | |
{ | |
await client.StopAsync(); | |
//await Log(LogSeverity.Info, $"Disconnected from voice on {guild.Name}."); | |
} | |
} | |
public async Task SendAudioAsync(IGuild guild, IMessageChannel channel, string path) | |
{ | |
// Your task: Get a full path to the file if the value of 'path' is only a filename. | |
if (!File.Exists(path)) | |
{ | |
await channel.SendMessageAsync("File does not exist."); | |
return; | |
} | |
IAudioClient client; | |
if (ConnectedChannels.TryGetValue(guild.Id, out client)) | |
{ | |
//await Log(LogSeverity.Debug, $"Starting playback of {path} in {guild.Name}"); | |
using (var ffmpeg = CreateProcess(path)) | |
using (var stream = client.CreatePCMStream(AudioApplication.Music)) | |
{ | |
try { await ffmpeg.StandardOutput.BaseStream.CopyToAsync(stream); } | |
finally { await stream.FlushAsync(); } | |
} | |
} | |
} | |
private Process CreateProcess(string path) | |
{ | |
return Process.Start(new ProcessStartInfo | |
{ | |
FileName = "ffmpeg.exe", | |
Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1", | |
UseShellExecute = false, | |
RedirectStandardOutput = true | |
}); | |
} | |
} |
@CrAzyScreamx, @STARLITENAMO
How to add AudioService to the service collection:
In your main Program.cs class you should have a private IServiceProvider _services
property, after that in the Main execution you simply add it when creating the Service collection: _services = new ServiceCollection().AddSingleton(new AudioService())
alongside the other services. If you have the Audio Service in a different namespace than the main program make sure to add your using
directives.
Everything is set up as instructed, Audio Service added to my service collection, Audio Module listens for the commands, #bot manages to join my voice channel but leaves almost instantly (Permissions on the server are correctly set up). I'm using Discord.Net version 1.0.2, is this code no longer valid for the 1.0.2 version?
@Flysenberg
I experienced the "bot manages to join my voice channel but leaves almost instantly" yesterday. The problem turned out be it was missing native libraries, opus and sodium (mentioned here https://discord.foxbot.me/docs/guides/voice/sending-voice.html#installing). I noticed this by attaching a debugger and observed a System.DllNotFoundException being thrown.
Binaries for Windows can be found at: https://dsharpplus.emzi0767.com/natives/index.html
@donno
I added "ffmpeg.exe", "libopus.dll" and "libsodium.dll" in bin\Debug and I still get "'System.DllNotFoundException' in mscorlib.dll" in the output and, of course, the bot won't stay in the voice channel.
How can I fix this?
@Flysenberg I am still having trouble with the AudioService. Can you explain more? Maybe with an example. That would help a lot! Thanks.
I get "Failed to create "AudioModule", dependency "AudioService" was not found."
@3NdR1m may be a bit late but you have to rename "libopus.dll" to "opus.dll" in order for the bot to stay in the channel.
I'm getting CreateProcess does not exist exist in current context. (line 56 of AudioService)
Probably meant to be CreateStream
even when i add AudioService to Service Collection i get an error that Audio Service was not found (i'm using discord.net-2.0.0-beta2-00936)
I think I have all this set up, and when the bot joins the voice channel the console says A MessageReceived handler is blocking the gateway task. After about 30 seconds it disconnects and says The operation has timed out. Anyone know why it does this?
@cheessecake I had the same issue and my issue was that I was connecting on the GuildAvailable event, while this is before the Ready event.
Apparently connecting should be done after the ready event so now that I Connect to the voice channel there I'm no longer seeing that problem, though I do have another problem when it's loading the opus DLL but that's something else.
I can get my bot to join the voice channel. However, it does not play any audio when i run the play command. The file is found and there are no exceptions. The execution seems to stop on await ffmpeg.StandardOutput.BaseStream.CopyToAsync(stream);
To fix the "bot manages to join my voice channel but leaves almost instantly problem" I:
Renamed libopus.dll to opus.dll
Renamed libopus.dll.checksums to opus.dll.checksums
Opened the opus.dll.checksums and replaced "libopus.dll" to "opus.dll"
Debug: any CPU to x64
I hope this helps
Hi! I got an error The name "CreateProcess" does not exist in the current context. Do someone know how to solve that?
@Arek123113 if the error in the AudioService, you need to change it to CreateStream
does nothing please help
Thanks for posting this, it's been really helping.
When I play a file shorter than 5 seconds, it causes the next file to mute for the same amount of time as the duration of the first file. My current fix is to make the bot leave and join the channel, but I was wondering if anyone knew a better solution?
Hello, I don't know why this doesn't work for me. I haven't changed anything from the code given. I just created Main https://pastebin.com/L91CfnWE the bot responds to the message command I made but not to audio commands. Can someone help me?
Is there a way to let this play YouTube music?
Hello. in "AudioModule.cs", Line 20("private readonly AudioService _service;"). The "AudioService" is underlined red saying that I am missing a directive or assembly reference. I am using all the directives in this code posted here and yet I'm still getting that error, What namespace is "AudioService" in?
Hello. in "AudioModule.cs", Line 20("private readonly AudioService _service;"). The "AudioService" is underlined red saying that I am missing a directive or assembly reference. I am using all the directives in this code posted here and yet I'm still getting that error, What namespace is "AudioService" in?
I believe it's just using Discord.
Add: using Discord and it should work, I believe.
How to Stream desktop audio??
My bot joins and then instantly disconnects from the voice channel. How do I fix this?
Same. How do I fix this?
I can only get the audio to play once following the SendAudioAsync method. When I call the audio command again the bot lights up green as if it were talking but no audio comes through. In order to play the audio file again the bot has to leave and rejoin. Any ideas?
@arbeers1 discord-net/Discord.Net#1274 (comment)
Can we start making a more updated version of this? I say we, but I don't really know what I'm doing.
I used this tutorial to try and make a music bot, but it didn't work. I'm not sure if that's because the libraries aren't set up right, or because I'm feeding it .mp3 files. But it no workie, and I can't find any other tutorials.
I did what the tutorial said and renamed one of the .dll files, and placed both inside my bin/debug folder (Strange that you don't want to reference it, unless FFmpeg does on its own. I'm not sure), and it didn't do anything. I think I would have felt better if it threw an error so I could know what was wrong with it.
Can we start making a more updated version of this? I say we, but I don't really know what I'm doing. I used this tutorial to try and make a music bot, but it didn't work. I'm not sure if that's because the libraries aren't set up right, or because I'm feeding it .mp3 files. But it no workie, and I can't find any other tutorials. I did what the tutorial said and renamed one of the .dll files, and placed both inside my bin/debug folder (Strange that you don't want to reference it, unless FFmpeg does on its own. I'm not sure), and it didn't do anything. I think I would have felt better if it threw an error so I could know what was wrong with it.
Same goes for me... the only thing I was able to find out is that it seems to get stuck at Line 59 ("await ffmpeg.StandardOutput.BaseStream.CopyToAsync(stream);") ... no idea why or how to fix it though! :/
Same goes for me... the only thing I was able to find out is that it seems to get stuck at Line 59 ("await ffmpeg.StandardOutput.BaseStream.CopyToAsync(stream);") ... no idea why or how to fix it though! :/
I got it working at some point, but I then switched to LavaLink. It requires you to have Java installed and to have a second terminal open to run it, but works great. It automatically searches for the song. You don't even need to install .mp3 files (you can if you want to still, just might not work with LavaLink). It would also be a good idea to switch over to DSharpPlus (if you decide to use LavaLink) because they have that linked with their API. So you don't have to do much to get it connected with the terminal that hosts LavaLink.
It says to me "Fille does not exists", IDK why...