Как я запустил свою онлайн‑радиостанцию GrindFM на AzuraCast и Яндекс.Облаке

—

от автора

Я играю в STALCRAFT, ныне STALZONE. Там есть радио Grind FM — играет фоном, создаёт атмосферу. Проблема в том, что это радио находится в безопасной зоне и играет даже не на всю эту зону. И мне захотелось сделать так, чтобы во время вылазки можно было включить это радио и мочить мутантов.

Немного поизучав, как это можно сделать без опыта в этом деле, я понял, что нужен просто сервер в облаке и программа с веб‑интерфейсом.

Что нужно

  1. Сервер (VPS) в Яндекс.Облаке — 1 ядро, 2 ГБ памяти, 20 ГБ SSD.

  2. Домен (по желанию, можно и по IP слушать).

  3. Музыка в MP3.

  4. Пара часов свободного времени.

Шаг 1. Создаём сервер

Я зашёл в консоль Яндекс.Облака, нажал «Создать виртуальную машину» и выбрал:

Что

Какое значение

ОС

Ubuntu 24.04

Ядра

4

Память

12 ГБ

Диск

150 ГБ SSD

SSH‑ключ

Сгенерировал одной кнопкой

Шаг 2. Устанавливаем AzuraCast

AzuraCast — это готовая панель для управления радио. Она поднимается через Docker.

Подключаюсь к серверу через Cloud Shell:

Ставлю Docker:

sudo apt updatesudo apt install curl -ycurl -fsSL https://get.docker.com -o get-docker.shsudo sh get-docker.shsudo usermod -aG docker $USER

Выхожу и захожу заново, чтобы группа docker применилась.

Качаю установщик AzuraCast:

curl -s https://raw.githubusercontent.com/AzuraCast/AzuraCast/main/docker.sh > docker.shchmod a+x docker.sh./docker.sh install

Дальше установщик задаёт вопросы отвечаем на них.

Поздравляю мы установили AzuraCast.

Шаг 3. Настройка в браузере

Открываю браузер и ввожу http://51.250.51.60 (IP тачки).

Создаю админа: почта и пароль.

Дальше мастер создания станции. Прохожу по вкладкам:

Профиль

  • Название: Grind FM

  • Жанр: Рок, пост‑панк, альтернатива

  • Часовой пояс: +3

  • Количество видимых песен: 5

  • Вещание по запросу: отключил

Вещание

  • Включил: Icecast на этом сервере

  • Всё остальное оставил по умолчанию

АвтоДиджей

  • Включил: LiquidSoap

  • Умный режим

  • AutoCue и ReplayGain: включил

Остальное

  • HLS: отключил

  • Запросы песен: отключил

  • Стримеры: отключил

Шаг 4. Заливаю музыку

Самый сложный шаг — найти музыку, которая используется в игре. Полазил я по интернету и в стим‑комьюнити нашел ссылку на Яндекс Диск со всей музыкой!

В панели захожу в раздел Медиафайлы, нажимаю «Загрузить» и перетаскиваю папку с MP3.

AzuraCast сам разобрал теги — исполнитель, название, обложка.

Шаг 5. Создаю плейлист

В разделе Плейлисты создаю новый:

Поле

Значение

Название

GrindFM

Источник

Базовые песни

Тип

Обычная ротация

Порядок

Перетасованный

Сохраняю, потом выбираю треки из медиатеки и добавляю их в плейлист.

Шаг 6. Запускаю эфир

Захожу в раздел Вещание, нажимаю ПЕРЕЗАПУСТИТЬ ВЕЩАНИЕ.

Минута — и сервисы загорелись зелёным: Icecast работает, Liquidsoap работает.

Шаг 7. Ссылка для слушателей

В разделе Обзор вижу ссылку:

Вставляю её в — Яндекс браузер играет. Кидаю друзьям — они тоже слышат.

Публичная страница с плеером: http://51.250.51.60/public/grindfm_radio

Шаг 8. Стиль в духе STALCRAFT

Чтобы страница не выглядела как стандартная заглушка, добавил кастомный CSS:

  • Тёмный фон с радиальным градиентом

  • Оранжевое свечение

  • Полоса прокрутки в сталкерском стиле

  • Скрыл лишние кнопки

  • Добавил картинку на фон и на альбом

Всё это вставил в настройках брендинга в поле «Пользовательский CSS».

