Я пытаюсь извлечь ледяные метаданные из потоков.
У меня есть код, который работает для некоторых потоков, а не для других.
Проблема в том, что некоторые потоки не возвращают значение icymetaint, и именно здесь код теряется.
Я не могу получить заголовок icymetaint из этого потока:
http://radio.hbr1.com:19800/tronic.ogg
Но когда я помещаю его в медиаплеер VLC, он показывает мета просто отлично.
Так что же мне здесь не хватает? Какие еще способы существуют для потока ледового вещания для передачи метаданных? Потоковая версия 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.'.';
;
}
Ты можешь использовать .xspf
Расширение точки монтирования, получить 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>
Как вы видете /playlist/trackList/track/title
XML-узел — это название вашей песни, /playlist/trackList/track/creator
обычно художник.
Это потому, что вы только пытаетесь разобраться в том, как древние метаданные проскальзывали в мозгах, представленные Nullsoft в Shoutcast.
правильный потоки используют контейнер (например, Ogg или WebM) вместо того, чтобы выбрасывать необработанные данные.
Более новые серверы Icecast предлагают JSON API (версия 2.4.1 и выше). Это более полезно, чем извлечение целого потока только для метаданных.
Если вы все равно декодируете поток, то вам следует поискать подходящие библиотеки для разбора потоков, на ум приходят libogg, libopus, libvorbis.