Создание 24/7 радио-стрима в духе Lofi (шаблон скрипта Liquidsoap | гайд по установке на Linux VPS) – Mikulski
Наложение сайта

Создание 24/7 радио-стрима в духе Lofi (шаблон скрипта Liquidsoap | гайд по установке на Linux VPS)

Особая благодарность EvergreenDeer, автору канала Deer Radio, за подсказки <3

Что в этой статье?

Данный гайд содержит в себе, по сути, готовый скрипт на языке программирования Liquidsoap, который воспроизводит зацикленное видео/анимацию/изображение и плейлист с музыкой из папки (добавляя новые треки в папку, плейлист будет обновляться автоматически) , показывает метаданные треков на экране (Исполнитель – Название песни), ну и отправляет поток на Youtube (или любую другую площадку, поддерживающую стримы). Проще говоря, типичный шаблон Lofi-радио.
А также подробную пошаговую инструкцию по установке и настройке минимально необходимого для запуска на виртуальном приватном сервере на базе Linux (Ubuntu в конкретном случае). С тем учетом, чтобы даже новичок смог разобраться и повторить эту процедуру.
В общем, вся та информация, которой мне остро не хватало, когда я загорелся идеей создания собственного 24/7 музыкального стрима.
Не обойдется и без лирических отступлений, которые можно было бы и пропустить, но и без них тоже нельзя.
Для всех платных подписчиков Boosty я подготовил видео-версию полного хода установки (на случай, если кому-то текстового варианта недостаточно). Полчаса реального времени на установку и запуск. Также пост с видео можно открыть и без подписки – разовым платежом.

UPD: Появилось дополнение к  этому гайду: https://mikulski.rocks/ru/lofi-strim-24-7-guide-ch2/, с примерами того, как можно усовершенствовать свой радио-стрим.

Моя кулстори

Так или иначе данный гайд перекликается с моим предыдущим туториалом “Как я сделал свое Стрим-Радио 24/7” на основе скрипта Ffplayout. Материал, к сожалению, уже не столь актуален, т.к. разработчик перешел с языка Python на Rust, а потому изменился процесс установки и отдельные детали настройки. Тем не менее в том посте я описал чуть более развернуто о выборе VPS и о других моментах, чем будет в этом посте, а потому также рекомендую к ознакомлению.
Ffplayout заточен именно под непрерывное воспроизведение плейлиста с видеофайлами и он меня всецело устраивал. Но я всегда хотел научиться создавать стримы по типу Lofi 24/7: зацикленная гифка и музыка. Казалось бы, что может быть проще? И это просто, если есть средства арендовать сервер с графической оболочкой и установить там OBS, либо воспользоваться готовыми решениями “из-коробки” от Onbubble или permastream.io.
Про Liquidsoap и его широкие возможности я узнал достаточно скоро, но пугала необходимость разбираться в объемной документации и самому программировать код (опыта программирования у меня вообще нет). А потому я излазил Github вдоль и поперек в поиске готовых решений, но все найденное либо не запускалось из-под моих кривых рук, либо работало крайне нестабильно. В общем, я оставил эту затею почти на год, пока место на диске не забилось видео под завязку и не встал вопрос о переходе на более дорогую конфигурацию VPS: хостером не было предусмотрено наращивание отдельных компонентов. Я решил, что это хороший повод, чтобы вернуться к Liquidsoap, попытаться собрать минималистичный скрипт и сменить формат радио с показа видеороликов на воспроизведение треков. Как ни крути, стрим с видеороликами многих сбивал с толку, несмотря на то, что вся информация была и в названии стрима и в описании, а сами видео были смонтированы. Самая частая фраза в чате: “Это запись?”.
Как бы то ни было все оказалось не так уж сложно. Стоило просто набраться терпения и последовательно прочесть несколько первых глав The Liquidsoap book, а затем отдельные части этого руководства, чтобы собрать рабочий стрим, а впоследствии и модернизировать его разными “фишками”. Так что, если вдруг вы увлечетесь “радиостроением” или же захотите что-то надстроить в скрипте, которым я поделюсь, то эта книга – ваш верный помощник.