/* GrindFM — Сталкерский стиль */body {    background: #0f0c08;    background-image:         radial-gradient(ellipse at 50% 0%, #2a1f14 0%, #0f0c08 70%);    color: #c4b5a0;    font-family: 'Courier New', monospace;}.player-container {    background: rgba(20, 15, 10, 0.85);    border: 2px solid #5a3d2b;    border-radius: 12px;    box-shadow: 0 0 40px rgba(80, 40, 20, 0.3);    backdrop-filter: blur(10px);}.navbar, .header {    background: rgba(10, 8, 6, 0.9);    border-bottom: 1px solid #4a3020;    box-shadow: 0 2px 20px rgba(0, 0, 0, 0.8);}h1, h2, h3, .station-name {    color: #d4c5b0;    text-shadow: 0 0 20px rgba(180, 100, 50, 0.3);    letter-spacing: 3px;    text-transform: uppercase;}.station-name {    font-size: 2.5rem;    font-weight: bold;    color: #e8d5b8;    text-shadow:         0 0 30px rgba(200, 120, 60, 0.4),        0 0 60px rgba(150, 80, 30, 0.2);}.now-playing {    background: rgba(30, 22, 16, 0.7);    border-left: 4px solid #8B5A2B;    padding: 20px;    border-radius: 8px;}.song-title {    color: #e8d5b8;    font-weight: bold;    font-size: 1.4rem;    text-shadow: 0 0 15px rgba(200, 150, 80, 0.2);}.song-artist {    color: #a8957a;    font-style: italic;}.btn, .button {    background: #2a1f14;    border: 1px solid #6a4d35;    color: #d4c5b0;    padding: 10px 25px;    border-radius: 6px;    text-transform: uppercase;    letter-spacing: 2px;    transition: all 0.3s ease;}.btn:hover, .button:hover {    background: #4a3120;    border-color: #b8885a;    box-shadow: 0 0 30px rgba(180, 100, 50, 0.2);    color: #f0e0c8;}.offline-text {    color: #8a7a6a;    font-style: italic;    font-size: 1.2rem;    border-left: 3px solid #5a3d2b;    padding-left: 20px;    background: rgba(0, 0, 0, 0.3);    border-radius: 4px;}.schedule-item {    background: rgba(30, 22, 16, 0.5);    border-bottom: 1px solid #3a2a1e;    padding: 12px;}.schedule-item:hover {    background: rgba(50, 35, 25, 0.6);}/* Анимированный градиент для фона */@keyframes zoneGlow {    0% { opacity: 0.3; }    50% { opacity: 0.6; }    100% { opacity: 0.3; }}.glow-border {    border: 1px solid #6a4d35;    animation: zoneGlow 3s ease-in-out infinite;}/* Стиль для ссылок */a {    color: #b8885a;    text-decoration: none;    border-bottom: 1px dashed #4a3020;    transition: color 0.3s;}a:hover {    color: #d4a87a;    border-bottom-color: #b8885a;}/* Стиль для изображений-заглушек */.default-album-art {    filter: sepia(0.3) brightness(0.7) contrast(1.2);    border: 2px solid #4a3020;    border-radius: 8px;}/* Полоса прокрутки в стиле сталкер */::-webkit-scrollbar {    width: 10px;    background: #1a1410;}::-webkit-scrollbar-thumb {    background: #4a3525;    border-radius: 5px;}::-webkit-scrollbar-thumb:hover {    background: #6a4d35;}/* Кнопка play */.play-btn {    background: #3a2a1e;    border: 2px solid #6a4d35;    color: #e8d5b8;    width: 60px;    height: 60px;    border-radius: 50%;    font-size: 24px;    transition: all 0.3s;    box-shadow: 0 0 30px rgba(180, 100, 50, 0.2);}.play-btn:hover {    background: #5a3d2b;    border-color: #b8885a;    box-shadow: 0 0 50px rgba(200, 120, 60, 0.3);    transform: scale(1.05);}/* Дополнительный текст в стиле радио Зоны */.radio-frequency {    color: #6a5a4a;    font-size: 0.8rem;    letter-spacing: 6px;    text-transform: uppercase;    border-top: 1px solid #3a2a1e;    padding-top: 10px;}/* ============================================= *//* 🚫 СКРЫВАЕМ КНОПКУ "ПЛЕЙЛИСТ" (точный класс) *//* ============================================= */a.btn.btn-link.text-secondary[href*="playlist"] {    display: none !important;}

Пользовательский JS для публичных страниц:

// GrindFM — Сталкерский JSdocument.addEventListener('DOMContentLoaded', function() {    console.log('☢️ GrindFM — Радио Зоны запущено');    // Добавляем радио-частоту в заголовок    const header = document.querySelector('.station-name');    if (header) {        const freq = document.createElement('span');        freq.className = 'radio-frequency';        freq.textContent = '🔴 103.7 FM — Зона';        freq.style.cssText = `            display: block;            font-size: 0.8rem;            color: #6a5a4a;            letter-spacing: 6px;            text-transform: uppercase;            border-top: 1px solid #3a2a1e;            padding-top: 10px;            margin-top: 8px;        `;        header.appendChild(freq);    }    // Добавляем сталкерскую приписку к статусу "оффлайн"    const offlineText = document.querySelector('.offline-text, .station-offline');    if (offlineText) {        const stalkerMsg = document.createElement('div');        stalkerMsg.style.cssText = `            font-size: 0.9rem;            color: #8a7a6a;            margin-top: 10px;            border-left: 3px solid #5a3d2b;            padding-left: 20px;            font-style: italic;            background: rgba(0, 0, 0, 0.3);            border-radius: 4px;            padding: 12px;        `;        stalkerMsg.textContent = '☢️ "Тихо в эфире. Жди сигнала."';        offlineText.parentNode.insertBefore(stalkerMsg, offlineText.nextSibling);    }    // Меняем заголовок вкладки    document.title = '☢️ GrindFM — Радио Зоны';    // Добавляем иконку радио (если есть)    const favicon = document.querySelector('link[rel="icon"]');    if (favicon) {        // favicon уже есть — ничего не делаем    }    // Анимация мигания для активного статуса    const statusDot = document.querySelector('.status-dot, .live-indicator');    if (statusDot) {        setInterval(() => {            statusDot.style.opacity = Math.random() > 0.9 ? '0.3' : '1';        }, 2000);    }    // Консольная заставка    console.log('%c☢️ GRIND FM — РАДИО ЗОНЫ', 'font-size: 20px; color: #e8d5b8; background: #1a1410; padding: 10px 20px; border: 2px solid #6a4d35; border-radius: 6px;');    console.log('%c"Здесь не место для слабых духом."', 'color: #8a7a6a; font-style: italic; font-size: 14px;');    // Обработка ошибок плеера с сталкерскими сообщениями    const audio = document.querySelector('audio');    if (audio) {        audio.addEventListener('error', function(e) {            console.log('⚠️ Потеря сигнала. Внимание, аномалия!');        });        audio.addEventListener('playing', function() {            console.log('📡 Сигнал принят. Эфир активен.');        });        audio.addEventListener('waiting', function() {            console.log('⏳ Буферизация... Перезагрузка в зоне.');        });    }    console.log('✅ GrindFM — готов к работе!');});

Писал его deepseek так как я не шарю.

Что в итоге

Что получилось

Как выглядит

Радиостанция

Работает 24/7

Публичная страница

http://51.250.51.60/public/grindfm_radio

Музыка

Играет, перемешивается, повторяет не чаще раза в 2 часа

Диджей

AutoDJ — автоматическая ротация

Что можно сделать дальше

  • Подключить домен и HTTPS

  • Включить запросы песен от слушателей

  • Добавить диджеев как в игре чтобы что‑то говорили и шутили

  • Создать самому сайт для радио

Сколько это стоит?

В Яндекс.Облаке первое время идёт бесплатный грант, потом:

  • Сервер: ~1500–2000 ₽/мес Моя конфигурация вышла в 8800₽/мес

  • Трафик: 100 ГБ в месяц бесплатно, дальше — 1,53 ₽/ГБ

При 100 слушателях и 128 кбит/с укладываешься в бесплатный лимит.

Спасибо, что прочитали) Я очень люблю игру STALCRAFT, играю очень долго и много, надеюсь, меня не на ругают за название станции как в игре и так далее) И в друг, разработчики прочитают это, прошу вас сделать квест с получением наушников с плеером, чтобы всегда слушать любимые треки в игре)

ссылка на оригинал статьи https://habr.com/ru/articles/1071714/