- PVSM.RU - https://www.pvsm.ru -

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

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

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

Что нужно

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

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

  3. Музыка в MP3.

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

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

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

Что

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

ОС

Ubuntu 24.04

Ядра

4

Память

12 ГБ

Диск

150 ГБ SSD

SSH‑ключ

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

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

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

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

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

Ставлю Docker:

sudo apt update
sudo apt install curl -y
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

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

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

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

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

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

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

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

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

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

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

Профиль

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

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

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

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

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

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

Вещание

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

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

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

АвтоДиджей

  • Включил: LiquidSoap

  • Умный режим

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

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

Остальное

  • HLS: отключил

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

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

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

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

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

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

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

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

Поле

Значение

Название

GrindFM

Источник

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

Тип

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

Порядок

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

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

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

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

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

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

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

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

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

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

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

Шаг 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 — Сталкерский JS
document.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]

Музыка

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

Диджей

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

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

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

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

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

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

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

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

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

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

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

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

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

Автор: Ariro

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/ubuntu-2/456811

Ссылки в тексте:

[1] VPS: https://www.reg.ru/?rlink=reflink-717

[2] http://51.250.51.60/public/grindfm_radio: http://51.250.51.60/public/grindfm_radio

[3] Источник: https://habr.com/ru/articles/1071714/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1071714