SHOUTcast Metadaten abfangen

dasnov

Grünschnabel
Hallo,
ich wollte mal diese Dokumentation umsetzen um die Metadaten eines Shoutcast Streams abzufangen. Ja ich weiß das es zum auslesen der Metadaten eines Shoutcast Streams schon ein paar Klassen gibt, diese kann ich aber leider nicht benutzen da ich das für eine Art Stream-Proxy brauche.
Habe schonmal ein bisschen was angefangen aber leider komm ich nicht ganz klar mit dem Byte zahlen und komm somit nicht an das Length Byte
Naja Hier mal mein Quellcode, vielleicht könnt ihr mich ja ein bisschen unterstützen :)

PHP:
<?php
$stream_ip = "123.123.123.123";
$stream_port = 8000;

$metaint = 0;
$linelen = 128;

$fp = fsockopen($stream_ip, $stream_port);
if ($fp) {
    fputs($fp, "GET / HTTP/1.0\r\n");
//    fputs($fp, "User-Agent: WinampMPEG/5.0\r\n\r\n");
    fputs($fp, "Icy-MetaData:1\r\n\r\n");
    while(!feof($fp)) {
      $bla = fgets($fp,$linelen);
//      echo $bla;
      //if(stristr($bla, "streamtitle")) echo $bla;
      if(stristr($bla, "icy-metaint")) {
        preg_match("#icy-metaint:([0-9]+)#is",$bla,$tmp);
        //var_dump($tmp);
        //exit;
        $metaint = $tmp[1];
        $bytes = $metaint;
      }
      if($bytes<0) {
        $bytes = $metaint;
        echo $bla."\n";
      } elseif($bytes>0 && $bytes<=$metaint) {
//        echo strlen($bla)."\n";
        //echo "nich moep\n";
        $bytes = $bytes - strlen($bla);
      }

      //echo "BYTES[ ".$bytes." ]\n";

      //if($bytes>0 && $bytes<200) echo $bla;
      //if(is_buffer($bla)==false) echo $bla;
    }
}
?>
 
Moin,

diese "Dokumentation" umzusetzen, da gibt es einen Knackpunkt :-(

Die Server wiederholen diese META-Blöcke meist nicht, wie erwartet, jeweils nach x Bytes. Im Grunde genommen kannst du nur halbwegs darauf vertrauen, dass der 1. Block nach den x Bytes kommt.
Danach wird er idR. erst wieder mitgeschickt, wenn es einen neuen Titel zu vermelden gibt.

Daher eine etwas andere Herangehensweise als Vorschlag:

Schaue in jeder Zeile nach, ob dort "StreamTitle" steht. Ist das der Fall, hast du den META-Block. Lese das Byte vor dieser Fundstelle und multlipiziere es mit 16...dann hast du die Länge des Blocks, die du lesen musst(beachte dabei, dass die Länge des Blocks also immer durch 16 teilbar ist...sind die eigentlichen Infos kürzer, wird er mit Bytes aufgefüllt).

Diesen Block kannst du dann nach belieben verarbeiten.
Ich hab da mal was vorbereitet: :-)
PHP:
<?php
$streams=array(
  'Cyber-FM' =>array('67.228.177.15',       8042),
  'LiveSets' =>array('stream.livesets.com', 8000),
  'Evolved'  =>array('208.83.20.167',       8090),
  'Bassdrive'=>array('205.188.215.226',     8012)
);

?>

<form method="POST">
<select name="stream">
<?php
foreach( $streams as $k=> $v)
  {
    echo '<option '.
         ((isset($_POST['stream'])&& $_POST['stream']==$k)?' selected':'').
         '>'.htmlentities($k);
  }
?>
</select>
<input type="submit">
</form>


<?php
if(isset($_POST['stream']) && isset($streams[$_POST['stream']]))
{
  $headers=array();
  $stream_ip = $streams[$_POST['stream']][0];
  $stream_port = $streams[$_POST['stream']][1];

  if ($fp = fsockopen($stream_ip, $stream_port)) 
    {
      fputs($fp, "GET / HTTP/1.0\r\n");
      fputs($fp, "Icy-MetaData:1\r\n\r\n");
    
      do //Header lesen und ausgeben
        {
          $header = fgets($fp);
          $arr=preg_split('@:@',$header,2);
          if(count($arr)==2)
            {
              $headers[$arr[0]]=$arr[1];
              echo '<strong>'.$arr[0].'</strong>:'.
                    strip_tags($arr[1],'<a>').'<br>';
            }
          
        } while ($header != "\r\n");
      
      
      //Nach META-Block suchen
      if(!empty($headers['icy-metaint']))
        {
          while(!feof($fp))
          {
            //Skriptlaufzeit verlängern
            set_time_limit (5);
            
            $line=fgets($fp);
            
            //META-Block gefunden?
            /*
              ich schaue zuerst mit stristr nach, 
              um nicht bei jeder Zeile preg_match() bemühen zu Müssen
            */
            if(stristr($line,'streamtitle') 
                && preg_match('@(.)StreamTitle.*$@',$line,$matches))
              {
                //Erstes Byte des META-Blocks * 16 = Länge des Meta-Blocks
                $meta_length = ord($matches[1])*16;
                
                //Ausgabe
                echo '<hr>'.substr($matches[0],1,$meta_length-1);
                flush();
              }
            }
          }
    }
}
?>
 
Zuletzt bearbeitet:
Zurück