Разработки
April 19

Трансляция потока музыки в сеть Интернет и на видеохостинги. Часть 2: Liquidsoap и Icecast2

Ранее, в статье https://teletype.in/@slakwik/WT_5jy3Ug6 описывал настройку стрима через Icecast+EZStream. Но со временем решил чуть «усложнить» стрим, разбавив стрим джинглами (аудиовставки с названием радиостанции) в случайном порядке и файлы для стрима брать просто из каталога (тоже, в случайном порядке).
Да и в целом, Liquidsoap работает стабильнее – не даром его используют на физических радиостанциях и эфирных студиях.

Пост будет продолжением\дополнением\обновлением предыдущего, только вместо EZStream мы настроим Liquidsoap, как источник аудиопотока.

Подготовка

Установите пакеты icecast2, liquidsoap и, если будете транслировать на видеохостинги, ffmpeg

У меня радиостанция работает на Raspberry Pi 3B, версии пакетов:

icecast2:
  Installed: 2.4.4-4+b1
liquidsoap:
  Installed: 1:2.2.5-debian-bookworm-1
ffmpeg:
  Installed: 7:5.1.5-0+deb12u1  

Под разные операционные системы могут быть разные версии пакетов, но желательно подбирать посвежее. Так же обратите внимание, что Liquidsoap может менять синтаксис файлов стрима – указанное ниже подходит к указанной версии и выше.

Настраиваем Icecast2

### Файл конфигурации для Icecast2 /etc/icecast2/icecast.xml
"ПАРОЛЬСТРИМА" – паролья для подключения плеера ezstream
"ПАРОЛЬРЕЛЕЯ" – пароль для перенаправления потока (в моем случае не используется, но оставлен)
"ПАРОЛЬАДМИНА" – паролья от консоли администратора Icecast2

<icecast>
    <location>Saint-Petersburg, Russia</location>
    <admin>slakwik@ya.ru</admin>
    <limits>
        <clients>100</clients>
        <sources>3</sources>
        <queue-size>524288</queue-size>
        <client-timeout>30</client-timeout>
        <header-timeout>15</header-timeout>
        <source-timeout>10</source-timeout>
        <burst-on-connect>1</burst-on-connect>
        <burst-size>65535</burst-size>
    </limits>

    <authentication>
    <source-password>ПАРОЛЬСТРИМА</source-password>
    <relay-password>ПАРОЛЬРЕЛЕЯ</relay-password>
    <admin-user>admin</admin-user>
    <admin-password>ПАРОЛЬАДМИНА</admin-password>
    </authentication>

    <directory>
        <yp-url-timeout>15</yp-url-timeout>
        <yp-url>http://dir.xiph.org/cgi-bin/yp-cgi</yp-url>
    </directory>

    <hostname>station.spbchurch.ru</hostname>

    <listen-socket>
        <port>8000</port>
    </listen-socket>
    <http-headers>
        <header name="Access-Control-Allow-Origin" value="*" />
    </http-headers>

    <fileserve>1</fileserve>

    <paths>
        <basedir>/usr/share/icecast2</basedir>
        <logdir>/var/log/icecast2</logdir>
        <webroot>/usr/share/icecast2/web</webroot>
        <adminroot>/usr/share/icecast2/admin</adminroot>
        <alias source="/" destination="/status.xsl"/>
    </paths>

    <logging>
        <accesslog>access.log</accesslog>
        <errorlog>error.log</errorlog>
        <loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
        <logsize>10000</logsize> <!-- Max size of a logfile -->
    </logging>

    <mount>
        <mount-name>/radio.mp3</mount-name>
        <charset>UTF-8</charset>
    </mount>
    <mount>
        <mount-name>/broadcast.mp3</mount-name>
        <charset>UTF-8</charset>
    </mount>
    <security>
        <chroot>0</chroot>
    </security>
</icecast>

Настраиваем Liquidsoap

Изменяем файл конфигурации службы

### Файл конфигурации службы Liquidsoap /etc/systemd/system/liquidsoap.service

[Unit]
Description=Liquidsoap Streaming Service
After=network.target