Ограничения и Что важно понимать?

  • Я никакой не программист и не сетевой администратор, а всего лишь энтузиаст. Поэтому, не исключено, что знающим специалистам некоторые моменты или формулировки могут показаться глупыми и нелепыми.
  • Версия Liquidsoap в данном гайде 2.1.2.
  • Операционная система VPS в данном гайде – Ubuntu 20.04 (на 22.04 установка на этапе opam install обрывается на слабой конфигурации).
  • Установка будет содержать только необходимый минимум библиотек для этого сетапа.
  • Устанавливать Liquidsoap желательно на чистую систему. Либо остановить ВСЕ возможные процессы на сервере (особенно, если VPS маломощный, как в данном случае). Компилятор Ocaml весьма прожорлив на ресурсы, поэтому велика вероятность, что он будет выдавать ошибку в процессе установки необходимых компонентов.
  • Алерты и виджеты (например, с DonationAlerts) добавить в сцену, по-легкому, не получится. Liquidsoap с такого рода веб-источниками, по умолчанию, не совместим. Возможно есть способ это сделать, но я пока не понимаю, как именно. Впрочем, если вы обращали внимание, то на 24/7 стримах, не то что виджеты, даже названия треков не всегда отображаются.
  • Конфигурация VPS, которая справляется со стримом в 720p (нагрузка процессора от 70 до 90%): 1 CPU 2400MHz и 1 GB RAM, Пресет видеокодека: Veryfast. 1080p, к сожалению не тянет, – даже при пресете Superfast нагрузка под 100% и лаги.
  • Место на диске, которое займет система и все устанавливаемые компоненты около 4.5гб.
  • Удостоверьтесь, что ваш хостер предоставляет веб-оболочку с файл-менеджером к файловой системе VPS. Это значительно упростит редактирование текста и загрузку файлов. Либо освойте подключение к VPS через FTP для этих целей.
  • Также, плюсом будет веб-оболочка для терминала/командной строки. Несмотря на то, что всю установку я буду объяснять через подключение из Windows Powershell (так удобнее и быстрее) – веб-оболочка упростит запуск/остановку скрипта в дальнейшем.
  • Как правило, в платных тарифах интернет-трафик безлимитный. Но на это тоже стоит обратить внимание и рассчитать трафик заранее, если его объем ограничен месячным лимитом: количество секунд в месяц x битрейт = наш трафик.
    Например, мы планируем, стримить в разрешении 720p с битрейтом 1500kbps (1,5 mbps):
    2592000 секунд в месяц Х 1,5mbps битрейта= 3888000mb, конвертируем эту величину в Терабайты (обычно трафик указывается в ТБ) через любой онлайн конвертер величин и получаем 0,48 ТБ в месяц. Следовательно, 1 ТБ трафика в месяц будет с лихвой хватать для трансляции в 720p.
  • На рынке большой выбор VPS. У меня нет опыта использования разных хостеров, поэтому посоветовать ничего не могу. Сам я, для удобства, выбрал того же провайдера – beget.com, который хостит мой сайт и где есть веб-оболочки для файл-менеджера и терминала, а также безлимитный трафик с широким каналом.

Установка Liquidsoap

VPS арендован, его IP-адрес и пароль root-пользователя получены – можно подключаться.
Для этого нужно открыть утилиту Windows Powershell и ввести команду:

ssh root@ip_адрес_вашего_сервера

Система запросит пароль и после его верного ввода (введенных символов или “*” на экране не будет видно – это нормально) состоится подключение.

Важно! В командной строке не работают привычные комбинации для копирования/вставки из буфера. CTRL+C - останавливает текущий запущенный процесс! В Powershell копировать/вставить осуществляется "Правым кликом" мыши!
Клавишей "Вверх" можно вызвать последние вводимые команды - чтобы не печатать их каждый раз заново.

Первым делом нужно создать нового пользователя и задать пароль:

sudo adduser ВАШ_НИК

