MAATRIX GAMES / Блог / Музыкальный бот для голосовых каналов Discord

Музыкальный бот для голосовых каналов Discord

MAATRIX GAMES

Если вы ставили музыкального бота года три назад и с тех пор не трогали — он почти наверняка сломался. YouTube несколько раз за последние годы менял механизм подписи и выдачи потоков, старые связки на голом ytdl-core или древнем lavaplayer без патчей сыплют 403 и обрывают трек через пять секунд после старта. Разберём, что реально работает сейчас, как поднять бота самому на Lavalink, чем это отличается от готового сервиса и на что обратить внимание с правами на воспроизведение — тема скользкая, но обходить её молчанием было бы нечестно.

Почему старые музыкальные боты сломались

YouTube не даёт стабильного публичного API для получения аудиопотока — все музыкальные боты так или иначе идут в обход, эмулируя поведение официального клиента (веб, Android, iOS) и расшифровывая подпись signatureCipher на лету. Раз в несколько месяцев YouTube меняет алгоритм обфускации, и все библиотеки, которые не обновляются активно, отваливаются разом: то 410 Gone, то бесконечный 403 Forbidden, то трек грузится, но обрывается на середине.

Вторая, более свежая проблема — PoToken (proof-of-origin token). С 2024 года YouTube всё активнее требует его для части клиентских типов: без токена сервер либо режет битрейт до почти нерабочего, либо сразу отдаёт ошибку. PoToken генерируется через эмуляцию браузерного окружения (BotGuard/JS-челлендж), и библиотеки, которые не умеют его выпускать, для многих видео просто перестают работать — особенно для музыки с активной защитой от ботов.

Отсюда практический вывод: любой проект, который не обновлялся последние полгода-год (включая многие туториалы в интернете), скорее всего не взлетит из коробки. Дальше — что реально держится на плаву.

Lavalink — ядро, на котором сейчас строят рабочих ботов

Lavalink — отдельный Java-сервер для стриминга аудио, к которому бот подключается по WebSocket и просто просит "играй этот трек". Сам Lavalink не занимается взломом YouTube — это делают плагины поверх него, и именно плагины сейчас обновляются быстрее всего, потому что за ними стоит активное сообщество, а не один разработчик.

Связка, которая на практике работает стабильно:

  • Lavalink v4 — сам аудио-сервер (последняя мажорная ветка, старые v3-конфиги и часть плагинов с ней несовместимы).
  • youtube-source (плагин от topi314) — заменяет встроенную в старый lavaplayer YouTube-экстракцию, которая официально признана нерабочей и удалена из ядра Lavalink начиная с v4. Плагин умеет несколько клиентских стратегий (WEB, ANDROID_MUSIC, TVHTML5EMBEDDED и т.д.) и поддерживает PoToken через отдельный генератор.
  • LavaSrc — добавляет резолвинг ссылок Spotify, Apple Music, Deezer и Yandex Music: сам трек с этих площадок не стримится (у них нет публичного стрим-API для ботов), но плагин находит по названию и исполнителю совпадение на YouTube/SoundCloud и играет оттуда. Это стоит понимать сразу — "плей по ссылке Spotify" не значит "стрим со Spotify".

Если делать бота с нуля и без Lavalink кажется избыточным, для небольших серверов подойдёт discord-player (npm install discord-player @discord-player/extractor) — обёртка на discord.js, которая тоже использует youtube-source под капотом через discord-player-youtubei, но не требует отдельного Java-процесса. Плюс — проще развернуть на одном VPS вместе с самим ботом. Минус — меньше гибкости при масштабировании на несколько серверов и отсутствие балансировки между нодами, которую даёт Lavalink.

Нужен игровой сервер?

MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.

Создать сервер

Установка Lavalink-сервера на VPS

Понадобится Java 17+ и отдельная директория под сервер. Если бот ещё не поднят вообще — начните с базовой установки Discord-бота на VPS, музыкальный функционал добавляется поверх уже живущего 24/7 процесса.

sudo apt update && sudo apt install -y openjdk-17-jre-headless
mkdir -p /opt/lavalink/plugins && cd /opt/lavalink
wget https://github.com/lavalink-devs/Lavalink/releases/latest/download/Lavalink.jar

Скачайте jar-файлы плагинов youtube-source и LavaSrc с их GitHub Releases в /opt/lavalink/plugins/, затем настройте application.yml:

