Веб-радіо в Linux: встановлення сервера Icecast та базове налаштування ротації з Ezstream

Давно планував і нарешті вирішив таки створити власну "лампову" радіо-станцію для локальної мережі Yggdrasil. Інформації про налаштування Icecast в мережі повно, але для мене знайдена інфа виглядала заплутаною: я не розумів, чому окремо розглядається Icecast, Ices, Ezstream та додатковий скриптинг, у той час як мені для початку було потрібно просто зробити тривіальну річ: мотати по колу плейлист музичних файлів.

В темі стрімінгу та аудіо-обробки - я нуб. З цієї причини вирішив написати невеличкий гайд для Debian/Linux, зрозумілий для себе "в минулому" а також практичну нотатку, на випадок якщо завалю сервер та доведеться пригадувати що робив. Згодом, планую також навчитись додавати ретрансляцію етерів новин за розкладом, можливо - пускати в ефір живі стріми, тоді й розширю цей матеріал до серії.

Icecast

Icecast (https://icecast.org) - це класичний сервер, на базі якого створюється публічний сервіс для слухачів (клієнтів). Його можна порівняти з проксі сервером Nginx для Веб-сайтів, от тільки створений він спеціально для операцій з потоковими даними. Цей сервер ніяк не взаємодіє з медіа-колекціями напряму, він просто отримує на себе сирий потік аудіо (або інших) даних з бекенду (по API) та розподіляє його на активні підключення, виступаючи в ролі хабу, своєрідної "радіо-вежі".

Встановлення

apt install icecast2

Налаштування

Після встановлення пакету з репозиторію, до системи буде автоматично додано сервіс systemd (/etc/init.d/icecast2) та стандартний файл конфігурації (/etc/icecast2/icecast.xml). Зайдемо до останнього та адаптуємо його під свої потреби:

nano /etc/icecast2/icecast.xml

    
    Earth
    icemaster@localhost
    
        100
        
        2
        524288
        30
        15
        10
        1
        65535
    

    
        
        PASSWORD

        
        PASSWORD

        
        admin
        PASSWORD
    

    
    ua

    
    
       UTF-8
    

    
    
        8000
        ::
    

    
    
        
1 /usr/share/icecast2 /var/log/icecast2 /usr/share/icecast2/web /usr/share/icecast2/admin access.log error.log 3 10000 0

Фаєрвол

У прикладі вище, використовується IPv6 маска хостів "::" (у вас це може бути IPv4 типу "0.0.0.0") для доступу без Веб-проксі. Тому відкриваємо й відповідний порт:

ufw allow 8000/tcp

Якщо ви плануєте проксуватись через 80/443 порти Nginx (у вас там має бути вже відкритим 80/tcp / 433/tcp відповідно), або у вас локальний хост на кшталт "::1" чи "127.0.0.1" (стандартно) тоді відкривати не потрібно.

Веб-проксі через Nginx

Хоча сам не користуюсь такою комбінацією, але додам нотатку з налаштування проксі для віртуального хосту Nginx, на прикладі конфігурації бекенд-сервера "127.0.0.1:8000"

server {
     # розкоментуйте, якщо використовуєте IPv4
     # listen IPv4:80

     listen [IPv6]:80;

     server_name IPv4 IPv6 DOMAIN_1 DOMAIN_2;

     location / {
          proxy_pass http://127.0.0.1:8000;

          # розкоментуйте значення якщо делегуєте журналювання серверу icecast
          # proxy_set_header X-Real-IP $remote_addr;
          # proxy_set_header X-Forwarded-Proto $scheme;
     }
}

SSL/TLS

В принципі, можна використовувати модні "захищені" з'єднання, але для стрімінгу я бачу його використання не доречним з точки зору енергозаощадження і здорового глузду в плані шифрування потоків з публічними даними. Дивіться самі, особисто я по причині вище завжди прослуховую радіо-станції по HTTP, якщо така опція надається сервером.

Ezstream

Коли "станцію" Icecast налаштовано, нам потрібно надіслати їй дані для трансляції. Такі дані можуть бути голосовими / потоковими або зберігатись у бінарних файлах. Оскільки мені потрібен останній варіант, з ним є одна не очевидна на перший погляд проблема: усі вони мають різні формати (`ogg`, `flac`, `mp3`, тощо) а також різні бітрейти та інші характеристики (в яких не торопаю). Оскільки вихідний стрім для слухача завжди має один формат, нам потрібно якимось чином відформатувати нашу колекцію до уніфікованого потоку: для цієї задачі й потрібен такий софт як Ezstream.

На відміну від популярної комбінації Icecast2 + Ices2 (https://icecast.org/ices/), Ezstream (https://icecast.org/ezstream/) відрізняється тим, що підтримує більше медіа-форматів з коробки та є простішим в налаштуванні (для поточних завдань)

Встановлення

apt install ezstream

Налаштування

Створімо окремого користувача з домашньою текою, де зберігатимуться налаштування та аудіо-файли:

useradd -m ezstream

Створення списку ротації

Насамперед, варто зауважити, що якщо це ротація великої колекції по колу, то медіа файли бажано звести до єдиного формату. Якщо цього не зробити то Ezstream буде конвертувати файли на льоту, що потребуватиме додаткових ресурсів CPU. На цьому етапі я не робив того, використовуючи колекцію що складається з mp3 і стрім мій буде в цьому ж форматі. Єдине що, я сумніваюся щодо різного бітрейту та інших аудіо-характеристик, це буде окремою темою про конвертацію наприклад з `ffmpeg`, але майте на увазі цей нюанс.

Для початку, завантажимо потрібні аудіофайли до умовної теки /home/ezstream/my-stream/collection. Якщо планується декілька тематичних стрімів, буде зручно заздалегідь створити для них простір імен у вигляді підтек, наприклад:

Після того, як до колекції додано медіа-файли, згенеруємо для них мета-індекс для ротації в Ezstream. На виході це буде звичайний текстовий список шляхів до файлів по одному на рядок:

find /home/ezstream/my-stream/collection -name *.mp3 > /home/ezstream/my-stream/playlist.txt

Оскільки операції вище я проводив від рута (без попереднього логіну з `su ezstream`) варто виправити права Unix, адже наш сервіс systemd пускатиметься саме від користувача ezstream:

chown ezstream:ezstream -R ~/ezstream

Конфігурація Ezstream

Коли дані ротації готові, можна перейти безпосередньо до налаштувань Ezstream.

Щоб не переварювати зайві опції, копіюємо мінімальний конфіг в домашню теку користувача `ezstream`:

cp /usr/share/doc/ezstream/examples/ezstream-minimal.xml /home/ezstream/my-stream/config.xml

Якщо вам потрібні додаткові опції, дивимось доступні пресети з коментарями:

ls /usr/share/doc/ezstream/examples/

Мій файл для конфігурації Icecast вище, містить деякі додаткові опції та зараз виглядає так:



  
    
      
      ::1

      
      PASSWORD
    
  
  
    
      
      NAME
      DESCRIPTION
      GENRE

      
      /my-stream.mp3

      
      mp3
    
  
  
    
      
      /home/ezstream/my-stream/playlist.txt

      
      No

      
      No
    
  

Зауважу, що на кожен потік (стрім) потрібен окремий файл конфігурації / systemd процес, не додавайте масив <stream> в <streams> - це так не працює і якщо ви додасте декілька, потік просто видаватиме один з потоків. Тобто для кожного стріму - має бути окремий файл конфігурації і окремий конфіг systemd для нього, тому вище ми і створили неймспейс "/home/ezstream/my-stream"

systemd

Останнє, що потрібно зробити - це створити сервіс systemd для налаштованого потоку Ezstream. Запускатиметься він від створеного вище користувача ezstream та вище створеної конфігурації "/home/ezstream/my-stream/config.xml"

nano /etc/systemd/system/ezstream-my-stream.service
[Unit]
After=network.target

[Service]
Type=simple

# актуальні користувач/група
User=ezstream
Group=ezstream

# я додав затримку, оскільки потік не зможе стартувати,
# якщо процес icecast того зробити не встиг (наприклад, при старті системи)
ExecStartPre=/bin/sleep 5s

# вказуємо коректний шлях до конфігурації
ExecStart=/usr/bin/ezstream -c /home/ezstream/my-stream/config.xml

# вказуємо актуальні шляхи до майбутніх журналів
StandardOutput=file:/home/ezstream/my-stream/mainstream-debug.log
StandardError=file:/home/ezstream/my-stream/mainstream-error.log

# можна розкоментувати, але тоді ви можете не помітити збій окрім як читаючи логи
# Restart=on-failure

[Install]
WantedBy=multi-user.target

Зберігаємось (Ctrl+X + Y) і виконуємо один раз в послідовності:

1. `systemctl enable ezstream-my-stream` - додаємо автозапуск стріма при старті системи

2. `systemctl start ezstream-my-stream` - стартуємо стрім

3. `systemctl status ezstream-my-stream` - перевіряємо статус

Ось власне і все, перезавантажувати процес Icecast не потрібно, конкретний потік Ezstream буде змонтовано та відмонтовано автоматично під час запуску / зупинки його процесу.

Тестування

Тепер можна в браузері перейти за адресою вашого сервера Icecast: на прикладі конфігурації вище, це http://[IP]:8000

Якщо у вас активні процеси Ezstream, вони мають відображатися в списку на головній сторінці. До кожного потоку, з права є кнопки експорту в форматах M3U і XSPF - якщо на них клікнути вони або скачаються або відкриються в плеєрі, що підтримує стрімінг. В себе на Fedora, я відкриваю .m3u як текстовий файл та виймаю з нього URL, після чого копіюю в розділ "Radio" програвача "Rhythmbox" :)

Посилання

Веб-версія цього матеріалу з коментарями на DevZone