Теперь важно наделить этого пользователя необходимыми правами:

sudo usermod -aG sudo ВАШ_НИК

Осталось зайти под этим пользователем:

su ВАШ_НИК

В дальнейшем, к серверу следует подключаться этим пользователем, т.к. все установленные компоненты будут закреплены за этой учеткой (а еще Liquidsoap не особо любит запуск от имени root):

 ssh ВАШ_НИК@ip_адрес_вашего_сервера

Прежде всего следует установить библиотеку, которая понадобится для отображения метаданных трека:

sudo apt-get install libfreetype6-dev

Для корректной установки Liquidsoap и его зависимостей нужен OPAM (Ocaml Package Manager) не ниже версии 2.0:

sudo apt-get install opam

Затем

opam init

Когда установка завершится, надо ввести команду, чтобы синхронизировать OCaml с текущим окружением (это нужно делать каждый раз, когда в логе вы увидите сообщение “run eval $(opam env)”):

eval $(opam env)

А также OCaml версии не ниже 4.12.0. Предлагаю установить 4.14.0, взяв пример из инструкции https://cs3110.github.io/textbook/chapters/preface/install.html:

opam switch create cs3110-2022fa ocaml-base-compiler.4.14.0

Это займет какое-то время, наберитесь терпения и не пугайтесь, если покажется, что система зависла.
И снова

eval $(opam env)

Теперь можно переходить к непосредственно самой установке Liquidsoap. Сперва нужно сделать “запрос”, который скачает все недостающие компоненты для запрашиваемых библиотек:

opam depext gd ffmpeg liquidsoap

А потом установить:

opam install gd ffmpeg liquidsoap

Где: gd – плагин, который понадобится для отображения текста, ffmpeg – кодировщик аудио/видео потоков, liquidsoap – это Liquidsoap с набором стандартных библиотек.

UPD: Команды opam depext/install liquidsoap установят последнюю версию Liquidsoap!
На сегодня (июль 2023) вышла новая версия Liquidsoap 2.2.0, в которую был внесен ряд изменений и которая, возможно, будет потреблять больше ресурсов CPU.
Поэтому, рекомендую установить версию 2.1.4 (последняя в ветке 2.1.x и с требованием к версии Ocaml не ниже 4.13.0).
Полная команда в таком случае будет выглядеть так:
opam depext gd ffmpeg liquidsoap.2.1.4
opam install gd ffmpeg liquidsoap.2.1.4

И в последний раз на сегодня:

eval $(opam env)

Готово! Чтобы удостовериться, что все прошло гладко можно проверить версию Liquidsoap и список установленных библиотек:

liquidsoap --version
opam list

Скрипт

Первым делом надо создать папки, где будут находится скрипт, фоновая анимация и музыка. Это желательно все сделать из консоли от имени созданного пользователя, чтобы избежать конфликтов ролей и прав в системе (LInux достаточно щепетилен в этом отношении):

cd
mkdir /home/ВАШ_НИК/radio
mkdir /home/ВАШ_НИК/radio/music

Теперь можно текстовым редактором nano создать файл (этой же командой его можно будет открыть снова):

nano /home/ВАШ_НИК/radio/stream.liq

Скопируйте и вставьте содержимое из этого шаблона:

#разрешение запуска от root / permission to run the script from the root user
settings.init.allow_root.set(true)

#функции для метаданных / metadata functions
song_author = ref('')
def apply_song(m) =
song_author := m["artist"]
end

song_title = ref('')
def apply_song2(m) =
song_title := m["title"]
end

def get_track_name_text()
"$(artist) - $(title)" % [ 
("artist", !song_author),    
("title", !song_title)
]
end 

# источник аудио / audio source
audio = playlist(reload_mode="watch", "/home/ВАШ_НИК/radio/music")
audio = mksafe(audio)

#источник видео / video source
background = single("/home/ВАШ_НИК/radio/background.gif")

#вызов метаданных / calling metadata
audio.on_track(apply_song) 
audio.on_track(apply_song2) 

