Intereting Posts
Laravel: Как взять последние строки n (любое число) после упорядоченного в порядке возрастания? Как перейти на статическую папку в Laravel Задайте рейтинг по электронной почте Как удалить строку из текстового файла с помощью php, не выходя из пустой строки Получение года и недели года с даты PHP (), когда неделя охватывает два года Пользовательский конфигурационный файл для codeigniter Загрузка WordPress Post In Div с использованием другого шаблона Данные динамической таблицы вывода 3-уровневая развертка столбчатой ​​диаграммы в режиме highchart? Как создать страницу 404 на сервере WAMP Класс «PharData» не найден Ошибка при попытке отправить новый пароль на электронную почту php CakePHP HTML Helper: изображение в пределах ссылки ускользает? Codeigniter отправляет электронное письмо с прикрепленным файлом Передача JSON-кодированной переменной из PHP в Javascript через POST

Отслеживание информации из аудиопотока с помощью PHP

Можно ли извлекать информацию трека из аудиопотока с помощью PHP? Я сделал кое-что, и ближайшая функция, которую я могу найти, – stream_get_transports, но мой хост не поддерживает HTTP-перенос через fsockopen (), поэтому мне нужно будет немного поработать, чтобы узнать, что еще возвращает эта функция.

В настоящее время я пытаюсь вытащить метаданные исполнителя и трека из потока AOL.

    Это поток SHOUTcast, и да, это возможно. Это абсолютно не связано с тегами ID3. Я написал сценарий некоторое время назад, чтобы сделать это, но больше не могу его найти. Только на прошлой неделе я помог другому парню, у которого был достаточно полный сценарий, чтобы сделать то же самое, но я не могу просто опубликовать его источник, поскольку он не мой. Однако я свяжусь с ним, если вы напишите мне по электронной почте на brad@musatcha.com .

    Во всяком случае, вот как это сделать самому:

    Первое, что вам нужно сделать, – это напрямую подключиться к серверу. Не используйте HTTP. Ну, вы могли бы использовать cURL, но, скорее всего, это будет намного сложнее, чем его ценность. Вы подключаетесь к нему с помощью fsockopen() ( doc ). Обязательно используйте правильный порт. Также обратите внимание, что многие веб-хосты блокируют много портов, но обычно вы можете использовать порт 80. К счастью, все потоки SHOUTcast, поддерживаемые AOL, используют порт 80.

    Теперь сделайте свой запрос так же, как ваш клиент.

    GET /whatever HTTP/1.0

    Но перед отправкой <CrLf><CrLf> этот следующий заголовок!

    Icy-MetaData:1

    Это сообщает серверу, что вы хотите метаданные. Теперь отправьте пару <CrLf> .

    Хорошо, сервер ответит кучей заголовков, а затем начнет отправлять вам данные. В этих заголовках будет icy-metaint:8192 или аналогичный. Этот 8192 является метаинтервалом . Это важно и действительно единственное значение, которое вам нужно. Обычно это 8192, но не всегда, поэтому обязательно прочитайте это значение!

    В основном это означает, что вы получите 8192 байта данных MP3, а затем кусок мета, за которым следуют 8192 байта данных MP3, а затем кусок мета.

    Прочтите 8192 байта данных (убедитесь, что вы не включаете заголовок в этот счетчик), отбросьте их, а затем прочитайте следующий байт. Этот байт является первым байтом метаданных и указывает, сколько времени метаданные. Возьмите значение этого байта (фактический байт с помощью ord() ( doc )) и умножьте его на 16. Результатом будет количество байтов для чтения для метаданных. Прочитайте это количество байтов в строковой переменной, с которой вы будете работать.

    Затем обрезаем значение этой переменной. Зачем? Поскольку строка заполняется 0x0 в конце (чтобы она была равномерно распределена на кратное 16 байт), и trim() ( doc ) позаботится об этом для нас.

    У вас будет что-то вроде этого:

    StreamTitle='Awesome Trance Mix - DI.fm';StreamUrl=''

    Я дам вам выбрать свой метод выбора для разбора этого. Лично я бы, наверное, просто разделился с лимитом на 2 ; , но остерегайтесь заголовков, которые содержат ; , Я не уверен, каков метод escape-символа. Немного экспериментов должно помочь вам.

    Не забудьте отключиться от сервера, когда закончите с ним!

    Есть много ссылок SHOUTcast MetaData. Это хороший вариант: http://www.smackfu.com/stuff/programming/shoutcast.html

    Здесь вы можете найти готовый код, полезный для вашей проблемы: https://gist.github.com/fracasula/5781710

    Этот маленький gist предоставляет простую функцию PHP, которая позволяет извлекать метаданные MP3 (StreamTitle) из потокового URL.

    Обычно в заголовках ответов потоковый сервер помещает заголовок «ледяной метчик», который сообщает нам, как часто метаданные отправляются в потоке. Таким образом, функция проверяет заголовки ответов и, если присутствует «ледяная метка», параметр интервала будет заменен.

    В другом месте функция вызывает URL-адрес потоковой передачи, соответствующий вашему интервалу, и, если метаданных нет, функция повторит попытку через рекурсию, начиная с параметра смещения.

     <?php function getMp3StreamTitle($streamingUrl, $interval, $offset = 0, $headers = true) { $needle = 'StreamTitle='; $ua = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36'; $opts = [ 'http' => [ 'method' => 'GET', 'header' => 'Icy-MetaData: 1', 'user_agent' => $ua ] ]; if (($headers = get_headers($streamingUrl))) foreach ($headers as $h) if (strpos(strtolower($h), 'icy-metaint') !== false && ($interval = explode(':', $h)[1])) break; $context = stream_context_create($opts); if ($stream = fopen($streamingUrl, 'r', false, $context)) { $buffer = stream_get_contents($stream, $interval, $offset); fclose($stream); if (strpos($buffer, $needle) !== false) { $title = explode($needle, $buffer)[1]; return substr($title, 1, strpos($title, ';') - 2); } else return getMp3StreamTitle($streamingUrl, $interval, $offset + $interval, false); } else throw new Exception("Unable to open stream [{$streamingUrl}]"); } var_dump(getMp3StreamTitle('http://str30.creacast.com/r101_thema6', 19200)); 

    Надеюсь, это поможет!

    Большое спасибо за код fra_casula. Вот немного упрощенная версия, работающая на PHP <= 5.3 (оригинал ориентирован на 5.4). Он также повторно использует один и тот же ресурс соединения.

    Я удалил исключение из-за своих собственных потребностей, возвращая false, если ничего не найдено.

      private function getMp3StreamTitle($steam_url) { $result = false; $icy_metaint = -1; $needle = 'StreamTitle='; $ua = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36'; $opts = array( 'http' => array( 'method' => 'GET', 'header' => 'Icy-MetaData: 1', 'user_agent' => $ua ) ); $default = stream_context_set_default($opts); $stream = fopen($steam_url, 'r'); if($stream && ($meta_data = stream_get_meta_data($stream)) && isset($meta_data['wrapper_data'])){ foreach ($meta_data['wrapper_data'] as $header){ if (strpos(strtolower($header), 'icy-metaint') !== false){ $tmp = explode(":", $header); $icy_metaint = trim($tmp[1]); break; } } } if($icy_metaint != -1) { $buffer = stream_get_contents($stream, 300, $icy_metaint); if(strpos($buffer, $needle) !== false) { $title = explode($needle, $buffer); $title = trim($title[1]); $result = substr($title, 1, strpos($title, ';') - 2); } } if($stream) fclose($stream); return $result; } 

    Это код C # для получения метаданных с использованием HttpClient:

     public async Task<string> GetMetaDataFromIceCastStream(string url) { m_httpClient.DefaultRequestHeaders.Add("Icy-MetaData", "1"); var response = await m_httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); m_httpClient.DefaultRequestHeaders.Remove("Icy-MetaData"); if (response.IsSuccessStatusCode) { IEnumerable<string> headerValues; if (response.Headers.TryGetValues("icy-metaint", out headerValues)) { string metaIntString = headerValues.First(); if (!string.IsNullOrEmpty(metaIntString)) { int metadataInterval = int.Parse(metaIntString); byte[] buffer = new byte[metadataInterval]; using (var stream = await response.Content.ReadAsStreamAsync()) { int numBytesRead = 0; int numBytesToRead = metadataInterval; do { int n = stream.Read(buffer, numBytesRead, 10); numBytesRead += n; numBytesToRead -= n; } while (numBytesToRead > 0); int lengthOfMetaData = stream.ReadByte(); int metaBytesToRead = lengthOfMetaData * 16; byte[] metadataBytes = new byte[metaBytesToRead]; var bytesRead = await stream.ReadAsync(metadataBytes, 0, metaBytesToRead); var metaDataString = System.Text.Encoding.UTF8.GetString(metadataBytes); return metaDataString; } } } } return null; }