server:
  port: 2333
lavalink:
  server:
    password: "сложный_пароль_сервера"
    sources:
      youtube: false   # встроенный источник отключаем — его больше нет в v4
      soundcloud: true
  plugins:
    - dependency: "dev.lavalink.youtube:youtube-plugin:1.11.4"
    - dependency: "com.github.topi314.lavasrc:lavasrc-plugin:4.4.0"

plugins:
  youtube:
    enabled: true
    clients: ["WEB", "ANDROID_MUSIC", "TVHTML5EMBEDDED"]
  lavasrc:
    providers:
      - "ytsearch:\"%ISRC%\""
      - "ytsearch:%QUERY%"
    spotify:
      clientId: "ваш_spotify_client_id"
      clientSecret: "ваш_spotify_client_secret"

Версии плагинов уточняйте на момент установки — обновляются часто, и старая версия youtube-source может снова упереться в свежую блокировку. Запуск:

java -jar Lavalink.jar

Для автозапуска — отдельный systemd-юнит lavalink.service с Restart=on-failure: на нагруженных инстансах после долгого аптайма у Lavalink случается течь памяти, и плановый перезапуск не помешает.

Бот на discord.js + lavalink-client: базовые команды

Сторона Discord-бота — обычный discord.js-проект, который просто отправляет команды на Lavalink через клиентскую библиотеку lavalink-client:

npm install discord.js lavalink-client dotenv
const { Client, GatewayIntentBits } = require('discord.js');
const { LavalinkManager } = require('lavalink-client');

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

client.lavalink = new LavalinkManager({
  nodes: [{
    authorization: process.env.LAVALINK_PASSWORD,
    host: '127.0.0.1',
    port: 2333,
    id: 'main',
  }],
  sendToShard: (guildId, payload) => client.guilds.cache.get(guildId)?.shard?.send(payload),
  client: { id: process.env.CLIENT_ID },
});

client.on('raw', (d) => client.lavalink.sendRawData(d));
client.once('ready', () => client.lavalink.init({ id: client.user.id }));

Команда /play:

async function play(interaction) {
  const query = interaction.options.getString('запрос');
  const voiceChannel = interaction.member.voice.channel;
  if (!voiceChannel) {
    return interaction.reply({ content: 'Зайдите в голосовой канал.', ephemeral: true });
  }

  const player = client.lavalink.createPlayer({
    guildId: interaction.guildId,
    voiceChannelId: voiceChannel.id,
    textChannelId: interaction.channelId,
    selfDeaf: true,
  });
  await player.connect();

  const res = await player.search({ query, source: 'ytsearch' }, interaction.user);
  if (!res.tracks.length) {
    return interaction.reply({ content: 'Ничего не найдено.', ephemeral: true });
  }

  await player.queue.add(res.tracks[0]);
  if (!player.playing) await player.play();

  await interaction.reply(`Добавлено в очередь: **${res.tracks[0].info.title}**`);
}

Остальные команды — /skip (player.skip()), /queue (список player.queue.tracks), /volume (player.setVolume(n), 0–150), /pause//resume, /stop (player.destroy()). Их логика тривиальна — сложный код уже внутри Lavalink, задача бота — дёргать нужные методы по слэш-командам. Подход к структуре команд и правам такой же, как в статье про Discord-бота для управления игровым сервером — регистрация через SlashCommandBuilder, ограничение по ролям там, где нужно (например, /stop не всем подряд на большом сервере).

Самостоятельный хостинг vs готовый сервис

Ниша "музыка в Discord" плотно занята готовыми ботами (Jockie Music, FredBoat в его нынешнем виде, десятки менее известных SaaS). Вопрос "писать своё или подключить готовое" зависит от того, что вам реально нужно:

Свой бот на LavalinkГотовый SaaS-бот
НастройкаЧас-два на первый запуск, дальше свободная кастомизацияПять минут, добавил через инвайт-ссылку
Лимиты очереди/трековНет — сами решаетеЧасто есть бесплатный лимит, платная подписка снимает
Уникальные команды под ваш серверЛегко добавить (плейлисты сообщества, интеграция с RCON-статусом сервера)Только то, что предусмотрел разработчик бота
Надёжность апдейтов при поломке YouTubeВаша ответственность — следить за релизами youtube-sourceОтветственность разработчика бота (но и зависимость от него)
СтоимостьVPS ~$5-10/мес (можно тот же, где крутится игровой сервер, если ресурсов хватает)Часто бесплатно с рекламой/лимитами, премиум $3-10/мес
Приватность и контроль данныхПолный — всё на вашей инфраструктуреДанные и логи на серверах стороннего сервиса