#отрисовка текста / drawtext
background = video.add_text(color=0xFFFFFF, font="/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", speed=0, x=50, y=50, size=26,
get_track_name_text,
background)

# смешивание / mixing sources
radio = mux_video(video=background, audio)

#rtmp+codec
url = "rtmp://localhost/live"
enc = %ffmpeg(format="flv",
%video(codec="libx264", width=1280, height=720, pixel_format="yuv420p",
b="750k", maxrate="750k", minrate="750k", bufsize="1500k", profile="Main", preset="veryfast", framerate=30, g=60),
%audio(codec="aac", samplerate=44100, b="128k"))

#вывод / output
output.url(fallible=true, url=url, enc, radio)
UPD: если вы все-таки установили версию 2.2.0, то в ней немного изменился синтаксис (вместо '!x', следует писать 'x()') и блок с метаданными будет выглядеть так:
def get_track_name_text()
"$(artist) - $(title)" % [ 
("artist", song_author()),    
("title", song_title())
]
end 

Чтобы сохранить изменения в nano, надо нажать F3 и подтвердить изменения.
F2, чтобы выйти из редактора.

Давайте разбираться и редактировать:

  • Символ # перед строкой обозначает, что эта строка “закомментирована” и не влияет на код.
  • settings.init.allow_root.set(true) – на всякий случай (если вдруг вы поленились создавать нового пользователя), разрешается запускать скрипт root-пользователем. Технически, можно удалить ее.
  • Блок “Функции метаданных” лучше не трогать – эти функции собирают информацию о треках из тегов mp3-файлов.
  • Источник аудио.
    * audio – имя переменной; playlist – режим воспроизведения файлов из папки (рандом включен по умолчанию); reload_mode = “watch” – значит, что плейлист обновится, как только в папку попадет новый файл; путь к папке – “/путь/к/папке”. <- не забудьте отредактировать директорию!
    * audio = mksafe(audio) – делаем источник “безопасным”. То есть если что-то случится с папкой с музыкой, то скрипт не сломается, а переключится на воспроизведение тишины.
    • Источник видео
      * background – имя переменной; single – режим воспроизведения единичного файла и путь к нему. По умолчанию зациклен. Можно указать gif-анимацию, jpg/png – изображения, mp4 – видео. <- не забудьте отредактировать директорию!
    • В блоке “Вызов метаданных “, – скрипт обращается к функциям из блока “функции метаданных”, чтобы собрать “Исполнитель – Песня” для текущего воспроизводимого трека.
    • Блок “Отрисовка текста”. Здесь указывается какой текст (get_track_name_text) и поверх какого источника (background) нужно отрисовать текст. А также атрибуты этого текста:
      *color=0xFFFFFF – цвет текста, в этом примере задан белый. Подходят коды html-разметки: код нужно подставить после “0x”. Например, желтый цвет с этого сайта будет выглядеть так: color=0xFCB900.
      *font=”/путь/к/шрифту” – указывается шрифт для отрисовки. В данном примере используется стандартный в Linux путь и шрифт. Для удобства, я рекомендую закидывать шрифты в ту же папку, где находится и сам скрипт.
      *speed=0 – означает, что текст статичен. Если поменять значение, то текста будет плыть по экрану.
      *x=50, y= 50 – координаты, где будет располагаться текст. x=0, y=0 – это левый верхний угол. Важно заметить, что в Liquidsoap не предусмотрены готовые инструменты для выравнивания текста (во всяком случае, я не смог разобраться или придумать математическую формулу для этого). Т.к. шаблон опирается на Lofi – радиостанции, то в данном примере текст размещается в левом верхнем углу с небольшим отступом от краев.
      *size= – размер шрифта.
    • “Смешивание”. Или правильнее, “Мультиплексор”. Грубо говоря объединяем видео и аудио в единый источник.
    • Блок “rtmp+codec”. Здесь определяется на какой адрес отправлять поток и указываются настройки для кодировщика.
      * url = “rtmp://a.rtmp.youtube.com/live2/ключ_трансляции” – здесь прописываются rtmp адрес и ключ трансляции, которые выдает площадка для стриминга. Если вы хотите рестримить сразу на несколько площадок или просто улучшить стабильность потока, то рекомендую дополнительно установить и настроить Nginx-сервер с Rtmp-модулем. Не так давно я опубликовал подробный гайд и на эту тему.
      *enc = – настройки кодировщика. Здесь начинается область творчества, экспериментов и личных предпочтений. Графы codec (как для видео, так и для аудио) и pixel_format, я рекомендую не трогать, если вы не знаете как этим пользоваться.
      *width=, height= – желаемое разрешение в пикселях (1920 x 1080 / 1280 x 720 и так далее).
      *b= – битрейт. Чтобы установить постоянный битрейт (CBR), что часто рекомендуется стрим-сервисами, то надо продублировать значение b в maxrate и minrate. Размер буфера bufsize – обычно устанавливается просто в два раза больше битрейта.
      *Дальше стандартные значения profile=”Main” и preset=”veryfast”.
      *framerate=, g= – количество кадров в секунду и количество ключевых кадров. Здесь я могу сильно ошибаться. Но, насколько я понял, то g (GOP-size) – надо указывать вдвое больше framerate (кадров в секунду) и тогда получится, что ключевые кадры будут вставляться каждые 2 секунды.
      Подбор битрейта, очевидно, большая тема для дискуссий. Я же для себя решил опираться на битрейт и фреймрейт исходного видео для фона, посмотрев их в свойствах файла и установив близкие значения в кодере. В любом случае, чем ниже битрейт, тем лучше транслируемость, что для радио основополагающий фактор.
      *Для аудио-кодека ставим параметры частоты дискретизации – samplerate=44100 (классика) и битрейт b= – тут по вкусу. Но явно не больше 320k. А так, насколько могу судить, то радиостанции редко устанавливают битрейт выше 128k.
    • Последняя строчка кода берет информацию из кодировщика, берет смешанный источник и отправляет его в эфир по указанному адресу.

