【2025年最新版】Discord音楽Botの作り方初心者向け完全ガイド - Node.jsで超高機能な音楽再生Botを作ろう!

はじめに

「Discordで友達と通話しながら、みんなで音楽を聴きたい!」そんな願いを叶える音楽Botを、Node.jsで一から作ってみませんか?

この記事では、プログラミング初心者の方でも理解できるように、YouTube音楽を再生できる高機能Discord Botの作り方を徹底解説します。完成するBotには、以下のような豪華な機能が搭載されています。

完成するBotの機能一覧

  • ✅ YouTube音楽の再生(URLまたは検索ワードで指定可能)
  • ✅ プレイリスト対応(最大50曲を一括追加)
  • ✅ キュー管理(複数の曲を順番に再生)
  • ✅ シャッフル・ループ再生
  • ✅ 音量調整・一時停止・スキップ
  • ✅ 進行状況バー表示
  • ✅ 5分間未使用時の自動退出

それでは、一緒に作っていきましょう!

1. 準備:必要なものをインストールしよう

1-1. Node.jsのインストール

まず、Node.jsをインストールします。Node.jsは、JavaScriptをパソコン上で動かすための環境です。

インストール手順:

  1. Node.js公式サイトにアクセス
  2. 「LTS版(推奨版)」をダウンロード
  3. ダウンロードしたファイルを実行してインストール

インストールできたか確認するため、ターミナル(WindowsならコマンドプロンプトやPowerShell)を開いて以下を実行してください。

bash

node --version

v18.0.0のようなバージョン番号が表示されればOKです!

1-2. FFmpegのインストール

FFmpegは、音声ファイルを処理するための必須ツールです。

macOSの場合:

bash

brew install ffmpeg

Windowsの場合:

  1. FFmpeg公式サイトからダウンロード
  2. 解凍してパスを通す(詳しくは「FFmpeg Windows インストール」で検索)

Linuxの場合:

bash

sudo apt update
sudo apt install ffmpeg

2. Discord Botの作成と招待

2-1. Discord Developer Portalでアプリを作成

  1. Discord Developer Portalにアクセス
  2. 「New Application」ボタンをクリック
  3. 好きな名前を入力(例:「My Music Bot」)
  4. 左メニューから「Bot」を選択
  5. 「Add Bot」をクリックしてBotユーザーを作成

2-2. 重要な設定を有効化

Bot設定画面で、以下の設定を必ず有効にしてください:

  • ✅ MESSAGE CONTENT INTENT - これがないとメッセージを読み取れません
  • ✅ SERVER MEMBERS INTENT(推奨)
  • ✅ PRESENCE INTENT(推奨)

2-3. トークンを取得

「TOKEN」セクションで「Reset Token」をクリックし、表示されたトークンをコピーします。

⚠️ 重要: トークンは他人に見せないでください!悪用される可能性があります。

2-4. Botをサーバーに招待

  1. 左メニューから「OAuth2」→「URL Generator」を選択
  2. 「SCOPES」で「bot」にチェック
  3. 「BOT PERMISSIONS」で以下にチェック:
    • Send Messages(メッセージ送信)
    • Connect(接続)
    • Speak(発言)
    • Read Message History(メッセージ履歴を読む)
  4. 画面下部に生成されたURLをコピーしてブラウザで開く
  5. Botを追加したいサーバーを選択して「認証」

これでBotがサーバーに参加しました!(まだオフライン状態ですが、これから起動させます)

3. プロジェクトのセットアップ

3-1. プロジェクトフォルダの作成

好きな場所に新しいフォルダを作り、そこで作業します。

bash

mkdir discord-music-bot
cd discord-music-bot

3-2. package.jsonの作成

プロジェクトの初期化を行います。

bash

npm init -y

これでpackage.jsonというファイルが作成されます。このファイルを開いて、以下のように編集します。

json

{
  "name": "discord-music-bot",
  "version": "1.0.0",
  "description": "Discord音楽再生Bot",
  "main": "main.js",
  "type": "module",
  "scripts": {
    "start": "node main.js",
    "dev": "node --watch main.js"
  },
  "dependencies": {
    "@discordjs/opus": "^0.9.0",
    "@discordjs/voice": "^0.16.1",
    "@distube/ytdl-core": "^4.16.12",
    "discord.js": "^14.14.1",
    "dotenv": "^16.4.1",
    "ffmpeg-static": "^5.2.0",
    "play-dl": "^1.9.7",
    "sodium-native": "^5.0.9",
    "youtube-dl-exec": "^3.0.25"
  }
}