Практичный ориентир: для небольшого дружеского сервера готовый бот избавляет от возни. Для игрового комьюнити, где музыкальный бот — часть общей инфраструктуры (тот же VPS, что и игровой сервер плюс бот со статистикой), свой инстанс на Lavalink окупается независимостью от чужих даунтаймов и лимитов — особенно если структура голосовых каналов сервера уже продумана, как в статье про структуру каналов Discord-сообщества.

Права на воспроизведение музыки в голосовом канале

Это тот пункт, где стоит быть честным, а не делать вид, что вопроса не существует. Технически музыкальный бот, который тянет аудио с YouTube в обход официального API, работает не по условиям использования YouTube — там прямо запрещено извлекать поток за пределами их собственных приложений. На практике для приватных некоммерческих Discord-серверов это массово игнорируемая серая зона: миллионы ботов так работают годами, и претензии со стороны правообладателей на уровне отдельного небольшого сервера — редкость.

Риски скорее технические, чем юридические, и они реальны:

  • Ваш IP может получить троттлинг или временный бан от YouTube, если бот активно используется — это проявляется как раз в виде тех самых 403. Отдельный VPS с чистым IP под Lavalink снижает риск по сравнению с ботом, запущенным из дома на том же IP, с которого вы сами смотрите YouTube.
  • Аккаунт, если используется OAuth/cookie-авторизация (некоторые сборки youtube-source позволяют войти под YouTube-аккаунтом для более стабильного доступа) — рискует получить ограничение самого аккаунта, а не только IP. Заводите под это отдельный аккаунт, не привязанный к личному.
  • Spotify/Apple Music/Deezer официально не дают транслировать чужой трек третьим лицам — поэтому LavaSrc и подобные плагины ищут совпадение на YouTube, а не стримят напрямую с этих сервисов. Ссылка на Spotify — просто удобный способ найти трек по метаданным, не более.
  • Если сервер публичный, крупный и потенциально коммерческий (донаты, реклама, монетизация) — риски выше, и стоит рассматривать честные альтернативы: официальные Spotify/YouTube Music виджеты со ссылкой вместо стрима внутри канала, либо лицензированные библиотеки роялти-фри музыки для фонового звука.

Универсального "безопасного на 100%" решения тут нет — это компромисс, который выбирает администратор сервера сам, оценивая масштаб и риски. Технический совет один: не размещайте музыкального бота на том же аккаунте/IP, который вы бережёте для чего-то важного.

Нужен игровой сервер?

MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.

Создать сервер

Частые вопросы

Можно ли обойтись без Lavalink и просто скачивать треки через yt-dlp перед проигрыванием?

Технически да, но это медленнее (нужно сначала докачать файл целиком или в буфер) и требует держать yt-dlp актуальным вручную — та же проблема с поломками, что и у старых библиотек, только без готовых плагинов-фиксов сообщества Lavalink.

Почему бот подключается к голосовому каналу, но звука нет?

Чаще всего не хватает ffmpeg в системе (для Lavalink не нужен — он сам транскодирует, но нужен для discord-player) либо не установлен пакет @discordjs/opus или opusscript на стороне Node.js-бота.

Ошибка This video is unavailable для трека, который отлично играет в браузере.

Обычно возрастное ограничение или региональная блокировка на стороне YouTube для клиента, который эмулирует youtube-source. Попробуйте другой clients в конфиге плагина (ANDROID_MUSIC часто обходит то, что блокирует WEB) — универсального клиента, который проходит везде, не существует.

Нужен ли отдельный VPS под Lavalink или можно на том же, где крутится игровой сервер?

Можно на том же — Lavalink не требователен к CPU (транскодирование аудио лёгкое), важнее свободная память под JVM (от 512 МБ) и то, что игровой сервер не упрётся в лимиты по сети из-за параллельного стриминга музыки на нагруженном комьюнити.

LavaSrc обязателен, если нужен только YouTube без Spotify-ссылок?

Нет, для чистого YouTube достаточно youtube-source. LavaSrc ставьте, только если реально нужны ссылки со Spotify/Apple Music/Deezer/Yandex Music как удобный ввод для пользователей.