С этим разобрались. Осталось загрузить треки в папку с музыкой через файл-менеджер или FTP и приступать к запуску.

Запуск

Чтобы запустить скрипт, надо перейти в папку, где он хранится:

cd /home/ВАШ_НИК/radio

И ввести команду:

liquidsoap имя_скрипта.liq

Или же если всецело следовать этому гайду, то:

liquidsoap stream.liq

По экрану побегут строчки и если что-то не так, то он сразу прекратит свою работу: надо лезть в скрипт и смотреть, может быть, где-то допущена ошибка (не закрыта скобка, пропущена запятая и так далее).
Если же все хорошо, то стрим запустится и можно лицезреть воочию результат своих стараний.

Но, если закрыть Powershell, то скрипт прекратит свою работу и стрим упадет.
Если у хостера есть веб-оболочка для терминала, то надо его открыть и залогиниться от имени созданного пользователя.
И повторить процедуру запуска: перейти в папку со скриптом и запустить его. Браузер можно закрыть – скрипт продолжить работать.
Если потребуется что-то изменить в скрипте, то после внесения правок, надо открыть этот веб-терминал (вы увидите что процесс идет), остановить процесс (CTRL+C), нажать клавишу “Вверх”, чтобы вызвать последнюю команду (это был запуск скрипта) и снова активировать Liquidsoap.

Если же веб-оболочки терминала нет, или вам просто хочется всем управлять из Powershell, то запускаться следует командой со следующими атрибутами для активации работы в фоновом режиме:

nohup liquidsoap stream.liq &

После чего можно смело закрывать окно Powershell. При повторном подключении к серверу, бегущих строчек в логе вы не увидите. Поэтому, чтобы остановить скрипт, надо “убить” фоновый процесс:

killall liquidsoap

UPD: Появилось дополнение к  этому гайду: https://mikulski.rocks/ru/lofi-strim-24-7-guide-ch2/, с примерами того, как можно усовершенствовать свой радио-стрим.
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии