How to keep html up to date with metadata from shoutcast using php and ajax without stream's password?

StackOverflow https://stackoverflow.com/questions/19949181

  •  30-07-2022
  •  | 
  •  

Вопрос

First let me explain where I'm coming from. I've got a great grasp of javascript, html and css, client sided stuff. Server sided code like php and server-client code like ajax are not my strong suits. From most of every single article I've read about extracting the metadata from the stream points to here. http://www.smackfu.com/stuff/programming/shoutcast.html And then someone says, just use php and ajax! It's not very helpful or direct since I'm just picking up both. I've yet to learn anything really about headers and using get requests so I'm at a loss with this method.

I also found an article which said to look up shoutcast class php, this is what I've found most helpful so far, and this is what I'm working with now. This one assumes I know the password to the stream I'm looking for (not ideal) but luckily I do. https://github.com/MaThGo/shoutcast-class/blob/master/shoutcast.class.php

Both of these I understand are different, the first is pseudo code for grabbing metadata as it passes by in the stream, the second is just pulling xml of the same metadata but off of the webserver.

I'm assuming it'd be an easy switch to change the class a bit to pull the same information from the 7.html instead, no password would be required.

Where I was originally stuck: after modifying the above shoutcast class script a bit I end up with the song and stream title in a variable. I've saved it (and tested it so I know it does output the right info using echo) as getInfo.php in the same folder as my index.html file.

<?php //shoutcast class script from above link followed by

$stream = shoutcast("ip","port","pass"); //constructing the class
$streamData = stream.getShoutcastData(); //getting array of shoutcast metadata
$streamTitle = streamData["SERVERTITLE"]; //gets the server's title
$streamSong = streamData["SONGTITLE"]; //gets the current song playing artist and track
$playerText = "You're listening to {$streamTitle} <br> Song: {$streamSong}"
echo $streamTitle;
?>

If I have an audio element and a div for the song information with an id "info" how can I run this script and have it only modify the content for that div every couple of seconds? Obviously I don't want to eat a ton of bandwidth requesting / or getting metadata that is not different than before. This is what I'm assuming the php and ajax combination is for. Figured this out, look further below, this is a terrible example script:

<!DOCTYPE HTML>
<html>
<head>
   <script>
       //perhaps something like this?
       function update()
       {
          document.getElementById("info").innerHTML= //not sure what do do here
       }
       //or a function which uses setTimeout()?
   </script>
</head>
<body onload="getThingsStarted()">

   <!--Where the magic should happen-->
   <div id="info">Somewhere in here</div>

   <div id="audio">
      <audio autoplay="true" controls="controls" src="http://ip:port/;">
   </div>

</body>
</html>

Fixed: My original code had bad syntax so the XMLHttpRequest inside my ajax code never executed, so no results were ever being returned (figures). Here's what got it working.

<!DOCTYPE HTML>
<html>
   <head>
   <script>
       //php ajax sample code w/ one slight modification from w3schools.com
       function loadXMLDoc()
       {
          var xmlhttp;
          if (window.XMLHttpRequest)
          {//IE7, Firefox, Chrome, Opera, Safari
             xmlhttp=new XMLHtppRequest();
          }
          else
          {//IE6, IE5 wow these are old
             xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
          }
          xmlhttp.onreadystatechange=function()
          {
             if(xmlhttp.readyState==4 && xmlhttp.status==200)
             {
                document.getElementById("info").innerHTML=xmlhttp.responseText;
             }
          }
          xmlhttp.open("GET","stream.php?q=1",true);
          xmlhttp.send();
       }
    </script>
    </head>
    <body>
       <div id="info">Stream info</div>
       <audio autoplay controls="controls" src="http://ip:port/;" ontimeupdate="loadXMLDoc()">
    </body>
</html>

Second Question: I'm wondering if anyone can point me to a good example of extracting the metadata using the method from the first link, or a modification of the shoutcast class so it doesn't require a password? Much appreciated.

Since the metadata from the server is a couple of seconds ahead of the stream (makes sense shoutcast uses a buffer so the audio is behind the webserver's changing metadata) I'm curious if I could compare the results (perhaps check for how large of a time delay between server and clients content?). Just some thoughts...

Это было полезно?

Решение

What version of DNAS are you running? In 2.0+ you should be able to pull an XML output of all public stream statistics from http://ip:port/statistics. Here's a live example of (hopefully) what you're trying to accomplish using JS: http://subfocus.fm.

To work around cross domain/port restrictions in the XMLHttpRequest (80 vs 8000 in this case typically) I have a local server script running a wget every minute to download the ShoutCAST XML file to the web server root path (publicly: http://ip/stats.xml). This may not be feasible in your case but I thought I'd share my patchwork solution.

As long as you have the XML on your web server, you should be able to use something along the lines of this for a single stream station:

<head>
<script>
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest()
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
}
function scMetaData() {
xmlhttp.open("GET", "stats.xml", false);
xmlhttp.send();
xmlDoc = xmlhttp.responseXML;
document.getElementById("info").innerHTML = "<b>Now Playing:</b> " + xmlDoc.getElementsByTagName("STREAM")[0].getElementsByTagName("SONGTITLE")[0].childNodes[0].nodeValue
}
setInterval(scMetaData, 10000);
</script>
</head>

<body onload="scMetaData();">
<span id="info"></span>
</body>

After creating the XMLHttpRequest object the rest is stored in a function to be called at a specified interval in milliseconds by setInterval(scMetaData, 10000); at the end of the script and also upon loading with <body onload="scMetaData();">. The live example I linked adds a FOR loop to parse the XML track IDs for 2 ShoutCAST streams.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top