各パッケージの役割:

  • discord.js: Discord APIを簡単に使えるようにするライブラリ
  • @discordjs/voice: 音声機能を提供
  • play-dl: YouTube動画の情報取得と再生
  • ytdl-core: YouTubeストリーミング(予備手段)
  • youtube-dl-exec: yt-dlpを使った確実な動画取得
  • dotenv: 環境変数の管理
  • sodium-native: 音声の暗号化

3-3. 依存関係のインストール

以下のコマンドで、必要なパッケージを一括インストールします。

bash

npm install

これには数分かかる場合があります。コーヒーでも飲んで待ちましょう☕

3-4. 環境変数ファイルの作成

プロジェクトフォルダに.envというファイルを作成し、以下を記述します。

env

DISCORD_TOKEN=先ほどコピーしたBotのトークン
PREFIX=!
YOUTUBE_COOKIE=cookies.txt

DISCORD_TOKENの部分には、Developer Portalでコピーしたトークンを貼り付けてください。

3-5. cookieの設定

Chrome/Edgeの場合

1. 拡張機能「Get cookies.txt LOCALLY」をインストール

   - https://chrome.google.com/webstore/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc

2. YouTubeにログイン(https://www.youtube.com)

3. 拡張機能アイコンをクリック

4. 「 ALL Export」をクリック

5. ダウンロードした `cookies.txt` をこのプロジェクトのルートフォルダに配置

Firefoxの場合

1. アドオン「cookies.txt」をインストール

   - https://addons.mozilla.org/firefox/addon/cookies-txt/

2. YouTubeにログイン(https://www.youtube.com)

3. アドオンアイコンをクリック

4. 「Current Site」を選択

5. `cookies.txt` として保存し、このプロジェクトのルートフォルダに配置

4. メインコードの実装

いよいよコーディングです!main.jsという名前でファイルを作成し、以下のコードを記述していきます。

4-1. 基本的な構造とインポート

javascript

import { Client, GatewayIntentBits, EmbedBuilder } from 'discord.js';
import { 
  joinVoiceChannel, 
  createAudioPlayer, 
  createAudioResource, 
  AudioPlayerStatus,
  VoiceConnectionStatus,
  entersState,
  StreamType
} from '@discordjs/voice';
import play from 'play-dl';
import ytdl from '@distube/ytdl-core';
import youtubedl from 'youtube-dl-exec';
import dotenv from 'dotenv';
import { PassThrough } from 'stream';

dotenv.config();

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
    GatewayIntentBits.GuildVoiceStates,
  ],
});

const PREFIX = process.env.PREFIX || '!';
const queues = new Map();

解説:

  • 必要なモジュールをインポート
  • dotenv.config().envファイルを読み込み
  • intentsでBotが受け取るイベントの種類を指定
  • queuesでサーバーごとの再生キューを管理

4-2. キュー管理クラスの作成

音楽の再生を管理するクラスを作ります。これがBotの心臓部です。

javascript

class MusicQueue {
  constructor(guildId, textChannel) {
    this.guildId = guildId;
    this.textChannel = textChannel;
    this.songs = [];
    this.connection = null;
    this.player = createAudioPlayer();
    this.isPlaying = false;
    this.currentSong = null;
    this.volume = 50;
    this.loop = false;
    this.loopQueue = false;
    this.startTime = null;

    // 曲が終わったら次の曲を再生
    this.player.on(AudioPlayerStatus.Idle, () => {
      if (this.loop && this.currentSong) {
        this.songs.unshift(this.currentSong);
      } else if (this.loopQueue && this.currentSong) {
        this.songs.push(this.currentSong);
      }
      this.playNext();
    });

    this.player.on('error', error => {
      console.error('プレイヤーエラー:', error.message);
      this.playNext();
    });
  }

  addSong(song) {
    this.songs.push(song);
  }

  // ... 他のメソッドは後述
}

クラスのポイント:

  • songs: 再生待ちの曲を保存する配列
  • player: 実際に音楽を再生するプレイヤー
  • loop: 1曲リピート機能
  • loopQueue: キュー全体のリピート機能

4-3. 再生機能の実装

javascript

