diff options
| author | Adam Malczewski <[email protected]> | 2026-04-02 02:22:36 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-04-02 02:22:36 +0900 |
| commit | 738732db20d827c4a305434a82c6464f3ebaf65d (patch) | |
| tree | baa0c9eddc72660342d3d3266ed5262f100030a3 /.rules | |
| download | music-bot-738732db20d827c4a305434a82c6464f3ebaf65d.tar.gz music-bot-738732db20d827c4a305434a82c6464f3ebaf65d.zip | |
Diffstat (limited to '.rules')
| -rw-r--r-- | .rules/plan/research.md | 619 |
1 files changed, 619 insertions, 0 deletions
diff --git a/.rules/plan/research.md b/.rules/plan/research.md new file mode 100644 index 0000000..5ff33dd --- /dev/null +++ b/.rules/plan/research.md @@ -0,0 +1,619 @@ +# Discord Music Bot Development — Tool Research Report + +> **Query:** What tools are needed to develop a Discord bot that streams YouTube audio to voice channels, with queue management via user commands — preferring JavaScript/TypeScript. + +--- + +## Executive Summary + +Building a Discord music bot that streams YouTube audio to voice channels in 2025 requires a carefully chosen stack due to YouTube's frequently changing API restrictions and the deprecation of several once-popular libraries. The recommended modern stack centers on **Discord.js v14** (Discord API framework), **@discordjs/voice** (low-level voice layer), a high-level music framework (**discord-player** or **DisTube**), and a YouTube extraction backend using **youtubei.js** (via `discord-player-youtubei` extractor or DisTube's plugin system). For large-scale or production bots, **Lavalink v4** (a Java-based audio server) offers superior performance. TypeScript is natively supported by all recommended libraries and is strongly advisable. + +--- + +## Architecture Overview + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Discord API (WebSocket + REST) │ +└────────────────────────┬────────────────────────────────────────┘ + │ + ┌────────▼────────┐ + │ discord.js │ ← Bot framework (JS/TS) + │ v14 │ + └────────┬────────┘ + │ + ┌──────────────┴───────────────┐ + │ │ + ┌────────▼──────────┐ ┌──────────▼──────────┐ + │ Music Framework │ │ @discordjs/voice │ + │ (discord-player │───────▶│ (low-level voice │ + │ OR DisTube) │ │ connections) │ + └────────┬──────────┘ └──────────┬──────────┘ + │ │ + ┌────────▼──────────┐ ┌──────────▼──────────┐ + │ YouTube Extractor│ │ Audio Processing │ + │ (youtubei.js / │ │ FFmpeg + Opus │ + │ yt-dlp) │ │ (encoding/decoding)│ + └───────────────────┘ └─────────────────────┘ + + ─── OR, for large bots ─── + +┌──────────────────────────────────────────────────────────────────┐ +│ Lavalink v4 (Java server) │ +│ Lavaplayer + youtube-source plugin → streams audio via WS │ +│ Node.js client: lavalink-client npm package │ +└──────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Component 1: Discord Bot Framework — Discord.js v14 + +**Repository:** [discordjs/discord.js](https://github.com/discordjs/discord.js) +**NPM:** `discord.js` +**Language:** TypeScript (ships `.d.ts` declarations) + +Discord.js is the overwhelmingly dominant Discord API library for Node.js, offering complete coverage of the Discord REST API and Gateway WebSocket events.[^1] v14 introduced native TypeScript support, slash command builders, interaction handling, and the `GatewayIntentBits` enum. + +### Required Intents for a Music Bot + +```typescript +import { Client, GatewayIntentBits } from 'discord.js'; + +const client = new Client({ + intents: [ + GatewayIntentBits.Guilds, // required for slash commands + GatewayIntentBits.GuildVoiceStates, // required for voice channel management + GatewayIntentBits.GuildMessages, // for prefix commands (if used) + GatewayIntentBits.MessageContent, // PRIVILEGED: required to read message content + ], +}); +``` + +> **Note:** `MessageContent` is a **privileged intent** — it must be enabled manually in the [Discord Developer Portal](https://discord.com/developers/applications). For a slash-command-only bot, it's not needed. + +### Slash Command Structure + +Modern bots use slash commands (`/play`, `/skip`, `/queue`, etc.) registered via the REST API. The recommended structure: + +``` +src/ + commands/ + play.ts + skip.ts + queue.ts + stop.ts + events/ + ready.ts + interactionCreate.ts + deploy-commands.ts + index.ts +``` + +--- + +## Component 2: Voice Layer — @discordjs/voice + +**Repository:** [discordjs/voice](https://github.com/discordjs/voice) +**NPM:** `@discordjs/voice` + +This is the **official, low-level Discord voice library** from the discord.js team.[^2] It handles: +- Joining and leaving voice channels +- Creating and managing audio players +- Creating audio resources from streams +- Subscribing voice connections to audio players + +It is the backbone used by all higher-level music frameworks (DisTube, discord-player). + +### Key APIs + +```typescript +import { + joinVoiceChannel, + createAudioPlayer, + createAudioResource, + AudioPlayerStatus, + VoiceConnectionStatus, +} from '@discordjs/voice'; +``` + +### Required Peer Dependencies + +From the official README[^2], you need to install one option from each category: + +| Category | Recommended | Alternatives | Purpose | +|---|---|---|---| +| **Opus** | `@discordjs/opus` | `opusscript`, `mediaplex` | Audio encoding (Opus codec for Discord) | +| **Encryption** | `sodium-native` | `sodium`, `libsodium-wrappers`, `tweetnacl` | Encrypting voice data | +| **FFmpeg** | System FFmpeg | `ffmpeg-static` (npm) | Media transcoding | + +```bash +npm install @discordjs/voice @discordjs/opus sodium-native +# Install FFmpeg: sudo apt install ffmpeg (Linux) or brew install ffmpeg (Mac) +# OR: npm install ffmpeg-static +``` + +> **Important:** As of 2024, Node.js 16+ is required by `@discordjs/voice`; Node.js 20+ is recommended for modern discord.js projects.[^3] + +--- + +## Component 3: Music Frameworks (High-Level Abstractions) + +Rather than building queue management, audio resource handling, and track searching from scratch, use one of these frameworks that sit on top of `@discordjs/voice`. + +### Option A: discord-player (Recommended for TypeScript/Flexibility) + +**Repository:** [Androz2091/discord-player](https://github.com/Androz2091/discord-player) +**NPM:** `discord-player` + `@discord-player/extractor` +**Docs:** [discord-player.js.org](https://discord-player.js.org) + +discord-player is a robust, TypeScript-first music framework providing:[^4] +- Built-in queue management with repeat, shuffle, volume control +- 64+ built-in audio filter presets +- Extensible Extractor API (pluggable source backends) +- `useMainPlayer()` hooks for clean code patterns +- Automatic voice state handling +- IP rotation support +- Object-oriented design with events system + +```bash +npm install discord-player @discord-player/extractor mediaplex +``` + +```typescript +import { Player } from 'discord-player'; +import { DefaultExtractors } from '@discord-player/extractor'; +import { YoutubeiExtractor } from 'discord-player-youtubei'; + +const player = new Player(client); +await player.extractors.loadMulti(DefaultExtractors); +// Register the YouTube extractor (see Component 4 below) +await player.extractors.register(YoutubeiExtractor, {}); + +player.events.on('playerStart', (queue, track) => { + queue.metadata.channel.send(`▶️ Now playing: **${track.cleanTitle}**`); +}); +``` + +**Play command example:** +```typescript +import { useMainPlayer } from 'discord-player'; + +const player = useMainPlayer(); +const { track } = await player.play(voiceChannel, query, { + nodeOptions: { metadata: interaction }, +}); +await interaction.followUp(`✅ Enqueued: **${track.cleanTitle}**`); +``` + +> **Note:** discord-player v6+ uses `discord-voip` (a fork of `@discordjs/voice`) as its internal voice layer.[^4] + +--- + +### Option B: DisTube (Batteries-Included) + +**Repository:** [skick1234/DisTube](https://github.com/distubejs/distube) +**NPM:** `distube` +**Docs:** [distube.js.org](https://distube.js.org) + +DisTube is a high-level, all-in-one music bot library offering more out-of-the-box functionality:[^5] +- Built-in queue, playlist, and voice connection management +- 20+ built-in audio filters (bassboost, nightcore, echo, karaoke, etc.) +- Plugin system supporting YouTube, Spotify, SoundCloud, Bandcamp, and 700+ other sites +- Full TypeScript support +- Requires `discord.js v14` and `@discordjs/voice` + +```bash +npm install distube @discordjs/voice @discordjs/opus +``` + +```javascript +import { DisTube } from 'distube'; + +const distube = new DisTube(client, { emitNewSongOnly: true }); + +distube.on('playSong', (queue, song) => + queue.textChannel?.send(`▶️ Playing \`${song.name}\` - \`${song.formattedDuration}\``) +); + +// Play command handler +distube.play(message.member!.voice.channel!, query, { + message, + textChannel: message.channel, + member: message.member!, +}); +``` + +### Option A vs. B Comparison + +| Feature | discord-player | DisTube | +|---|---|---| +| Abstraction Level | Medium-High | High | +| TypeScript Quality | Excellent | Good | +| Queue Management | Built-in | Built-in | +| Audio Filters | 64+ presets | 20+ built-in | +| Plugin/Extractor System | Extractor API | Plugin system | +| Customizability | High | Moderate | +| Ease of Setup | Moderate | Simple | +| Supports 700+ sites | Via extractors | Via plugins (yt-dlp plugin) | +| Community Size | Large | Large | +| Voice Library | `discord-voip` (fork) | `@discordjs/voice` | + +**Recommendation:** Use **discord-player** for TypeScript-first, flexible development. Use **DisTube** if you want maximum out-of-the-box features with minimal setup. + +--- + +## Component 4: YouTube Audio Extraction — The Critical Piece + +YouTube is the most complex component due to frequent API changes and the **deprecation of ytdl-core** in August 2024.[^6] + +### ⚠️ What NOT to Use Anymore + +| Library | Status | Reason | +|---|---|---| +| `ytdl-core` | **Deprecated (Aug 2024)** | No longer maintained; frequently broken | +| `@distube/ytdl-core` | **Deprecated** | Maintenance stopped; recommends migration to youtubei.js | +| `play-dl` | **Archived (Jun 2025)** | Repository archived; no new updates | + +### ✅ Current Recommended Options + +#### Option 1: `discord-player-youtubei` (Best for discord-player) + +**Repository:** [retrouser955/discord-player-youtubei](https://github.com/retrouser955/discord-player-youtubei) +**NPM:** `discord-player-youtubei` + +Built on top of `youtubei.js` (YouTube's InnerTube API), this extractor plugin is the current community standard for discord-player YouTube support.[^7] + +```bash +npm install discord-player-youtubei +``` + +```typescript +import { YoutubeiExtractor } from 'discord-player-youtubei'; + +// Register once at startup - not in every command +await player.extractors.register(YoutubeiExtractor, { + // Optional: authenticate with YouTube account for higher rate limits + // authentication: 'OAUTH_TOKEN' +}); +``` + +#### Option 2: `youtubei.js` (LuanRT) — Direct Usage + +**Repository:** [LuanRT/YouTube.js](https://github.com/LuanRT/YouTube.js) +**NPM:** `youtubei.js` +**Docs:** [ytjs.dev](https://ytjs.dev) + +A full JavaScript client for YouTube's private InnerTube API. Enables searching, metadata fetching, and stream URL extraction. Used under the hood by `discord-player-youtubei` and referenced as the recommended successor to `ytdl-core`.[^6] + +#### Option 3: `yt-dlp` (via subprocess — Most Robust) + +**Binary:** [yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp) (Python, installed separately) +**Node wrapper:** `yt-dlp-wrap` npm package + +`yt-dlp` is a Python CLI tool that is the most actively maintained YouTube downloader. It handles YouTube's anti-bot measures most robustly.[^8] It can be called from Node.js as a subprocess: + +```typescript +import { spawn } from 'child_process'; +import { createAudioResource, StreamType } from '@discordjs/voice'; + +function getYtDlpStream(url: string) { + const proc = spawn('yt-dlp', [ + '-f', 'bestaudio', + '--no-playlist', + '-o', '-', // output to stdout + url, + ], { stdio: ['ignore', 'pipe', 'ignore'] }); + + return createAudioResource(proc.stdout, { + inputType: StreamType.Arbitrary, + }); +} +``` + +> **Note:** Requires `yt-dlp` binary to be installed on the host system (`pip install yt-dlp` or system package manager). Can also be used via DisTube's `@distube/yt-dlp` plugin. + +#### Option 4: DisTube YouTube Plugin + +For DisTube users, the official `@distube/youtube` plugin or the `@distube/yt-dlp` plugin handles YouTube extraction natively within the DisTube ecosystem.[^5] + +--- + +## Component 5: Lavalink — For Production/Large-Scale Bots + +**Repository:** [lavalink-devs/Lavalink](https://github.com/lavalink-devs/Lavalink) +**Docs:** [lavalink.dev](https://lavalink.dev) +**Version:** v4 (stable) + +Lavalink is a **standalone Java audio server** that offloads all audio processing from your bot's Node.js process.[^9] It communicates with your bot over WebSocket and is used in production by major bots (FredBoat, Dyno, etc.). + +### Why Lavalink? + +- **Performance**: Audio transcoding happens in a separate JVM process — your bot stays fast +- **Scalability**: Supports multiple nodes for horizontal scaling +- **Seeking**: Built-in seeking support +- **Volume control**: Precise volume control +- **Filters**: Equalizer, timescale, tremolo, vibrato, rotation, distortion filters +- **YouTube support**: Via the official `youtube-source` plugin for Lavaplayer[^10] + +### Requirements + +- **Java 17 LTS or newer** (runs as a separate process) +- Your Node.js bot connects as a client via WebSocket + +### Setup Overview + +1. **Download** the Lavalink JAR from [GitHub Releases](https://github.com/lavalink-devs/Lavalink/releases) +2. **Configure** `application.yml`: +```yaml +server: + port: 2333 +lavalink: + server: + password: "your-strong-password" +plugins: + youtube: + enabled: true + clients: ["MUSIC", "ANDROID_VR", "WEB", "WEBEMBEDDED"] +``` +3. **Run**: `java -jar Lavalink.jar` +4. **Connect** your Node.js bot using `lavalink-client`: + +```bash +npm install lavalink-client +``` + +```typescript +import { LavalinkManager } from 'lavalink-client'; + +client.lavalink = new LavalinkManager({ + nodes: [{ + authorization: 'your-strong-password', + host: 'localhost', + port: 2333, + id: 'main-node', + }], + sendToShard: (guildId, payload) => + client.guilds.cache.get(guildId)?.shard?.send(payload), + client: { id: process.env.CLIENT_ID!, username: 'MusicBot' }, +}); + +client.on('raw', d => client.lavalink.sendRawData(d)); +client.on('ready', () => client.lavalink.init({ ...client.user! })); +``` + +### Node.js Lavalink Clients + +| Package | Notes | +|---|---| +| `lavalink-client` | Most actively maintained; full TypeScript support | +| `shoukaku` | Performant, popular choice | +| `lavacord` | Lightweight; [lavacord.js.org](https://lavacord.js.org) | +| `moonlink.js` | Alternative with good TS support | + +### Lavalink YouTube Source Plugin + +The official [`youtube-source`](https://github.com/lavalink-devs/youtube-source) plugin for Lavaplayer uses multiple InnerTube clients to maximize success rate against YouTube's anti-bot measures.[^10] Configure in `application.yml` as shown above. + +--- + +## Component 6: Development Toolchain + +### TypeScript Setup + +```bash +npm install -D typescript @types/node ts-node tsup +``` + +**Recommended `tsconfig.json`:** +```json +{ + "compilerOptions": { + "target": "ES2022", + "module": "commonjs", + "lib": ["ES2022"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} +``` + +**Build tool:** Use **`tsup`** (fast, zero-config TypeScript bundler) or plain `tsc`. + +### Environment Variables + +Use **`dotenv`** for managing secrets: +```bash +npm install dotenv +``` + +``` +# .env +DISCORD_TOKEN=your_bot_token +CLIENT_ID=your_application_id +GUILD_ID=optional_test_guild_id +``` + +### Project Scaffolding Options + +| Template | Description | +|---|---| +| [KevinNovak/Discord-Bot-TypeScript-Template](https://github.com/KevinNovak/Discord-Bot-TypeScript-Template) | Production-ready TS template with PM2/Docker support | +| [MericcaN41/discordjs-v14-template-ts](https://github.com/MericcaN41/discordjs-v14-template-ts) | Handlers, MongoDB, permissions, cooldowns | + +--- + +## Component 7: Persistence & State Management + +For queue persistence across restarts or advanced features: + +| Need | Tool | +|---|---| +| Simple key-value / queue state | **Redis** (`ioredis` npm) | +| Relational data (playlists, server settings) | **PostgreSQL** via `pg` or **SQLite** via `better-sqlite3` | +| ORM | **Prisma** (excellent TypeScript support) | +| In-memory only (simplest) | Native `Map<string, Queue>` (no persistence) | + +For most bots, an in-memory `Map` per guild is sufficient for queue state. Persist only playlists/settings to a database. + +--- + +## Component 8: Deployment & Hosting + +### Minimum Hardware Requirements + +- **RAM:** 512 MB minimum; 1 GB recommended (2+ GB if running Lavalink on the same host) +- **CPU:** 1 vCPU minimum +- **OS:** Ubuntu 22.04+ LTS recommended +- **Java:** Required only if running Lavalink on the same host (Java 17+) + +### Process Management + +**PM2** (simpler, Node.js-native): +```bash +npm install -g pm2 +pm2 start dist/index.js --name music-bot +pm2 save && pm2 startup +``` + +**Docker** (more portable, production-grade): +```dockerfile +FROM node:20-alpine +WORKDIR /app +RUN apk add --no-cache ffmpeg python3 py3-pip && pip3 install yt-dlp +COPY package*.json ./ +RUN npm ci --only=production +COPY dist/ ./dist/ +CMD ["node", "dist/index.js"] +``` + +Use `docker-compose.yml` to run the bot + Lavalink together. + +### Hosting Providers + +| Provider | Type | Notes | +|---|---|---| +| DigitalOcean Droplet | VPS | $6/mo for 1GB RAM; full control | +| Linode/Akamai | VPS | Similar to DigitalOcean | +| Hetzner Cloud | VPS | Cheapest per-GB in EU | +| Railway.app | PaaS | Easy deploy, free tier available | +| Fly.io | PaaS | Free tier with containers | +| VPS self-hosted | VPS | Maximum control | + +> **Avoid serverless platforms** (Lambda, Vercel) — Discord bots require persistent WebSocket connections. + +--- + +## Full Recommended Stack Summary + +### For a Starter/Personal Bot (Simpler) + +```bash +npm install discord.js @discordjs/voice discord-player @discord-player/extractor \ + discord-player-youtubei mediaplex ffmpeg-static sodium dotenv +npm install -D typescript @types/node ts-node tsup +``` + +| Layer | Choice | +|---|---| +| Discord API | `discord.js` v14 | +| Voice | `@discordjs/voice` (via discord-player internally) | +| Music Framework | `discord-player` v6+ | +| YouTube Backend | `discord-player-youtubei` (uses `youtubei.js`) | +| Opus Encoding | `mediaplex` | +| FFmpeg | `ffmpeg-static` or system install | +| Encryption | `sodium` | +| Language | TypeScript | +| Deployment | PM2 on a VPS | + +### For a Production Bot (Large Scale) + +```bash +npm install discord.js lavalink-client dotenv +npm install -D typescript @types/node tsup +# On server: Java 17+, then run Lavalink JAR +``` + +| Layer | Choice | +|---|---| +| Discord API | `discord.js` v14 | +| Voice/Streaming | Lavalink v4 (Java server) + `lavalink-client` | +| YouTube Backend | Lavalink `youtube-source` plugin | +| Language | TypeScript | +| Deployment | Docker Compose (bot + Lavalink) on VPS | + +--- + +## Legal & ToS Considerations + +> ⚠️ **Important:** Streaming YouTube audio directly to Discord may violate [YouTube's Terms of Service](https://www.youtube.com/static?template=terms), specifically Section 5.B which prohibits downloading content except through YouTube's explicitly permitted mechanisms. + +Key considerations: +- **Private bots** (in your own server) face significantly less legal risk than public bots +- Two of the largest music bots — **Groovy** and **Rythm** — were shut down in 2021 following legal pressure from YouTube/Google +- YouTube's Music API and official embeds are the ToS-compliant alternatives +- Bots using Spotify typically use Spotify's search to find the song name, then stream the YouTube equivalent (since Spotify doesn't provide audio streams) +- Consider using **SoundCloud** or other platforms with permissive APIs as alternatives or fallbacks + +--- + +## Key Repositories Summary + +| Repository | Purpose | Language | +|---|---|---| +| [discordjs/discord.js](https://github.com/discordjs/discord.js) | Discord API client library | TypeScript | +| [discordjs/voice](https://github.com/discordjs/voice) | Discord voice connections | TypeScript | +| [Androz2091/discord-player](https://github.com/Androz2091/discord-player) | High-level music framework | TypeScript | +| [skick1234/DisTube](https://github.com/distubejs/distube) | All-in-one music library | TypeScript | +| [retrouser955/discord-player-youtubei](https://github.com/retrouser955/discord-player-youtubei) | YouTube extractor for discord-player | TypeScript | +| [LuanRT/YouTube.js](https://github.com/LuanRT/YouTube.js) | InnerTube API client | TypeScript | +| [lavalink-devs/Lavalink](https://github.com/lavalink-devs/Lavalink) | Audio server for large bots | Java | +| [lavalink-devs/youtube-source](https://github.com/lavalink-devs/youtube-source) | YouTube plugin for Lavalink | Java | +| [lavalink-devs/lavalink-client](https://github.com/lavalink-devs/lavalink-client) | Node.js Lavalink client | TypeScript | +| [yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp) | YouTube downloader CLI | Python | + +--- + +## Confidence Assessment + +| Finding | Confidence | Notes | +|---|---|---| +| discord.js v14 is the standard | **Very High** | Unambiguous community consensus | +| `ytdl-core` is deprecated (Aug 2024) | **Very High** | Confirmed via npm README + GitHub | +| `play-dl` is archived (Jun 2025) | **Very High** | Confirmed via GitHub repo status | +| `discord-player-youtubei` is recommended | **High** | Multiple community sources + GitHub | +| `discord-player` uses `discord-voip` fork | **High** | Confirmed via official README[^4] | +| Lavalink v4 is stable | **Very High** | Confirmed via official README[^9] | +| Lavalink youtube-source uses InnerTube | **Very High** | Confirmed via repo README[^10] | +| `mediaplex` is recommended over `@discordjs/opus` for discord-player | **High** | Stated in discord-player README[^4] | +| Legal risks around YouTube streaming | **High** | Based on precedent (Groovy/Rythm) + YouTube ToS | + +--- + +## Footnotes + +[^1]: [discordjs/discord.js](https://github.com/discordjs/discord.js) — Official Discord.js repository; docs at [discord.js.org](https://discord.js.org) + +[^2]: [discordjs/voice README.md](https://github.com/discordjs/voice/blob/main/README.md) — Lists all required optional dependencies (encryption, Opus, FFmpeg) + +[^3]: [discordjs/voice installation docs](https://discordjs.guide/voice) — Node.js 16+ required; 20+ recommended + +[^4]: [Androz2091/discord-player README.md](https://github.com/Androz2091/discord-player/blob/master/README.md) — Full setup instructions, mediaplex recommendation, FFmpeg notes + +[^5]: [skick1234/DisTube README.md](https://github.com/distubejs/distube/blob/main/README.md) — Official README; plugin architecture; install `distube @discordjs/voice @discordjs/opus` + +[^6]: [ytdl-core deprecation discussion](https://stackoverflow.com/questions/78824388/ytdl-core-is-returning-a-stream-with-nothing-in-it) — Community discussion on ytdl-core being broken; `@distube/ytdl-core` points to `youtubei.js` as successor; [npm @distube/ytdl-core](https://www.npmjs.com/package/@distube/ytdl-core) + +[^7]: [retrouser955/discord-player-youtubei GitHub](https://github.com/retrouser955/discord-player-youtubei) — YouTube extractor built on youtubei.js for discord-player v6/v7 + +[^8]: [yt-dlp PyPI](https://pypi.org/project/yt-dlp/) — Most actively maintained YouTube downloader; regularly updated against YouTube's bot detection + +[^9]: [lavalink-devs/Lavalink README.md](https://github.com/lavalink-devs/Lavalink/blob/master/README.md) — v4 is stable; Java 17 required; used by FredBoat, Dyno in production + +[^10]: [lavalink-devs/youtube-source README.md](https://github.com/lavalink-devs/youtube-source) — YouTube plugin for Lavaplayer using multiple InnerTube clients for robustness |
