LoginSignup
9
12

More than 5 years have passed since last update.

DiscordのBotでボイスチャンネルに音楽を流す

Posted at

検索してもなかなか出ないしめっちゃハマったので書きます。
今流行のDiscordのBotをめちゃくちゃ簡単に作れる「Discord.Net」という神ライブラリがあるのですが、
それをつかってボイスチャンネルにmp3を流す方法です。
Discord.Netの基本的なことはここを読むとわかりやすいです。

環境

  • Windows10
  • Visual Studio
  • Discord.Net

手順

  • Discord.NetとDiscord.Net.AudioをNugetで検索して入れる
  • 必要な2つのDLLを入れる(重要)
  • NAudioもNugetから入れる
  • サンプルコードの通りに書く

なお、再生するファイルはmp3です。

参考

Voice — Discord.Net 0.9.4 documentation

ここに全部載ってた。英語が読めなかった(小並)

DLLのダウンロード

Nugetを使うライブラリの方はいいとして、それとは別にexeファイルと同じ場所(デバッグ中ならbin/DEBUG)に入れるべきDLLが2つあります。
↓画像
SS_NoName_20161218175237_No00.jpg
↑の矢印のところのリンクをクリックして、GitHubのDownloadボタンを押してダウンロードします。
DLした「libsodium.dll」「opus.dll」をexeファイルと同じ場所にコピーしてください。

コード

ClientがAudioを使うよという宣言

var _client = new DiscordClient();

_client.UsingAudio(x => 
{
        x.Mode = AudioMode.Outgoing;
});

これを使う前にどこかで実行しておいてください。

ボイスチャンネルに参加(Join)

var voiceClient = await _client.GetService<AudioService>().Join(voiceChannel);

このvoiceClientを使って音を送信します。voiceChannelは、例えばMessageEventArgsの.User.VoiceChannelにアクセスすると、そのユーザーの参加しているボイスチャンネルが取得できます。
たとえばこう

_client.MessageReceived += (s,e) => { var vc = e.User.VoiceChannel;};

NAudioで音声のバイトデータを送る

さっきのページからの引用です。

using NAudio;
using NAudio.Wave;
using NAudio.CoreAudioApi;

public void SendAudio(string filePath)
{
        var channelCount = _client.GetService<AudioService>().Config.Channels; // Get the number of AudioChannels our AudioService has been configured to use.
        var OutFormat = new WaveFormat(48000, 16, channelCount); // Create a new Output Format, using the spec that Discord will accept, and with the number of channels that our client supports.
        using (var MP3Reader = new Mp3FileReader(filePath)) // Create a new Disposable MP3FileReader, to read audio from the filePath parameter
        using (var resampler = new MediaFoundationResampler(MP3Reader, OutFormat)) // Create a Disposable Resampler, which will convert the read MP3 data to PCM, using our Output Format
        {
                resampler.ResamplerQuality = 60; // Set the quality of the resampler to 60, the highest quality
                int blockSize = OutFormat.AverageBytesPerSecond / 50; // Establish the size of our AudioBuffer
                byte[] buffer = new byte[blockSize];
                int byteCount;

                while((byteCount = resampler.Read(buffer, 0, blockSize)) > 0) // Read audio into our buffer, and keep a loop open while data is present
                {
                        if (byteCount < blockSize)
                        {
                                // Incomplete Frame
                                for (int i = byteCount; i < blockSize; i++)
                                        buffer[i] = 0;
                        }
                        _vClient.Send(buffer, 0, blockSize); // Send the buffer to Discord
                }
        }

}

NAudioについては知らなかったのでそのままコピペして使いました。

まとめたクラス

using Discord;
using Discord.Audio;
using System;
using System.Threading.Tasks;
using NAudio.Wave;

namespace SinobigamiBot
{
    class VoiceSample
    {
        private DiscordClient Client { get; set; }
        public IAudioClient VoiceClient { get; set; }

        public VoiceSample(DiscordClient client)
        {
            Client = client;
        }

        /// <summary>
        /// これを呼び出して使う
        /// </summary>
        /// <returns></returns>
        public async Task SendAudio(Channel vChannel, string filepath)
        {
            await JoinChannel(vChannel);
            SendAudio(filepath);
        }

        private async Task JoinChannel(Channel vChannel)
        {
            VoiceClient = await Client.GetService<AudioService>().Join(vChannel);

        }

        private void SendAudio(string filepath)
        {
            if (!System.IO.File.Exists(filepath))
                throw new Exception("not found!!!!" + filepath);

            var channelCount = Client.GetService<AudioService>().Config.Channels; // Get the number of AudioChannels our AudioService has been configured to use.
            var OutFormat = new WaveFormat(48000, 16, channelCount); // Create a new Output Format, using the spec that Discord will accept, and with the number of channels that our client supports.
            using (var MP3Reader = new Mp3FileReader(filepath)) // Create a new Disposable MP3FileReader, to read audio from the filePath parameter
            using (var resampler = new MediaFoundationResampler(MP3Reader, OutFormat)) // Create a Disposable Resampler, which will convert the read MP3 data to PCM, using our Output Format
            {
                resampler.ResamplerQuality = 60; // Set the quality of the resampler to 60, the highest quality
                int blockSize = OutFormat.AverageBytesPerSecond / 50; // Establish the size of our AudioBuffer
                byte[] buffer = new byte[blockSize];
                int byteCount;

                while ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0) // Read audio into our buffer, and keep a loop open while data is present
                {
                    if (byteCount < blockSize)
                    {
                        // Incomplete Frame
                        for (int i = byteCount; i < blockSize; i++)
                            buffer[i] = 0;
                    }
                    VoiceClient.Send(buffer, 0, blockSize); // Send the buffer to Discord
                }
            }

        }
    }
}

インスタンスを生成してSendAudioに引数を渡せば再生できます!

まとめ

2つのDLLのダウンロードを忘れないこと!
あとは公式のページを読む!

9
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
12