Трансляция потока музыки в сеть Интернет и на видеохостинги. Часть 3: Liquidsoap в контейнере
Настройка Liquidsoap в docker-контейнере
Настройка перед установкой
debian/ubuntu
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginalma linux/centos stream/redos
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Запускаем службу Docker
sudo systemctl start docker.service sudo systemctl enable docker.service
Структура файлов каталогов
/opt/radio # Основной каталог | script.liq # Скрипт работы Liquidsoap music/ # Монтируемый каталог с медиа | songs # Каталог с музыкой/подкастами | song1.mp3 song2.mp3 song3.mp3 jingles # Каталог с джинглами | file1.mp3 file2.mp3 file3.mp3
Создаем каталоги
sudo mkdir -p /opt/radio/liquidsoap
sudo mkdir -p /opt/radio/music/{songs,jingles}Редактируем файл /opt/radio/liquidsoap/docker-compose.yml
services: liquidsoap: image: pltnk/liquidsoap container_name: liquidsoap restart: always volumes: - /opt/radio/script.liq:/etc/liquidsoap/script.liq - /opt/radio/music:/music
Редактируем файл /opt/radio/script.liq
## Внизу файла замените:
## IP-АДРЕС-ХОСТА заменяем на внутренний ip-адрес хоста, где запущен сервис icecast2, куда мы будет транслировать аудиопоток
## ПАРОЛЬ-СТРИМА заменяем на пароль стрима, который мы указали в конфигурационном файле в icecast2
## ТОЧКА-МОНТИРОВАНИЯ заменяем на имя точки монтирования, которую мы указали в конфигурационном файле icecast2
# плейлист с джинглами
# указываем каталог с мр3-файлами джинглов. например, '/music/jingles'
jingles = mksafe(playlist(id="jingles",mode="randomize",reload_mode="watch",'/music/jingles'))
# дополнительная рандомизация
# отслеживает, чтобы последние два часа песни в рандоме не повторялись
l = playlog()
def check(r)
m = request.metadata(r)
if l.last(m) < 17200. then
false
else
l.add(m)
true
end
end
# плейлист с треками стрима
# указываем каталог с мр3-файлами стрима. например, '/music/songs'
s = playlist(check_next=check,mode="randomize",'/music/songs')
# играем треки из каждого плейлиста, каждые 10 музыкальных треков - один джингл
radio = rotate(weights = [10, 1],[s,jingles])
radio = nrj(radio)
out = output.icecast(%mp3,
host = "IP-АДРЕС-ХОСТА",
port = 8000,
password = "ПАРОЛЬ-СТРИМА",
mount = "ТОЧКА-МОНТИРОВАНИЯ",
fallible=true,
radio
)Размещаем медиа
В каталог /opt/radio/music/songs копируем все ваши mp3-файлы с музкальными композициями/подкастами
В каталог /opt/radio/music/jingles копируем все ваши джинглы
Запускаем liquidsoap
cd /opt/radio/liquidsoap docker compose up
Ожидаем запуск и наблюдаем за работой
Сначала пройдёт процедура скачивания базового образа, затем будут выполнены команды запуска контейнера
Затем появятся журналы работы liquidsoap. Например, такие:
Container liquidsoap Created
Attaching to liquidsoap
liquidsoap | 2025/04/23 21:11:03 >>> LOG START
liquidsoap | 2025/04/23 21:11:02 [main:3] Liquidsoap 2.0.3-1
liquidsoap | 2025/04/23 21:11:02 [main:3] Using: graphics=[distributed with Ocaml] bytes=[distributed with OCaml 4.02 or above] pcre=7.4.6 sedlex=3.3 menhirLib=20211128 dtools=0.4.5 duppy=0.9.2 cry=0.6.7 mm=0.7.4 ogg=0.7.4 ogg.decoder=0.7.4 vorbis=0.8.0 vorbis.decoder=0.8.0 mad=0.5.3 dynlink=[distributed with Ocaml] lame=0.3.7 samplerate=0.1.6 taglib=0.3.10 camomile=1.0.2
liquidsoap | 2025/04/23 21:11:02 [dynamic.loader:3] Could not find dynamic module for fdkaac encoder.
liquidsoap | 2025/04/23 21:11:02 [clock:3] Using builtin (low-precision) implementation for latency control
liquidsoap | 2025/04/23 21:11:03 [frame:3] Using 44100Hz audio, 25Hz video, 44100Hz main.
liquidsoap | 2025/04/23 21:11:03 [frame:3] Video frame size set to: 1280x720
liquidsoap | 2025/04/23 21:11:03 [frame:3] Frame size must be a multiple of 1764 ticks = 1764 audio samples = 1 video samples.
liquidsoap | 2025/04/23 21:11:03 [frame:3] Targeting 'frame.duration': 0.04s = 1764 audio samples = 1764 ticks.
liquidsoap | 2025/04/23 21:11:03 [frame:3] Frames last 0.04s = 1764 audio samples = 1 video samples = 1764 ticks.
liquidsoap | 2025/04/23 21:11:03 [sandbox:3] Sandboxing disabled
liquidsoap | 2025/04/23 21:11:03 [video.converter:3] Couldn't find preferred video converter: ffmpeg.
liquidsoap | 2025/04/23 21:11:03 [audio.converter:3] Using samplerate converter: libsamplerate.
liquidsoap | 2025/04/23 21:11:03 [test.mp3:3] Connecting mount test.mp3 for source@93.191.60.93...
liquidsoap | 2025/04/23 21:11:03 [test.mp3:3] Connection setup was successful.
liquidsoap | 2025/04/23 21:11:03 [clock.main:3] Streaming loop starts in auto-sync mode
liquidsoap | 2025/04/23 21:11:03 [clock.main:3] Delegating synchronisation to CPU clock
liquidsoap | 2025/04/23 21:11:03 [switch_2:3] Switch to switch_1.
liquidsoap | 2025/04/23 21:11:03 [switch_1:3] Switch to mksafe.
liquidsoap | 2025/04/23 21:11:03 [mksafe:3] Switch to safe_blank.
liquidsoap | 2025/04/23 21:11:03 [decoder.id3v2:2] Error while decoding file tags: Invalid_argument("String.sub / Bytes.sub")
liquidsoap | 2025/04/23 21:11:03 [jingles:3] Prepared "/music/jingles/Спасён_v1.mp3" (RID 1).
liquidsoap | 2025/04/23 21:11:03 [mksafe:3] Switch to jingles with transition.
liquidsoap | 2025/04/23 21:11:03 [songs:3] Prepared "/music/songs/Псалом 51 (на стихи Н.Басовского).mp3" (RID 0).
```В этот момент можно перейти на icecast2 точку подключения и послушать, появился ли стрим.
И если всё ОК, звук есть, то завершите работу контейнера, нажав комбинацию клавиш Ctrl+C и дождитесь завершения работы контейнера.
Далее настроим автоматический запуск и работу нашего liquidsoap
Настройка работы liquidsoap, как сервис
Редактируем файл сервиса /etc/systemd/system/liquidsoap.service
[Unit] Description=liquidsoap as a docker container After=docker.service Requires=docker.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/bash -c "docker compose -f /opt/radio/liquidsoap/docker-compose.yml up --detach" ExecStop=/bin/bash -c "docker compose -f /opt/radio/liquidsoap/docker-compose.yml stop" [Install] WantedBy=multi-user.target
Обновляем сервисы
sudo systemctl daemon-reload
Запускаем liquidsoap, как службу
sudo systemctl start liquidsoap
Переключаем службу в автозапуск
sudo systemctl enable liquidsoap
Заключение
Остаётся только дать ссылку на документацию к Liquidsoap https://www.liquidsoap.info/doc-2.3.2/
Надеюсь, что статьи помогут вам в работе ваших интернет-радиостанций.