Отдаём метаданные в удалённый icecast без использования кодировщиков.

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

  1. Есть какая-то программа автоматизации эфира, MegaMix, Sound Empire или аналогичная, которая как минимум умеет отдавать готовый поток в стереомикс, а метаданные складывать в текстовый файл.
  2. Есть какой-то encoder, который забирает со стереомикса или линейного входа звук и шлёт его на удалённый сервер, например edcast, или edcast reborn.
  3. Есть удалённый вещательный сервер с icecast, который является видимой точкой вещания для конечных пользователей.

И есть проблема — файл с метаданными, подсунутый в локальный edcast, никак не меняет метаданные в удалённом icecast. Грусть. Печаль. Боль…

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

Решая свою проблему я вдохновлялся этим. Если в двух словах — нужно сделать следующее:

  1. Установить на машину с файликом метаданных (и с вещательной программой видимо) php. У нас это был Windows и я установил php 5.6 с этой страницы. Устанавливал в c:\php. Никакой дополнительной настройки не потребовалось, разве что пришлось включить curl. Делается это достаточно просто:
    • Переименовываем php.ini-prodiction в php.ini
    • Раскоментируем строчку ;extension=php_curl.dll
    • Скачиваем тут файл сертификата и размещаем его к примеру в c:\php\cacert.pem, так же приводим в порядок строчку ;curl.cainfo =
    • Находим в c:\php библиотеки libeay32.dll и ssleay32.dll и копируем их в c:\windows\system32 (в качестве альтернативы можно обавить директорию php в path).
    • Перекладываем php_curl.dll из c:\php\ext в c:\php

  2. Непосредственно скрипт обновления метаданных у нас выглядел так:
    <?php
    /**
    * This program will check a file every 5 seconds to see if it has changed...if it has, the new metadata will be sent to the icecast server(s)
    */


    //the path to the file where your song information is placed...please see below notes for formatting of metadata
    DEFINE('songfile', "c:\metadata\data,txt");


    //simply copy and paste this code block for each server you need to add
    $serv["host"][] = "stream.vyshka24.ru"; //ip or hostname the server is running on
    $serv["port"][] = 80; //port the server is running on
    $serv["mount"][] = "/256"; //this format: /mount
    $serv["user"][] = "admin"; //icecast server username
    $serv["passwd"][] = "fixmenow"; //icecast server password

    while(1)
    {
        $t=time();
        clearstatcache();
        $mt=@filemtime(songfile);
        if ($mt===FALSE || $mt<1)
        {
            echo "file not found, will retry in 5 seconds";
            sleep(5);
            continue;
        }

        if ($mt==$lastmtime)
        {
            //file unchanged, will retry in 5 seconds
            sleep(5);
            continue;
        }
       
        $da="";
        $f=@fopen(songfile, "r");
        if ($f!=0)
        {
            $da=@fread($f, 4096);
            fclose($f);

            /**
            * Assuming that the file is in this format:
            *
            * Title: Superhero
            * Artist: Jane's Addiction
            * Time: N/A
            */

           
            //separate our file by lines
            $explode_da=explode("\n", $da);
           
            if(is_array($explode_da))
            {
                //remove "Title: "
                $title=preg_replace("/Title: /", '', $explode_da[0]);
               
                //remove "Artist: "
                $artist=preg_replace("/Artist: /", '', $explode_da[1]);
               
                //our metatdata to send to the server
                $final_metadata=urlencode(trim($artist.' - '.$title));
            }
            else
            {
                $final_metadata=urlencode("Parse Error - Please Check Your Output File");
            }
        }
        else
        {
            echo "error opening songfile, will retry in 5";
            sleep(5);
            continue;
        }
       
        $lastmtime=$mt;
       
        for($count=0; $count < count($serv["host"]); $count++)
        {
            $mysession = curl_init();
            curl_setopt($mysession, CURLOPT_URL, "http://".$serv["host"][$count].":".$serv["port"][$count]."/admin/metadata?mount=".$serv["mount"][$count]."&mode=updinfo&song=".$final_metadata);
            curl_setopt($mysession, CURLOPT_HEADER, false);
            curl_setopt($mysession, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($mysession, CURLOPT_POST, false);
            curl_setopt($mysession, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            curl_setopt($mysession, CURLOPT_USERPWD, $serv["user"][$count].":".$serv["passwd"][$count]);
            curl_setopt($mysession, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($mysession, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");
            curl_setopt($mysession, CURLOPT_CONNECTTIMEOUT, 2);
            curl_exec($mysession);
            curl_close($mysession);
        }
       
        echo "song updated";
       
        sleep(5);
    }
    ?>

    Т.е. данный код обновлял точку вещания /256 на хосте stream.vyshka24.ru на 80-ом порту с периодичностью в 5 секунд. Пароль естественно изменён 🙂 Точек вещания у нас три — 128 kbps, 192 kbps и 256 kbps, так что файлов было три. Запуск команды c:\php\php.exe -f c:\php\256.php (файлики лежат по путям c:\php\128.php, c:\php\192.php и c:\php\256.php) стартовал скрипт и всё работало хорошо, только вот три консольки всё время открытых напрягали оператора эфира.

  3. Дабы решить проблему, описанную в предыдущем пункте были сделаны три bat файла понятного содержания:
    • 128.batc:\php\php.exe -f c:\php\128.php
    • 192.batc:\php\php.exe -f c:\php\192.php
    • 256.batc:\php\php.exe -f c:\php\256.php

    Созданные bat файлы посредством утилиты nssm были обёрнуты в сервисы и стали стартовать при старте системы. Попытка реализовать то же самое посредством планировщика заданий с триггером «включение системы» успехом не увенчалась.

К описанному выше можно добавить лишь то, что php код добавляет «- » слева к метаданным, и удаляет некотрые регекспы (которых в нашем файле кстати не было), т.е. пользователь получит строку «- John Smith — The good song» даже если в файле была строка «Artist: John Smith Title: The good song».

Сразу хочу уточнить что icecast/edcast/php и пр. — не совсем моя тема и адаптированные мной решения не претендуют на изящность. Так же хочу сказать что думал над вариантом слать файл по ftp на вещательный сервер (там lamp) и разбирать там, но и на эфирной/сигнальной машине это оказалось сделать не сложно.

[UPD]
Как оказалось, данная проблема характерна только для ogg потока. Mp3 поток нормально отдаётся с метаданными средствами edcast.

Запись опубликована в рубрике Без рубрики, Программки с метками , . Добавьте в закладки постоянную ссылку.

3 комментария на «Отдаём метаданные в удалённый icecast без использования кодировщиков.»

  1. Андрей говорит:

    Привет!
    Есть проблема — не передаются метаданные для FLAC потока Icecast 2.4.4
    Подметил, что в версии Icecast KH-15 (https://github.com/karlheyes/icecast-kh/releases/tag/icecast-2.4.0-kh15) это возможно… но вот как — непонятно!
    Вот один из таких потоков http://besidefm.ga:8000/stream.m3u в нем отображается «Артист — Имя трека»
    Прошу связаться со мной, если есть возможность и время, спасибо!

Добавить комментарий для IdeaFix Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *