title: Icecast/Shoutcast radio stream: extracting now playing info
body: <p>How do I extract "current track / now playing" info from a shoutcast/icecast radio stream? I tried following solutions:</p>
  
  <ul>
  <li><a href="https://github.com/ghaiklor/icecast-parser" rel="nofollow noreferrer">https://github.com/ghaiklor/icecast-parser</a></li>
  <li><a href="https://code.google.com/archive/p/streamscraper/" rel="nofollow noreferrer">https://code.google.com/archive/p/streamscraper/</a></li>
  <li>Parsing the .xspf file <a href="https://stackoverflow.com/questions/40174150/cant-extract-metdata-from-some-icecast-streams">Can&#39;t extract metdata from some icecast streams</a></li>
  <li>Analyzing the audio stream in PHP/native Android (<a href="https://stackoverflow.com/questions/44050266/get-info-from-streaming-radio">get info from streaming radio</a>, <a href="https://stackoverflow.com/questions/4911062/pulling-track-info-from-an-audio-stream-using-php/4914538#4914538">Pulling Track Info From an Audio Stream Using PHP</a>, <a href="http://www.smackfu.com/stuff/programming/shoutcast.html" rel="nofollow noreferrer">http://www.smackfu.com/stuff/programming/shoutcast.html</a></li>
  </ul>
  
  <p>All of the methods above work for some radiostations, such as 
  <a href="http://icecast.vrtcdn.be/stubru-high.mp3" rel="nofollow noreferrer">http://icecast.vrtcdn.be/stubru-high.mp3</a></p>
  
  <p>However, for a number of icecast/shoutcast streams, all of them fail. Example: <a href="http://icecast-qmusic.cdp.triple-it.nl/Qmusic_be_live_64.aac" rel="nofollow noreferrer">http://icecast-qmusic.cdp.triple-it.nl/Qmusic_be_live_64.aac</a>. When analyzing the audio stream itself, the streamTitle is always empty. The xspf file always has an empty title tag. However, I notice other apps and websites do succeed in gathering current track info for this radio station. The homepage of the radio station also contains the current track/playlist info: <a href="https://qmusic.be/playlist/qmusic" rel="nofollow noreferrer">https://qmusic.be/playlist/qmusic</a>.</p>
  
  <p>I know I could go and write an html scraper that extracts this data, but I only want to use this as a last resort. Besides, I have multiple streams with similar problems and this would not be a generic solution that can be applied to all of them.</p>
  
  <p>So, am I missing something? Is there another general way in which metadata can be extracted from an icecast/shoutcast server? I also tried using the 7.html file or the /stats?sid=1 files, but did not have a lot of luck with these approaches (as in: files not present/invalid urls). Below a php script from one of the hyperlinks that works in some cases. Any help or feedback would be greatly appreciated! </p>
  
  <p>PS: Sorry for the mixup of tools/frameworks/languages. Tried lots of stuff here. Extra thanks for answers that are React-Native compatible!</p>
  
  <pre><code>&lt;?php
  function getMp3StreamTitle($streamingUrl, $interval, $offset = 0, $headers = true)
  {
      $needle = 'StreamTitle=';
      $ua = 'Mozilla';
      $opts = [
              'http' =&gt; [
              'header' =&gt; 'Icy-MetaData: 1',
              'user_agent' =&gt; $ua
                  ]
              ];
      if (($headers = get_headers($streamingUrl))) {
          foreach ($headers as $h) {
              if (strpos(strtolower($h), 'icy-metaint') !== false &amp;&amp; ($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://icecast.vrtcdn.be/stubru-high.mp3', 16000));
  </code></pre>