[Service]
# Указываем путь к файлу стрима. Например, /opt/spbchurch.liq
ExecStart=/usr/bin/liquidsoap /opt/spbchurch.liq
#/opt/nsr.liq
#spbchurch.liq
Restart=always
RestartSec=5
User=liquidsoap
Group=liquidsoap

[Install]
WantedBy=multi-user.target

Настраиваем файл стрима Liquidsoap

### Файл конфигурации стрима /opt/spbchurch.liq

# новый синтаксис настроек
# устанавливаем уровень 3 - для отладки достаточно
settings.log.level.set(3)
# если нужно - включаем вывод отладочной информации
#settings.log.stdout.set(true)
# если нужно включаем телнет-сервер для управления стримом (см. документацию ;-)
# server.telnet()

# включаем журналирование событий
log.file := true
# указываем путь к файлу-журналу
log.file.path := "/var/log/liquidsoap/stream.log"
log.stdout := false

# плейлист с джинглами
# указываем каталог с мр3-файлами джинглов. например, '/media/mp3'
jingles = mksafe(playlist(id="jingles",mode="randomize",reload_mode="watch",'/media/jingles'))

# дополнительная рандомизация
# отслеживает, чтобы последние два часа песни в рандоме не повторялись
l = playlog()
def check(r)
  m = request.metadata(r)
  if l.last(m) < 17200. then
    log.info("Rejecting #{m['filename']} (played #{l.last(m)}s ago).")
    false
  else
    l.add(m)
    true
  end
end

# плейлист с треками стрима
# указываем каталог с мр3-файлами стрима. например, '/media/mp3'
s = playlist(check_next=check,mode="randomize",'/media/mp3')

# играем треки из каждого плейлиста, каждые 10 музыкальных треков - один джингл
radio = rotate(weights = [10, 1],[s,jingles])
radio = nrj(radio)
#radio = crossfade(radio)

out = output.icecast(%mp3,
  host = "127.0.0.1",
  port = 8000,
  password = "ПАРОЛЬСТРИМА",
  mount = "radio",
  fallible=true,
  radio
)

Обновляем службу, запускаем Icecast2 и Liquidsoap

# обновление служб
sudo systemctl daemon-reload
# перезапуск службы
sudo systemctl restart icecast2
sudo systemctl restart liquidsoap

Проверяем работу

# проверка состояния Liquidsoap
# запускается долго, если сервер не самый мощный
# у меня на raspberry pi 3b запускается минут 5
#
# запускаем команду и ждем ответа Liquidsoap
# пошел ли стрим или ошибки при запуске стрима
sudo tail -f /var/log/liquidsoap/stream.log

Открываем браузер, вводим адрес своего стрима. Например, http://10.0.1.13:8000/broadcast.mp3
И если всё настроено верно – должен пойти стрим

Настройка Ffmpeg для трансляции видеопотока с вашим стримом

### Скрипт для запуска потока на видеохостинг

#!/bin/bash

# видеофайл, который будет являться "лицом" стрима. например, рядом с скриптом лежит файл vkradio.mp4
VIDEO="vkradio.mp4"

# адрес стрима icecast2 с локальной точкой подключения. например, http://10.0.1.13:8000/broadcast.mp3
BROADCAST="http://10.0.1.13:8000/broadcast.mp3"

# параметры стрима
RESOLUTION="640x480"
BITRATE="1500k"
FRAMERATE="5"

# URL для подключения к видеохостингу, ниже пример для Youtube
URL="rtmp://a.rtmp.youtube.com/live2/xxxx-xxxx-xxxx-xxxx-xxxx"

# сам скрипт запуска трансляции
/usr/bin/ffmpeg  -re -stream_loop -1 -i "$VIDEO" -i "$BROADCAST" -c:a aac -s "$RESOLUTION" -ab 128k -b:v "$BITRATE" -threads 2 -crf 22 -preset fast -vcodec libx264 -pix_fmt yuv420p -maxrate 2048k -bufsize 2048k -framerate $FRAMERATE -g 2 -strict experimental -f flv "$URL"

Примерно так это всё работает у меня сейчас (апрель 2025) и размещено по адресу radio.spbchurch.ru

В следующей статье я опишу, как поднять вебсайт, создать веб-страницу с плеером стрима и создание простой страницы со списком текущих треков