После того, как мы исправили метаданные, можно научить нашу радиостанцию сообщать о своём состоянии разным каталогам, например, TuneIn. В данной статье я расскажу как зарегистрироваться в каталоге TuneIn и, в качестве приятного бонуса, Liquidsoap Flows. После регистрации в каталоге мы научимся сообщать ему данные о своей станции для повышения её рейтинга в поиске.

Регистрация в TuneIn

Для начала нужно просто зарегистрировать свою радиостанцию в сервисе TuneIn, чтобы они хотя-бы знали о вас. Для этого идём в раздел для радиостанций, а именно — добавление новой станции. Аккуратно заполняем все поля. E-Mail желательно оставить рабочий, потому что туда будут приходить письма с подтверждением (и, честно говоря, спам, от которого легко отписаться). Не стоит обделять вниманием поле «Description», оно благоприятно влияет на положение радиостанции в поиске по ключевым словам. После ввода всех полей отправляем форму, подтверждаем E-Mail если необходимо, и ждём. В течение 48 часов радиостанция будет создана, и ей будет назначен специальный идентификатор, который потребуется нам далее.

Ключи оэлютс, или получение партнёрского доступа

Теперь нам нужно подать заявку на участие в партнёрской программе, по которой мы сможем сообщать TuneIn статистику воспроизводимых композиций. Она нужна каталогу чтобы выводить нашу станцию в результатах при поиске по названию исполнителя.

После регистрации в TuneIn станции будет присвоен идентификатор. Вытащить его можно прямо из ссылки на радиостанцию. Например, для Проводача ссылка выглядит так: http://tunein.com/radio/Provodach-s255847/ — вот это вот «s255847» и есть Station ID. Обращаю внимание, что буква s в начале обязательна!

Согласно требованиям TuneIn, нам следует отправить письмецо на адрес broadcaster-support@tunein.com, в котором нужно указать свой Station ID и ПО, которое будет использоваться для отправки статистики. Рекомендую писать по-английски. Я, например, просто сказал, что использую Liquidsoap и кастомное решение.

Текст моего письма:

Hello. I am the owner of Provodach station listed in TuneIn and I would like to use your AIR API.
My station ID is s255847
Our station uses Liquidsoap scripting system as streaming server so we’ll use custom script to make calls to your API (script will use cURL to do HTTP).
Please, provide us Partner ID and Partner Key and allow us to use the API.

Прошу знатоков простить за мой французский английский. В ответ мне пришли данные: Partner ID, Partner Key и Station ID (который мы итак знали). Теперь можно использовать API.

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

Согласно документации, использование TuneIn AIR API максимально просто — делаем GET-запрос к air.radiotime.com, указывая все требуемые параметры. Что-то вроде этого:

http://air.radiotime.com/Playing.ashx?partnerId=Ya3BAlV53h&partnerKey=Ve3Re13en4ever&id=s13371488&title=Artifacts&artist=Chainless

Здесь параметры говорят сами за себя, даже и пояснять, думаю, не стоит. Но теперь ведь нам нужно научить Liquidsoap делать такие запросы! Тут уже на помощь приходит команда system(), входящая в состав «жидкого мыла».

Береги шелл смолоду

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

def shell_escape (s) =
        s = string.escape(s) # стандартная функция
        s = string.replace(pattern='\?', fun(_)->"_", s) # чтобы не было лишних вопросов
        s
end

Замечательно. Поехали дальше.

Делаем запросы к API

TRIGGER WARNING! Здесь и далее я буду использовать код на PHP и вызывать его из командной строки. Особо впечатлительных разработчиков-илитариев прошу закрыть эту статью и отойти от экранов.

Для взаимодействия с AIR API, а так же удобного хранения настроек (ключей авторизации, например) я решил написать маленький скрипт на PHP, который посредством cURL делает запросы к AIR API. Этот скрипт мы будем вызывать из Liquidsoap при каждой смене трека.

<?php

define ('TI_PARTNER_ID', '<ваш partner id>');
define ('TI_PARTNER_KEY', '<ваш partner key>');
define ('TI_STATION_ID', '<ваш station id>');