async playNext() {
  if (this.songs.length === 0) {
    this.isPlaying = false;
    this.currentSong = null;
    
    if (this.textChannel) {
      this.textChannel.send('✅ キューの再生が完了しました。');
    }
    return;
  }

  this.currentSong = this.songs.shift();
  this.isPlaying = true;

  try {
    // yt-dlpを最優先使用(最も信頼性が高い)
    const ytdlpStream = youtubedl.exec(this.currentSong.url, {
      format: 'bestaudio[ext=webm]/bestaudio',
      output: '-',
    });
    
    const passThrough = new PassThrough();
    ytdlpStream.stdout.pipe(passThrough);
    
    const resource = createAudioResource(passThrough, {
      inputType: StreamType.Arbitrary,
      inlineVolume: true,
    });
    
    this.player.play(resource);
    
    // 再生開始メッセージ
    if (this.textChannel) {
      const embed = new EmbedBuilder()
        .setColor(0x00FF00)
        .setTitle('🎵 再生中')
        .setDescription(`[${this.currentSong.title}](${this.currentSong.url})`)
        .setThumbnail(this.currentSong.thumbnail || '')
        .addFields(
          { name: '再生時間', value: formatDuration(this.currentSong.duration), inline: true },
          { name: 'リクエスト', value: this.currentSong.requestedBy, inline: true }
        );
      
      this.textChannel.send({ embeds:  });
    }
  } catch (error) {
    console.error('再生エラー:', error.message);
    this.playNext(); // エラーが出ても次の曲を再生
  }
}

3段階フォールバック戦略:

  1. yt-dlp: 最も確実な方法(第一選択)
  2. ytdl-core: yt-dlpが失敗した場合の予備
  3. play-dl: 最後の手段

この3つを組み合わせることで、ほとんどの動画を再生できるようになります。

4-4. playコマンドの実装

ユーザーからのコマンドを処理する部分です。

javascript

client.on('messageCreate', async (message) => {
  if (message.author.bot || !message.content.startsWith(PREFIX)) return;

  const args = message.content.slice(PREFIX.length).trim().split(/ +/);
  const command = args.shift().toLowerCase();

  let queue = queues.get(message.guild.id);

  if (command === 'play' || command === 'p') {
    const voiceChannel = message.member?.voice?.channel;
    if (!voiceChannel) {
      return message.reply('先にボイスチャンネルに参加してください!');
    }

    if (!args.length) {
      return message.reply('YouTubeのURLまたは検索ワードを入力してください!');
    }

    const query = args.join(' ');

    try {
      await message.channel.sendTyping();

      let song;
      const validateResult = play.yt_validate(query);
      
      if (validateResult === 'video') {
        // 直接URLが指定された場合
        const songInfo = await play.video_info(query);
        song = {
          title: songInfo.video_details.title,
          url: songInfo.video_details.url,
          duration: songInfo.video_details.durationInSec,
          thumbnail: songInfo.video_details.thumbnails[0]?.url || '',
          requestedBy: message.author.tag,
        };
      } else {
        // 検索ワードの場合
        const searchResults = await play.search(query, { 
          limit: 1, 
          source: { youtube: 'video' } 
        });
        
        if (!searchResults || searchResults.length === 0) {
          return message.reply('❌ 曲が見つかりませんでした。');
        }
        
        const video = searchResults[0];
        song = {
          title: video.title,
          url: video.url,
          duration: video.durationInSec,
          thumbnail: video.thumbnails[0]?.url || '',
          requestedBy: message.author.tag,
        };
      }

      if (!queue) {
        queue = new MusicQueue(message.guild.id, message.channel);
        queues.set(message.guild.id, queue);
      }

      queue.addSong(song);

      const embed = new EmbedBuilder()
        .setColor(0x00FF00)
        .setTitle('🎵 キューに追加しました')
        .setDescription(`[${song.title}](${song.url})`)
        .setThumbnail(song.thumbnail);

      await message.reply({ embeds:  });

      if (!queue.isPlaying) {
        await queue.play(voiceChannel);
      }
    } catch (error) {
      console.error('playコマンドエラー:', error);
      message.reply('❌ エラーが発生しました。');
    }
  }
});

このコードのポイント:

  • play.yt_validate()でURLか検索ワードかを判定
  • URLなら直接情報取得、検索ワードなら検索してから取得
  • Embedメッセージで見た目を美しく
  • エラーハンドリングでBotが落ちないようにする

4-5. その他の便利なコマンド

javascript

// スキップコマンド
else if (command === 'skip' || command === 's') {
  if (!queue || !queue.isPlaying) {
    return message.reply('再生中の曲がありません。');
  }
  queue.skip();
  message.reply('⏭️ スキップしました。');
}

