Welcome, Guest. Please login or register | Contrast:

Author Topic: [v1.0] Play audio from YT or local file  (Read 1291 times)

CHT

  • *
  • Junior Contributor

  • Total posts: 16
  • Reputation: 11

[v1.0] Play audio from YT or local file
« on: 31 May 2017, 09:38:19 »
Spoiler: Thanks • show
ChristianFreak/Chris, for making the YT part of this guide.
The long gone d3illust/Code 4 Coffee, which made that pin for local audio in the Coding With Storm Discord.
Myself, for the additional stuff and testing. I'm that much of an attention hoarder.


Requirements:
-Have a copy of Visual Studio installed, that is able to make C# Console Apps.
-Have a bot that's able to use commands, and has the required links to audio service.
-Discord.Net v1.0.0-rc minimum.
-The AudioModule.cs and AudioService.cs from here.

Stuff to note:
1. While the code is similar, I've tweaked it to use a two file system instead.
2. Due to the change, a stop command will be able to work. This has been tested.
3. The stop command sadly makes your bot leave the channel. When it does so, use the leave command, then make it join again.

Setting up prerequisites:
Spoiler: show
1. Make sure you have libsodium and opus(rename from libopus to opus) dlls, ytdl and ffmpeg in the required locations.

2. Have the audio code from here in the respective files shown. Blindly copying would lead to failure later on, and I won't take any responsibility for that.

3. Be sure to have the following line in AudioModule as shown below.
Code: [Select]
using System.Diagnostics;
4. Have a line in AudioService as below, just above/below the link for ConcurrentDictionary. If you had copied the entire stuff from part 2, remove the IAudioClient client lines.
Code: [Select]
public static IAudioClient client;


Making magic:
Spoiler: show
All stuff are in AudioModule, unless otherwise stated.

1. Have the CreateStream Process from here in AudioService. If you don't recall how to, the code block below will help.
Code: [Select]
private Process CreateLinkStream(string url)
{
      Process currentsong = new Process();

      currentsong.StartInfo = new ProcessStartInfo
      {
           FileName = "cmd.exe",
           Arguments = $"/C youtube-dl.exe -o - {url} | ffmpeg -i pipe:0 -ac 2 -f s16le -ar 48000 pipe:1",
           UseShellExecute = false,
           RedirectStandardOutput = true,
           CreateNoWindow = true
      };

      currentsong.Start();
      return currentsong;
}
2. In your play command, have the parameters as shown below.
Code: [Select]
public async Task PlayCmd(string param, [Remainder] string song)
3. Within the command, adjust the code according so that the current code it has falls under an if statement. This code will be used for playing local files. Shown below is a reference/guide.
Code: [Select]
if (param.Contains("local"))
            {
                await _service.SendAudioAsync(Context.Guild, Context.Channel, song);
            }
4. Add an else if to play the YT links. Shown below is a reference/guide.
Code: [Select]
else if (param.Contains("online"))
            {
                await _service.SendLinkAsync(Context.Guild, Context.Channel, song);
            }
5. Add the following code to AudioService.
Code: [Select]
public async Task SendLinkAsync(IGuild guild, IMessageChannel channel, string path)
        {
            if (ConnectedChannels.TryGetValue(guild.Id, out client))
            {
                var output = CreateLinkStream(path).StandardOutput.BaseStream;
                var stream = client.CreatePCMStream(AudioApplication.Music, 128 * 1024); //, 128 * 1024 helps with low-end computers streaming.
                await output.CopyToAsync(stream);
                await stream.FlushAsync().ConfigureAwait(false);
            }
        }

6. (Optional) Add an else to inform the user what options are available. No reference/guide for this, cause this is your personal preference.

7. (Optional) Have a simple stop command as you wish. The codes to add in the respective cs files are as listed.
Code: AudioService.cs [Select]
public async Task StopAudio(IGuild guild)
        {
            await client.StopAsync();
            return;
        }
Code: [Select]
[Command("stop", RunMode = RunMode.Async)]
        public async Task StopCmd()
        {
            await _service.StopAudio(Context.Guild);
        }


With that, you now have the best of both local file streaming, and YT music. As I tested the code, there should be no errors. If there's something you're unsure with within the guide, let me know.

Edit: Your AudioService code in the end should look something similar to this, if you have the stop command. If not, omit it during the checking.
If you copy this and don't understand how to make it work, I'm not available for assistance.

CHT

  • *
  • Junior Contributor

  • Total posts: 16
  • Reputation: 11

Re: [v1.0] Play audio from YT or local file
« Reply #1 on: 03 June 2017, 19:46:25 »
Changed how the audio stuff works, and thus it's working better than ever.

CHT

  • *
  • Junior Contributor

  • Total posts: 16
  • Reputation: 11

Re: [v1.0] Play audio from YT or local file
« Reply #2 on: 30 August 2017, 21:57:54 »
Changed links for libsodium and libopus.

Lost

  • *
  • Newbie Contributor

  • Total posts: 2
  • Reputation: 0

Re: [v1.0] Play audio from YT or local file
« Reply #3 on: 03 December 2017, 20:18:27 »
Hello!

So I've been writing out the code and to cut to the chase it says that 'VideoInfo' basically doesn't exist, I've tried all other directories of 'youtubeExplode' but no luck.