2016-10-21 9 views
0

Я пытаюсь извлечь метаданные icecast из потоков. У меня есть код, который работает для некоторых потоков, а не для других. Проблема в том, что некоторые потоки не возвращают значение icymetaint, и именно здесь код теряется.Не удается извлечь метаданные из некоторых потоков icecast

Я не могу получить заголовок icymetaint из этого потока: http://radio.hbr1.com:19800/tronic.ogg

Но когда я положил его в VLC Media Player он показывает мета просто отлично. Так что же я здесь не хватает? Какие существуют другие способы для потока icecast для передачи метаданных? Версия потока Icecast 2.3.3

Это код внутри класса для извлечения метаданных и заголовков:

public function GetDataFromStream($parsedUrl) 
{ 
    $returnData = array(); 
    $addr = $parsedUrl['host']; 

    $addr = gethostbyname($addr); 

    $sock = fsockopen($addr, $parsedUrl['port'], $errno, $errstr, 5); 
    $path = isset($parsedUrl['path'])?$parsedUrl['path']:'/'; 

    if ($sock) 
    { 
     $request = 'GET '. $path .' HTTP/1.0' . CRLF . 
      'Host: ' . $parsedUrl['host'] . CRLF . 
      'Connection: Close' . CRLF . 
      'User-Agent: ' . $this->useragent . CRLF . 
      'Accept: */*' . CRLF . 
      'icy-metadata: 1'.CRLF. 
      'icy-prebuffer: 65536'.CRLF. 
      (isset($parsedUrl['user']) ? 'Authorization: Basic ' . 
      base64_encode($parsedUrl['user'] . ':' . $parsedUrl['pass']) . CRLF : ''). 
      'X-TipOfTheDay: Winamp "Classic" rulez all of them.' . CRLF . CRLF; 

     if (fwrite($sock, $request)) 
     { 
      $theaders = $line = ''; 

      while (!feof($sock)) 
      { 
       $line = fgets($sock, 4096); 

       if('' == trim($line)) 
        break; 
       $theaders .= $line; 
      } 

      $theaders = explode(CRLF, $theaders); 

      foreach ($theaders as $header) 
      { 
       $t = explode(':', $header); 


       if (isset($t[0]) && trim($t[0]) != '') 
       { 
        $name = preg_replace('/[^a-z][^a-z0-9]*/i','', strtolower(trim($t[0]))); 
        array_shift($t); 
        $value = trim(implode(':', $t)); 

        if ($value != '') 
        { 
         if (is_numeric($value)) 
          $this->headers[$name] = (int)$value; 
         else 
          $this->headers[$name] = $value; 
        } 
       } 
      } 

      if (isset($this->headers['icymetaint'])) 
      { 
       $metainterval = $this->headers['icymetaint']; 
       $intervals = 0; 
       $metadata = ''; 

       while(1) 
       { 
        $data = ''; 

        while(!feof($sock)) 
        { 
         $data .= fgetc($sock); 

         if (strlen($data) >= $metainterval) 
          break; 
        } 

        $len = join(unpack('c', fgetc($sock))) * 16; 

        if ($len > 0) 
        { 
         $metadata = str_replace("\0", '', fread($sock, $len)); 
         break; 
        } 
        else 
        { 
         $intervals++; 
         if ($intervals > 100) break; 
        } 
       } 

       $metarr = explode(';', $metadata); 

       foreach ($metarr as $meta) 
       { 
        $t = explode('=', $meta); 

        if (isset($t[0]) && trim($t[0]) != '') 
        { 
         $name = preg_replace('/[^a-z][^a-z0-9]*/i','', strtolower(trim($t[0]))); 

         array_shift($t); 

         $value = trim(implode('=', $t)); 

         if (substr($value, 0, 1) == '"' || substr($value, 0, 1) == "'") 
          $value = substr($value, 1); 

         if (substr($value, -1) == '"' || substr($value, -1) == "'") 
          $value = substr($value, 0, -1); 

         if ($value != '') 
         { 
          $tmp = &$this->metadata; 
          $tmp[$name] = $value; 
         } 
        } 
       } 
       $this->valid = true; 
      } 
      else 
      { 
       $this->valid = false; 
      } 

      fclose($sock); 
     } 
     else 
      echo 'unable to write.'; 
    } 
    else 
     //echo 'no socket '.$errno.' - '.$errstr.'.'; 
     ; 

} 

ответ

2

Вы можете использовать .xspf расширение MOUNTPOINT, получить XML и разобрать его:

<?php 
$stream_url = "http://radio.hbr1.com:19800/tronic.ogg"; 
$xspf_url = $stream_url . ".xspf"; 
$xml = file_get_contents($xspf_url); 
if($xml){ 
    $data = simplexml_load_string($xml); 
    // Track artist 
    print $data->trackList->track->creator; 
    // Track title 
    print $data->trackList->track->title; 
} 
?> 

Вот как .xspf данных выглядит (я использую lynx, чтобы прочитать содержимое URL):

$ lynx -mime_header http://radio.hbr1.com:19800/tronic.ogg.xspf 
HTTP/1.0 200 OK 
Content-Type: application/xspf+xml 
Content-Length: 615 

<?xml version="1.0" encoding="UTF-8"?> 
<playlist xmlns="http://xspf.org/ns/0/" version="1"> 
    <title/> 
    <creator/> 
    <trackList> 
    <track> 
     <location>http://radio.hbr1.com:19800/tronic.ogg</location> 
     <creator>Res Q</creator> 
     <title>Fakesleep (2012)</title> 
     <annotation>Stream Title: HBR1 - Tronic Lounge 
Stream Description: Music on Futurenet 
Content Type:application/ogg 
Bitrate: Quality 0,00 
Current Listeners: 28 
Peak Listeners: 45 
Stream Genre: Tech House, Progressive House, Electro, Minimal</annotation> 
     <info>http://www.hbr1.com</info> 
    </track> 
    </trackList> 
</playlist> 

As вы можете видеть /playlist/trackList/track/title XML-узел - это название вашей песни, /playlist/trackList/track/creator обычно является художником.

+0

Я проверил .xspf и перечисляет количество слушателей, пик слушателей, качество. Это не самое важное для меня, это название песни. Я что-то упускаю? –

+0

'.xspf' есть все, что вам нужно, я обновил свой ответ. –

+0

Теперь я понял, что потоки, поддерживающие json версии 2.4 и выше, являются теми, которые не возвращают заголовок в файле .xspf. Другие делают. Большое спасибо. Помечено как правильный ответ. –

0

Это потому, что вы только пытаетесь разобрать Braindead Slipstreaming древних метаданных, введенный в Nullsoft Shoutcast ,

Правильные потоки используют контейнер (например, Ogg или WebM) вместо того, чтобы выбрасывать исходные данные.

Новые серверы Icecast предлагают API JSON (версия 2.4.1 и выше). Это более полезно, чем вытягивание всего потока только для метаданных.

Если вы все равно декодируете поток, тогда вам нужно заглянуть в соответствующие библиотеки для синтаксического анализа потоков, libogg, libopus, libvorbis.

+0

Спасибо за ваш ответ. Проблема в том, что я не могу контролировать, какая версия будет потоком, поэтому мне нужно будет разобрать их все. Я пробовал объединить Ogg и WebM, libogg, libopus, libvorbis с ключевым словом php, но я не нашел ничего полезного в разборе стерамов с php. –