Update jPlayer track/listeners on a webpage with jsonp

With version 2.4, IceCast is shipping their own xml2json template. IceCast 2.4 doesn’t yet deal with the CORS issue so if you want to parse the metadata/listener count etc. client-side, you will still need to output JSONP. IceCast 2.4.1 has fixed this.

I recently found myself working on a small web-radio project for some friends, and I stumbled upon some interesting technical “challenges” (to say so).

I wanted a HTML5 Web-Radio Player (I used the excellent jPlayer project, which supports html5’s <audio>in a wide range of browsers, but also has a fall-back to Adobe Flash for older browsers), but I also wanted the current playing track and a listener count on it. I modified a default jPlayer skin to show up the elements I needed, but I was still left with the issue of actually getting the data from the icecast server to my webpage (player).

From my searches I found some PHP scripts that connect to the stream and retrieve the data using the ICY protocol, but those were really slow based on my tests.

Keeping on searching, I found some good ideas of using Icecast’s templating system that is used to generate its admin & stats pages, which are all output as XML, to generate JSON instead.

Now, this would be all fine and I would have considered this matter fixed, except… there’s the “dreaded” Access-Control-Allow-Origin: * issue, which prevents you from loading JSON data from another domain other than the one the page is hosted, unless you send the Access-Control header, which you can’t really do using Icecast.

The other solution involved using JSONP (which is basically JSON wrapped in a function, that is loaded by the browser as a script and interpreted), and this looked perfect!

Without further explanations (because I suck at writing these things), here’s the rundown.

Tools needed:

  • An Icecast server that you have access to (ie: you can modify it’s config file and it’s web templates)
  • A page where you can use jQuery (not hard, really, it’s hard to find a project these days that doesn’t use jQuery)
  • Some ideas on how stuff works ©

First step is to create the XSL file that is used to generate the JSONP data we’re going to use.

Create a file called json.xsl with the following contents. I placed mine (on ubuntu-server) in /usr/share/icecast2/web/ :

Updated: Added SL’s suggestion to the xml:output tag.

If everything’s good, you should be able to go to http://yourserver:port/json.xsl and receive a JSONP string like this:

In this JSONP you can see the mount point listed as /radio and then the stats. These can be extended to support more data (everything that icecast is able to show about a specific mount point).

Now, to actually make an use of this data, we will use some simple HTML elements and some simple AJAX with jQuery.

The HTML code that interests us:

And the javascript code that does all the magic:

This defines a function called radioTitle() that does all the magic needed.

As for updating the data while the page is opened, we will need to add 2 timers to be run on the webpage every 10 seconds. We will also do this using jQuery, because it’s more convenient

And that’s pretty much all the work.

You can see it in action (and play around) on this JSFiddle: http://jsfiddle.net/Znuff/vL5TM/

I will try to extend the json.xsl file whenever I will have the time with all the possible stats, but for now this will work.

Credits for the ideas:

