- PVSM.RU - https://www.pvsm.ru -
Я играю в STALCRAFT, ныне STALZONE. Там есть радио Grind FM — играет фоном, создаёт атмосферу. Проблема в том, что это радио находится в безопасной зоне и играет даже не на всю эту зону. И мне захотелось сделать так, чтобы во время вылазки можно было включить это радио и мочить мутантов.
Немного поизучав, как это можно сделать без опыта в этом деле, я понял, что нужен просто сервер в облаке и программа с веб‑интерфейсом.
Сервер () в Яндекс.Облаке — 1 ядро, 2 ГБ памяти, 20 ГБ SSD.
Домен (по желанию, можно и по IP слушать).
Музыка в MP3.
Пара часов свободного времени.
Я зашёл в консоль Яндекс.Облака, нажал «Создать виртуальную машину» и выбрал:
|
Что |
Какое значение |
|---|---|
|
ОС |
Ubuntu 24.04 |
|
Ядра |
4 |
|
Память |
12 ГБ |
|
Диск |
150 ГБ SSD |
|
SSH‑ключ |
Сгенерировал одной кнопкой |
AzuraCast — это готовая панель для управления радио. Она поднимается через Docker.

Подключаюсь к серверу через 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.

Открываю браузер и ввожу http://51.250.51.60 (IP тачки).
Создаю админа: почта и пароль.
Дальше мастер создания станции. Прохожу по вкладкам:
Название: Grind FM
Жанр: Рок, пост‑панк, альтернатива
Часовой пояс: +3
Количество видимых песен: 5
Вещание по запросу: отключил

Включил: Icecast на этом сервере
Всё остальное оставил по умолчанию

Включил: LiquidSoap
Умный режим
AutoCue и ReplayGain: включил

HLS: отключил
Запросы песен: отключил
Стримеры: отключил
Самый сложный шаг — найти музыку, которая используется в игре. Полазил я по интернету и в стим‑комьюнити нашел ссылку на Яндекс Диск со всей музыкой!
В панели захожу в раздел Медиафайлы, нажимаю «Загрузить» и перетаскиваю папку с MP3.
AzuraCast сам разобрал теги — исполнитель, название, обложка.
В разделе Плейлисты создаю новый:
|
Поле |
Значение |
|---|---|
|
Название |
GrindFM |
|
Источник |
Базовые песни |
|
Тип |
Обычная ротация |
|
Порядок |
Перетасованный |

Сохраняю, потом выбираю треки из медиатеки и добавляю их в плейлист.
Захожу в раздел Вещание, нажимаю ПЕРЕЗАПУСТИТЬ ВЕЩАНИЕ.
Минута — и сервисы загорелись зелёным: Icecast работает, Liquidsoap работает.

В разделе Обзор вижу ссылку:
Вставляю её в — Яндекс браузер играет. Кидаю друзьям — они тоже слышат.
Публичная страница с плеером: http://51.250.51.60/public/grindfm_radio [2]
Чтобы страница не выглядела как стандартная заглушка, добавил кастомный 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 |
|
Публичная страница |
|
|
Музыка |
Играет, перемешивается, повторяет не чаще раза в 2 часа |
|
Диджей |
AutoDJ — автоматическая ротация |

Подключить домен и 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
Нажмите здесь для печати.