Simple music player

April 18th, 2012. Tagged: ffmpeg, JavaScript, Music

I put up a few MP3s on http://anacondalimousine.com, in simple a hrefs. While modern browsers will let you click and display some sort of player in a new page, why not play them in-page without a refresh? Simple enough. Plus we have HTML5 audio. Problem is, old IEs don't support HTML5 audio and you need flash or, god forbid, a Java applet to play them.

What's a webmaster to do? All I need is a simple PLAY button next to each link

While I was aware of SoundManager, I accidentally stumbled across sound.js yesterday and thought I should give it a chance. Tiny (3K), it should give me an easy way to do x-browser playing with the help of some SWF for IE, I assume. Dropped the JS from their CDN (nice), but then what? "Online documentation" points to API docs which I don't feel like reading. Demos don't give you the code. Next.

Sound manager has a nice "basic template". Awesome. Replace the sound.js js with SoundManager's. Load in FF. It's looking for an swf. In FF. Why? Because FF doesn't play mp3. Well, I'd rather convert the MP3 than have the user load SWF. But anyway, I drop the swf. For whatever reason (like you need a reason!) I've disabled flash in FF and forgot about it. So no sound in FF. And maybe I'm not the one. Requiring SWF in FF feels unnecessary, although I'm sure Sound Manager probably has way around it. I'm sure. I've met the author, he's brilliant. But... I still need to write some JS to initialize the playing. And if I'm to write code, might as well go solo.

Here's what I came up with, hope it helps.

Disclaimer: I haven't tested in IE, and I mean at all. Should probably work in newer IEs

Demo

http://anacondalimousine.com

Codez, how they work

Everything in an immediate function. Unobtrusive. Bail if (IE) browser doesn't know about Audio.

(function () {
  if (!Audio) return;
  
  // ...
 
}());

Codes for play and stop:

var playsym = "▶", stopsym = "■";

Some browsers play mp3, some OGG, so let's just change the extension and have both .mp3 and .ogg on the server

var extension = new Audio().canPlayType('audio/mpeg') === '' ? 'ogg' : 'mp3';

Loop though all links on the page, find the ones that point to .mp3

var dl = document.links;
for (var i = 0; i < dl.length; i++) {
  if (dl[i].href.split('.').slice(-1)[0] !== "mp3") {
    continue;
  }
  var p = document.createElement('button');
  p.innerHTML = playsym;
  p.onclick = play;
  dl[i].parentNode.insertBefore(p, dl[i]);
}

Forgot to mention, my markup is as simple as it gets:

  <p><a href="virus.mp3">Virus</a></p>
  <p><a href="yesterday.mp3">Yesterday</a></p>
  <p><a href="parting.mp3">Parting</a></p>
  <p><a href="faultline.mp3">Faultline</a></p>

So all I'm doing is insert a PLAY button right before the link. Onclick it should play.

The play() function initializes Audio with the appropriate extension, based on what the browser supports:

  function play(e) {
    var button = e ? e.target : window.event.srcElement;
    button.innerHTML = stopsym;
    var a = new Audio(button.nextSibling.href.replace('mp3', extension));
    a.play();

And if you click the same button as the music plays, you stop it and reset the button click handler:

    button.onclick = function() {
      a.pause();
      button.innerHTML = playsym;
      button.onclick = play;
    };
  }

That's it

So simple and tiny, it's all inline, no extra requests, not a SWF in sight. Support for 72.3% of all browsers. The other 30% can still download the file and play it with a separate program.

SoundManager and, I assume, sound.js have more features, events and other shiny, but for my simple purpose I'm so happy with the result I'll even blog about it 🙂

For full source - view source at http://anacondalimousine.com

Moarr info:

p.s. about the mp3 to ogg conversion... ffmpeg ftw:

$ ffmpeg -i in.mp3 -acodec vorbis -aq 60 -strict experimental out.ogg

Tell your friends about this post on Facebook and Twitter

Sorry, comments disabled and hidden due to excessive spam.

Meanwhile, hit me up on twitter @stoyanstefanov