You can see it in action on this page: http://stream.amea-radio.gr/

  • SL

    Hello

    A small addition to avoid a “Resource interpreted as script but transferred with MIME type text/plain” warning in Chrome: add media-type=”text/javascript” to the xsl:output tag.

  • Phil

    Hi

    Congratulations, your work is nice, a very interesting solution to avoid the use of php, and opening broadcast software ports to everybody.

    Thank you very much for sharing it.

    Bests
    Phil

  • geox

    You really save dud, tanks!

    • geox

      *You really save me dud, tanks!*

  • Danut

    Salut, ma tot chinui de ceva vreme sa-mi fac si eu o simpla pagina web cu un player radio acolo (shoutcast/icecast) dar nici ca reusesc, sunt prea in afara ca sa ma descurc, si de aceea daca te rog sa-mi trimiti si mie un exemplu cu toate fisierele incluse, in format .zip se poate? (poate-ti cer prea mult dar multumesc oricum)

  • lee

    is it possible to extend this script so it detects fallback mounts?

  • gnfb

    OMG as the yunguns say! I think this is my solution icecast server at home/edcast/winamp/
    http://101.98.206.223:8000/ to also play on ipads http://radio.wlg.co.nz/sound/ . But was having problems getting to work. Am a real novice at this just a hobby anyway lets see if I can follow what you did………..

  • AndRec

    Hey, thank you very much for the tutorial.

    This is exactly what I want.

    Did you use WordPress for this?

    I’m asking that because I’m trying to do it using WordPress.

    The first problem is that I haven’t found any tutorial to install Jplayer in WordPress. Then I installed the plugin mp3-jplayer, which is based on jplayer and it is working fine.

    So now I just am not sure about where am I supposed to put the javascript file.

    I put this code in functions.php:

    function RadioTitle() {

    wp_register_script( ‘RadioTitle’, get_template_directory_uri() . ‘/jvs/jsmeta.js’, array(‘jquery’),’1.0.0′,true );

    wp_enqueue_script( ‘RadioTitle’ );

    }

    add_action(‘wp_enqueue_scripts’, ‘RadioTitle’);

    And, of course, I created the jvs directory and put the code that you provided.

    Is this the right procedure? It doesn’t seem to work here, but probably I’m doing something wrong.

    Thanks again!

    • I wanted to use wordpress in the beginning, but I gave up on that idea.

      I’m not familiar with these plugins

      • AndRed

        That’s OK. Thanks.

  • Getterzinger Hi

    Hello.

    I’m having some trouble with your code. The json works fine and returns what I want. However, the javascript isn’t working. I tried it on my website, but to no avail. The js fiddle code doesn’t seem to update itself either after running it. What am I doing wrong? I’d be very grateful for some help.

    • The jsfiddle posted doesn’t have a source anymore (the service I made it for is currently down), so it can’t update stuff.

      I’ll need a source of data.

  • tony

    Great article! Looks like icecast 2.4.1 supports setting arbitrary HTTP headers per-mount or globally:

    http://icecast.org/docs/icecast-trunk/changes.html

    “Fixed JSON access by adding support for global and mount specific custom HTTP headers.

    The purpose is to fix JSON access from browsers, by supporting basic CORS use cases. This is both important for some HTML5 or use cases and accessing the JSON status API.

    The default icecast config contains the very permissive global header: “

    • Thanks. I’ll add this to the article.

  • Awesome script, thanks!
    I have added a line that will report the current title of the fallback/autoDJ stream if there is no reported title for the live mount point. I don’t know much about javascript but it works perfectly. haha
    http://pastebin.com/2hWUUNSc

  • Very cool, thanks for the tip!

  • I have to thank you many times for this great tutorial. As a Javascript/JSON newbie it was very helpful and I got a working result in no time.
    During testing I found a problem with your json.xsl: It does not properly escape reserved characters as ” in the JSON output. This results sometimes (When the title contains a “) in a malformed JSON object and no track information is displayed.
    I found solutions to this problem. But I was not successful in implementing it myself. As a reference, also the status-json.xsl provided with newer icecast versions includes code to correctly escape characters.

    • As a recommendation, always use the latest tools provided by IceCast. I don’t really use IceCast myself that much, and I’ve kept this post mostly for historical reasons.

      Why not just use their status-json.xsl template and just switch to using JSON instead of JSONP with my code?

      • I had the same idea and tried the status-json.xsl provided by icecast. But I struggled with the resulting JSON. With your xsl it is easy to directly index the string you are interested in. With the icecast xsl I would have to search through first, to find the correct index for a certain mountpoint.

  • Colin Davis

    Hi am a very new to coding, and need some help. I can’t get your script to work, been trying all day with no success. it works using jsfiddle. I copied your code into a blank html document and put the javascript code between and . I have created the json.xsl file and that is working fine. I am using opensuse linux and followed your example. Not sure how to get this working for me. Do i need to load programs onto opensuse, sorry for being such a novice, however I would really like to get this to work. Many Thanks. Colin

    • If it works in jsfiddle but not in your HTML, please keep in mind that YOU HAVE to use jQuery for this to run.

      Also, meet the Developers Console in Chrome (press F12) and go to the last tab (Console) and you will see more info on why it doesn’t work.

      • Colin Davis

        Thank you very much, adding jquery did the trick.

  • Colin Davis

    Hi Znuff. Your script works great, thank you. I have another challenge, and as a new coder I need some help. I am using a program (Radio DJ) which feeds into ice cast and using your script works perfectly, however I am looking at trying something a bit different. Radio DJ outputs a text file which can be configured to contain Artist, Title and Year (and other info if required) The text file contains one line in the format for example: Michael Jackson – Thriller – 1982. This text file is updated every time the song changes. What I want to do is read that text file, say every 15 seconds and display it in a web page. It is very similar to your script idea, but reading a different format file. The output into the web page would look something like this:

    Artist: Michael Jackson
    Title: Thriller
    Year: 1982

    I would be very grateful if you could help me with some code that would achieve my objective.

    As I’ve mention in a previous post, I am new to coding and learning all the time. Your help will be gratefully appreciated. Colin.

  • Pingback: Icecast Now Playing WordPress Widget Script – AutoNarcosis()

  • Ivaylo Georgiev

    Hello , could you please let me know which version of jplayer I need to download for this to work ?
    When I test it with my stream info on jfiddle it works but when I build the javascript and html on my end nothing is updated

    • Ivaylo Georgiev

      also , do I need to add the java code to main.js ? It is not clear to me.

    • Danny Hermans

      i used the 380 player from the soundmanager project than create some divs and create your content blocks important is that you create it as a php page with html elements
      it does auto update for me.. you can see it in working order here ….
      http://player.vrienden-cafe.nl/demo/360-player/testj.php

      • Danny Hermans

        also make sure your icecast.xml is set right this is mine setup i have change the passwords for security reasons….

        53
        10
        5
        12400
        5
        30
        5
        10356

        radiopass
        radiopass
        radiopass

        /radio.mp3
        50
        1
        /tmp.mp3
        1
        /home/mscplitescripts/disc
        /home/mscplitescripts/connect
        1024k

        /live2.mp3
        50
        /trtmp.mp3
        1
        /home/mscplitescripts/disconnecttrans</on-discon$
        /home/mscplitescripts/connecttrans
        1024k

        .
        ./log
        ./web
        ./admin

        ban.txt

  • Danny Hermans

    can it be made that it has a scrolling or color wavy text ?
    that would be super
    this script works well on the latest icecast KS version not sure on the regular version have not tested it with the normal icecast … anyway i would like to have it output with some text effects thanks

  • Nikos Maraslis

    Hi, I don’t know if I am late for this discussion. I am interesting to use this script in a blog with different radios. amea stream is not working any more. Accidently I found a stream that it works and the script is working too.
    The stream is http://reusable-box.me:8001 with mount point /mpd
    I copy your code and this stream in my test page and it works.
    But when I try other Icecast streams the script is not working. I am thinking now that the problem is around that “parseMusic” term. Could it be something to work, with the given by Icecast, “icestats”.. status-json.xsl? (I am not programmer and I’m not owner of any station)
    Thank you.

  • Ian Laborte

    Hey bro, im so bad in english hope you can help me , i know imma bit late, im working on a project like this for thesis, i copy your codes and do all the requirements for this code will work, but in the end it doesnt work, the title wont display. thank you

Next ArticleWindows 8: Enable/Disable Hibernate via PowerShell