// キュー表示コマンド
else if (command === 'queue' || command === 'q') {
  if (!queue || (!queue.currentSong && queue.songs.length === 0)) {
    return message.reply('キューは空です。');
  }

  let queueList = '';
  if (queue.currentSong) {
    queueList += `**▶️ 再生中:**\n${queue.currentSong.title}\n\n`;
  }

  if (queue.songs.length > 0) {
    queueList += '**次の曲:**\n';
    queue.songs.slice(0, 10).forEach((song, index) => {
      queueList += `${index + 1}. ${song.title}\n`;
    });
  }

  const embed = new EmbedBuilder()
    .setColor(0xFF00FF)
    .setTitle('📜 再生キュー')
    .setDescription(queueList);

  message.reply({ embeds:  });
}

// ループコマンド
else if (command === 'loop' || command === 'l') {
  if (!queue) {
    return message.reply('再生中の曲がありません。');
  }
  queue.loop = !queue.loop;
  message.reply(queue.loop ? '🔂 1曲ループを有効にしました。' : '▶️ 1曲ループを無効にしました。');
}

4-6. Bot起動処理

javascript

client.once('clientReady', () => {
  console.log(`${client.user.tag} としてログインしました!`);
  client.user.setActivity('音楽 | !help', { type: 'LISTENING' });
});

client.login(process.env.DISCORD_TOKEN);

5. Botを起動しよう

すべてのコードが揃ったら、いよいよ起動です!

bash

npm start

ターミナルに「としてログインしました!」というメッセージが表示されれば成功です🎉

Discordを開いて、Botがオンラインになっているか確認しましょう。

6. 使ってみよう

基本的な使い方

  1. ボイスチャンネルに参加
  2. テキストチャンネルで !play https://www.youtube.com/watch?v=... または !play 曲名
  3. Botが自動的にVCに参加して音楽を再生開始!

便利なコマンド例

bash

# 曲を検索して再生
!play YOASOBI 夜に駆ける

# キューを確認
!queue

# 現在再生中の曲を表示
!nowplaying

# シャッフル
!shuffle

# ループ再生
!loop

# 音量調整(次の曲から反映)
!volume 70

7. よくある問題と解決法

問題1: 「MESSAGE CONTENT INTENT」エラー

解決法: Discord Developer PortalでINTENTを有効にする

問題2: 音が出ない

原因と解決法:

  • FFmpegがインストールされていない → インストールし直す
  • Botに権限がない → サーバー設定で権限を付与
  • トークンが間違っている → .envファイルを確認

問題3: YouTube 403エラー

2024年後半から、YouTubeの保護が強化されています。

解決法:

  1. Cookieを設定する(推奨・最も効果的)
  2. 別の動画を試す
  3. APIを設定する

問題4: 再生が途中で止まる

原因と解決法:

  • ネット回線が不安定 → 安定した回線に切り替える
  • サーバー負荷が高い → 他のプログラムを終了する
  • 動画が削除/非公開 → 別の動画を試す

8. さらに機能を追加するアイデア

このBotはすでに高機能ですが、さらに以下のような機能を追加できます:

追加機能のアイデア

  • お気に入り機能: ユーザーごとにプレイリストを保存
  • 歌詞表示: Genius APIと連携
  • イコライザー: 音質調整機能
  • 投票スキップ: 複数人の投票でスキップ
  • 24時間配信: 自動で音楽を流し続ける
  • Spotify連携: Spotifyのプレイリストにも対応

データベース連携

より高度な機能を実装するなら、MongoDBやSQLiteを使ってデータを永続化しましょう。

bash

npm install mongoose  # MongoDBの場合

まとめ

お疲れ様でした!これで、あなただけの高機能Discord音楽Botが完成しました🎉

この記事で学んだこと:

  • ✅ Discord Botの作成と招待
  • ✅ Node.jsでの非同期プログラミング
  • ✅ 音声ストリーミングの処理
  • ✅ エラーハンドリングとフォールバック戦略
  • ✅ Embedメッセージでの美しいUI作成

このBotをベースに、自分だけのオリジナル機能を追加してみてください。プログラミングは楽しむことが一番大切です!

質問や改善案があれば、ぜひコミュニティで共有してください。それでは、素敵な音楽ライフを!🎵

参考リンク:


この記事は2025年10月時点の最新情報に基づいています。APIの仕様変更により、一部の機能が動作しなくなる可能性があります。

\ 最新情報をチェック /

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です