Музыка в торговом зале (Интернет-радиостанция на Linux)




Пре-амбула

Необходимо как-то сделать аудио-вещание в торговом зале магазина, желательно чтобы музыка играла вперемешку с рекламой, минимум усилий на составление списков проигрывания. Но чтобы не приедалась однообразием. 

Амбула

Установка/настройка


Сначала устанавливаем Ubuntu-сервер (я ставил 16.04 LTS). 
Настройки практически по умолчанию, из дополнительных действий -- указание часового пояса и установка OpenSSH-сервер (чтобы подключаться потом через ssh). 

Прописываем в DNS А-запись для сервера -- чтобы в дальнейшем при настройке сервиса интернет-радиостанции использовать имя сервера а не его ip-адрес.

Так же устанавливаем пакеты для работы с ALSA -- аудио-подсистема в linux : 
sudo apt install alsa-base
sudo apt install alsa-utils
sudo apt install alsa-tools

Запускаем alsamixer, выставляем уровень звука на максимум (регулировка уровня звука в торговом зале ложится на усилитель): 



NB! Необходимо обновить программу silan ("Silan is a standalone application to analyze audio files for silence and print ranges of detected signals"). В ubuntu 16.04 установлен silan версии 0.3.2: 
user@audio:~$ silan --version
silan version 0.3.2
Эта версия программы неправильно обрабатывает аудио-файлы и AirTime обрезает некоторые аудио-файлы до одной минуты.
Обновляем silan: 
# wget -qO- http://download.opensuse.org/repositories/home:/hairmare:/silan/Debian_7.0/Release.key | apt-key add -
# echo 'deb http://download.opensuse.org/repositories/home:/hairmare:/silan/xUbuntu_16.04 ./' > /etc/apt/sources.list.d/hairmare_silan.list
# apt-get install silan -y --allow-unauthenticated

Теперь можно приступать к установки сервиса интернет-аудио-вещания LibreTime. 

Вариант А (предпочтительный): 
git clone https://github.com/libretime/libretime.git
cd libretime/
sudo ./install
Вариант Б (с наскока не рабочий): 
Качаем пакет LibreTime
wget https://github.com/LibreTime/libretime-debian-packaging/releases/download/debian%2F3.0.0_alpha.6-2/libretime_3.0.0.alpha.6-2_amd64.deb
устанавливаем пакеты IceCast и только что скаченный LibreTime:
sudo apt  install icecast2 /home/user/libretime_3.0.0.alpha.6-2_amd64.deb
Во время установки IceCast попросит настройку -- необходимо согласится, однако все параметры оставить по умолчанию.

После этого, кроме указанных пакетов, будет установлен и настроен Apache2.
Проверим, какие сайты он обслуживает:

sudo a2query -s

Видим, что кроме нужного сайта AirTime (клоном которого является LibreTime) есть еще default-сайт. Отключаем его :

sudo a2dissite 000-default

Апач предлагает перезагрузить его сервис, перезагружаем:

sudo service apache2 reload