// Этой функцией мы будем делать запросы к AIR API.
function curl_request ($type, $data = Array())
{
        $curl = curl_init();

        if($curl)
        {
                curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
                curl_setopt($curl, CURLOPT_URL, 'http://air.radiotime.com/Playing.ashx'.($type == 'get' ? '?'.http_build_query($data) : ''));
                curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($curl, CURLOPT_TIMEOUT, 5);
                curl_setopt($curl, CURLOPT_USERAGENT, 'Custom Air API Solution; liquidsoap/1.1.1; +https://provoda.ch');

                if ($type == 'post')
                {
                        curl_setopt($curl, CURLOPT_POST, true);
                        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
                }

                $out = curl_exec($curl);
                curl_close($curl);
                return (empty ($out)) ? false : $out;
        } else
                return false;
}


$options = getopt("", Array("title:", "artist:"));
$title = ''; $artist = '';
if (empty($options['artist']))
{
        $metadata = explode(' - ', $options['title']);
        if (count($metadata) < 2)
                die ("Bad --title parameter supplied!\n");

        $artist = $metadata[0]; $title = $metadata[1];
}
else
{
        $artist = $options['artist']; $title = $options['title'];
}

echo ("Sending song to TuneIn: Artist '$artist'; Title '$title'\n");
$req_res = curl_request('get', Array (
                        'partnerId' => TI_PARTNER_ID,
                        'partnerKey' => TI_PARTNER_KEY,
                        'id' => TI_STATION_ID,
                        'artist' => $artist,
                        'title' => $title
        )
);
echo ($req_res);
echo("\ndone.\n\n");

Использование скрипта крайне простое:

/usr/bin/php air.php --title "Artifacts" --artist "Chainless"

Если скрипту сообщить только title, в котором будет название композиции в стандартном виде (например, «Chainless — Artifacts»), он сам извлечёт нужные данные. Если данных не хватает, запрос к API выполнен не будет.

Теперь самое время вызвать этот скрипт из Liquidsoap! Изменим нашу функцию update_title, описанную ранее, и добавим туда взаимодействие с TuneIn:

def update_title(m) =
        title = m["title"]
        if title == "" or title == "Unknown" then
                content = m["filename"]
                content = basename (content)
                meta = string.extract(pattern='(.+)\s+-\s+(.+)\.[a-zA-Z0-9]{1,5}', content)
                sArtist = meta["1"]
                sTitle  = meta["2"]

                # Не забываем shell_escape, иначе худо будет!
                system ("/usr/bin/php /opt/scripts/php/air.php --title #{shell_escape(sTitle)} --artist #{shell_escape(sArtist)}")
                [("title", sTitle),
                 ("artist", sArtist)]
        else
                sArtist = string.recode(out_enc="UTF-8", m["artist"])
                sTitle = string.recode(out_enc="UTF-8", m["title"])

                # Не забываем shell_escape, иначе худо будет!
                system ("/usr/bin/php /opt/scripts/php/air.php --title #{shell_escape(sTitle)} --artist #{shell_escape(sArtist)}")
                [("title", sTitle),
                 ("artist", sArtist)]
        end
end

Готово! Теперь при каждой смене трека радиостанция оповестит об этом TuneIn, а он, в свою очередь, запомнит, что там у нас творилось, и поможет другим людям найти нашу станцию.

Потоки жидкого мыла

В качестве бонуса мы также можем зарегистрироваться в Liquidsoap Flows, месте, где собраны все радиостанции, использующие «жидкое мыло». Лишним не будет, да и API у них крайне простое:

# live - наш результирующий поток
live = register_flow(
  # Название радиостанции
  radio="Provoda.ch",

  # Сайт станции
  website="https://provoda.ch",

  # Краткое описание
  description="The most atmospheric and cozy radio station in the world.",

  # Жанр
  genre="experimental",

  # Пользователь. Однажды задав, можно ограничить доступ других, чтобы не плодили фейков.
  user="ya3baal",
  # Смотри выше
  password="pa5sw0rd",

  # Список потоков станции. Оформляется в виде ассоциативного массива.
  streams=[("mp3/128k","http://radio.nyan.pw/station/provodach"),
           ("mp3/64k","http://radio.nyan.pw/station/provodach-low")],
# Поток аудио 
live)

Вот и всё. Теперь мы ещё и потоками жидкого мыла обмазались.