Заходим на веб-страницу настройки libreTime (например, http://192.168.1.106/), и пробегаем по мастеру установок:

тут ничего не менял


тут тоже далее

тут вместо IP-адреса ресурса указал его имя (можно fqdn -- потом будет удобно переносить станцию в другую сеть)

опять по-умолчанию

готово



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

sudo service airtime-playout start
sudo service airtime-liquidsoap start
sudo service airtime_analyzer start
sudo service airtime-celery start

необходимо запустить конфигуратор заново - можно просто удалить файл /etc/airtime/airtime.conf .

Важно после установки сервиса добавить ему права доступа к аудио-подсистеме сервера (чтобы сервис мог проигрывать аудиопток не только "в сеть", но и через аудиовыход сервера, к которому подключен усилитель магазина)

 sudo usermod -a -G audio www-data

Зайдем на страницу проверки работоспособности (в моем случае, http://nsk-audio-01/?config):

Если все нормально , то можно открывать веб-интерфейс LibreTime/AirTime  (например, http://nsk-audio-01) , регистрироваться в системе (логин/пароль по-умолчанию: admin/admin), и настраивать работу "станции".

Сначала настроить трансляцию аудио-потока на локальную звуковую карту (ради этого все и затевалось -- чтобы с этой карты через усилитель аудио-поток пошел в торговый зал):




Использование

Подготавливаем  mp3-файлы к загрузке на сервер.
Подготовка в моем случае свелась к расстановки mp3-тэгов внутри аудио-файлов через программу mp3tag. Можно тэги расставить непосредственно в LibreTime , но это придется делать вручную для каждого аудио-файла, а через mp3tag можно один набор тэгов распространить на все аудио-файлы в папке. Я заполнял тэги "Год" (в каком году стали использовать данный аудио-файл), "Жанр" ("Реклама" для рекламы или "Магазин" для музыки в торговом зале), "Альбом" (для рекламы: "FullYear" для круглогодичной рекламы или "<МЕСЯЦ>" для сезонной ). Далее по этим тэгам настроим smart-блоки.
Регламент именования тэгов должны разработать маркетологи 

Загружаем подготовленные аудио-файлы на сервер :


Дожидаемся пока сервер обработает загруженные файлы (в правой панели на последнем скриншоте отображаются файлы со статусом импорта "Pending import" - ожидающие импорта. Можно так же их отфильтровать через радио-кнопку "Ожидание").

Когда импорт закончен можно настроить смарт-блоки:

Сначала смарт-блок для рекламы :

указываем:
  1. имя блока: реклама в мае
  2. критерии отбора: Жанр=реклама И Год=2019 И (Альбом=FullYear ИЛИ Альбом=МАЙ)
  3. ограничение звучание смарт-блока: 3 минуты
  4. тип блока: динамический
  5. Разрешить повторение треков: да 
  6. Разрешить последнему треку превысить лимит по времени (не обрывать звучание?): да
  7. Сортировка треков: случайная
Сохраняем смарт-блок.

Подобным образом настраиваем смарт-блок для музыки в торговом зале: 


Создаем новый плей-лист:

и отправляем в него нужные смарт-блоки:


После этого заполняем календарь передач:

Указываем имя передачи в календаре, время и дату начала и окончания передачи (начало/окончание работы магазина), требуется ли повтор передачи в другие дни календаря (да!), тип повтора (недельный), ...

... когда конкретно повторять передачу (у нас с понедельника по воскресенье) или повторять, бесконечно (чекбокс в данный момент не установлен - передача запланирована только на май), какой плейлист автоматически загружать и проигрывать ("Плей-лист Май"), заполнять ли все эфирное время передачи этим плей-листом (да)

в конце нажать "Добавить эту программу".

Все настроено.

По достижении назначенного в календаре времени запустится трансляция указанного в передаче плей-листа (во время трансляции надпись "В эфире" станет красной):


этот аудио-поток можно услышать как напрямую подключившись к аудиовыходу на сервере (туда подключается усилитель магазина), так и удаленно через интернет (нажать на кнопку "слушать").

PS

На одном из первых серверов, который настраивался не совсем по этой инструкции, неожиданно появилась проблема: при попытке загрузить на сайт новые аудио-ролики на странице airtime появлялась ошибка: An error occurred while processing your upload. Please try again in a few minutes.
В логе /var/log/airtime/zendphp.log в это время регистрировались сообщения:

2019-08-08T20:16:09+07:00 ERR (3): 192.168.10.50 [ErrorController.php:26 - errorAction()] - ACCESS_REFUSED - Login was refused using authentication mechanism AMQPLAIN. For details see the broker logfile.
2019-08-08T20:16:09+07:00 ERR (3): 192.168.10.50 [ErrorController.php:54 - errorAction()] - An internal application error has occurred.: PhpAmqpLib\Exception\AMQPProtocolConnectionException: ACCESS_REFUSED - Login was refused using authentication mechanism AMQPLAIN. For details see the broker logfile. in /usr/share/airtime/php/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Connection/AbstractConnection.php:661
2019-08-08T20:17:54+07:00 ERR (3): 192.168.10.50 [MediaController.php:161 - postAction()] - ACCESS_REFUSED - Login was refused using authentication mechanism AMQPLAIN. For details see the broker logfile.
2019-08-08T20:47:52+07:00 ERR (3): 192.168.10.50 [ErrorController.php:26 - errorAction()] - ACCESS_REFUSED - Login was refused using authentication mechanism AMQPLAIN. For details see the broker logfile.
2019-08-08T20:47:52+07:00 ERR (3): 192.168.10.50 [ErrorController.php:54 - errorAction()] - Произошла внутренняя ошибка.: PhpAmqpLib\Exception\AMQPProtocolConnectionException: ACCESS_REFUSE  - Login was refused using authentication mechanism AMQPLAIN. For details see the broker logfile. in /usr/share/airtime/php/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Connection/AbstractConnection.php:661
2019-08-08T20:48:39+07:00 ERR (3): 192.168.10.50 [ErrorController.php:26 - errorAction()] - ACCESS_REFUSED - Login was refused using authentication mechanism AMQPLAIN. For details see the broker logfile.
2019-08-08T20:48:39+07:00 ERR (3): 192.168.10.50 [ErrorController.php:54 - errorAction()] - Произошла внутренняя ошибка.: PhpAmqpLib\Exception\AMQPProtocolConnectionException: ACCESS_REFUSE  - Login was refused using authentication mechanism AMQPLAIN. For details see the broker logfile. in /usr/share/airtime/php/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Connection/AbstractConnection.php:661
Поиск решения в google привел меня к следующему: 
  1. проблема возникла в службе очереди RabbitMQ, в его логе (/var/log/rabbitmq/rabbit@audio-01.log) были сообщения о ошибках в учетных данных airtime:

    =INFO REPORT==== 8-Aug-2019::21:53:03 ===
    accepting AMQP connection <0.2640.0> (127.0.0.1:40136 -> 127.0.0.1:5672)

    =ERROR REPORT==== 8-Aug-2019::21:53:06 ===
    closing AMQP connection <0.2640.0> (127.0.0.1:40136 -> 127.0.0.1:5672):
    {handshake_error,starting,0,
                     {amqp_error,access_refused,
                                 "PLAIN login refused: user 'airtime' - invalid credentials",
                                 'connection.start_ok'}}

    =INFO REPORT==== 8-Aug-2019::21:53:07 ===
    accepting AMQP connection <0.2644.0> (127.0.0.1:40142 -> 127.0.0.1:5672)

    =ERROR REPORT==== 8-Aug-2019::21:53:10 ===
    closing AMQP connection <0.2644.0> (127.0.0.1:40142 -> 127.0.0.1:5672
      {handshake_error,starting,0,
                     {amqp_error,access_refused,
                                 "AMQPLAIN login refused: user 'airtime' - invalid credentials",
                                 'connection.start_ok'}}
  2. заглянув в настройки airtime (/etc/airtime/airtime.conf), я обнаружил что airtime пытается подключиться к RabbitMQ под учетной записью airtime/airtime к vhost /airtime:

    [rabbitmq]
    host = 127.0.0.1
    port = 5672
    user = airtime
    password = airtime
    vhost = /airtime
  3. проверил список пользователей, которые зарегистрированы в RabbitMQ, и не нашел ни такого пользователя ни такого vhost (!!!):

    user@audio-01:~$ sudo rabbitmqctl list_users
    [sudo] пароль для user:
    Listing users ...
    guest   [administrator]

    user@audio-01:~$ sudo rabbitmqctl list_vhosts
    Listing vhosts ...
    /
  4. создал пользователя airtime с паролем (и добавил ему тэг administrator - по аналогии с guest):

    user@audio-01:~$ sudo rabbitmqctl add_user airtime airtime
    Creating user "airtime" ...

    user@audio-01:~$ sudo rabbitmqctl set_user_tags airtime administrator
    Setting tags for user "airtime" to [administrator] ...
  5. Добавил vhost /airtime:

    user@audio-01:~$ sudo rabbitmqctl add_vhost /airtime
    Creating vhost "/airtime" ...
  6. Проверил кто какие права имеет в RabbitMQ, не увидел в списке ни пользователя ни vhost:

    user@audio-01:~$ sudo rabbitmqctl list_permissions
    Listing permissions in vhost "/" ...
    guest   .*      .*      .*
  7. Добавил пользователю airtime права на vhost:

    user@audio-01:~$ sudo rabbitmqctl set_permissions -p /airtime airtime ".*" ".*" ".*"
    Setting permissions for user "airtime" in vhost "/airtime" ...
  8. Перезапустил RabbitMQ:

    user@audio-01:~$ sudo rabbitmqctl stop_app
    Stopping node 'rabbit@audio-01' ...

    user@audio-01:~$ sudo rabbitmqctl start_app
    Starting node 'rabbit@audio-01' ...
     
  9. Аудио-ролики через веб-интерфейс стали грузиться нормально, в журнале /var/log/rabbitmq/rabbit@audio-01.log ошибки пропали:

    =INFO REPORT==== 8-Aug-2019::22:23:03 ===
    Setting permissions for 'airtime' in '/airtime' to '.*', '.*', '.*'

    =INFO REPORT==== 8-Aug-2019::22:23:04 ===
    accepting AMQP connection <0.2375.0> (127.0.0.1:57210 -> 127.0.0.1:5672)

    =INFO REPORT==== 8-Aug-2019::22:23:06 ===
    accepting AMQP connection <0.2392.0> (127.0.0.1:57214 -> 127.0.0.1:5672)

Комментарии