Build an Embedded MP3 Player in Flash

Introduction
In my last article Use Web Standards With Flash, I mentioned that Flash is most useful for building small player applications that present audio and video content. Today, I’d like to dive a little deeper into this idea and present a technique for playing MP3 files in a browser window.

Say you have created some audio files that you are really proud of. So proud, in fact, that you’d like to include these songs on your site. Now, in pure HTML and CSS, you can provide beautifully styled links to each of your MP3 files. Lovely, except that each time a user clicks on a link, he leaves the page that lists the links to all of your other songs. Instead, he gets a nice, pure white browser window with the little Quicktime toolbar.

What’s wrong with that? Well, not only can the user not immediately access the other songs you’ve posted, but there may well have been additional content that the user wanted to read while listening to your truly stunning audio files.

Before we jump up and say, “Oh yes – let’s use Flash,” we should consider other alternatives. The first thing that comes to my mind is Windows Media Player. Windows media files can be embedded in a page, and, through the use of JavaScript, you could even build a dynamic menu. But then you run into the tricky problem of cross platform support for .wma files. At least, the embedded stuff never seems to play correctly on my Mac. Also, presuming you are starting with MP3 files, you’ll need to re-encode your music before you post it. Not to mention the fact that many people don’t have Windows Media Player installed at all. Then there’s Real Player, which has some advantages such as better cross-platform support, but still requires an extra step of running your audio through another encoder.

So, we want a solution that lets us post regular old MP3 files and play them in a browser using an embedded interface. If I may, I would suggest that Flash is an excellent choice in this situation.

Using the embed techniques discussed in my earlier article, we can offer users a simple interface built in Flash that allows then to listen to audio without leaving the page. A number of Webmonkey readers wrote to say they like that idea and wondered if I might write a tutorial on actually building an MP3 player. So, today I’ll show you how to make a Flash MP3 player with a very simple play/pause button. The resulting file will weigh in at a paltry 4KB. You can embed the player on your page and allow users to listen to your audio content (podcasting anyone?) without leaving the page. I won’t go into the complete detail necessary to create a full blown iTunes-type Flash jukebox, but I’ll offer a few suggestions for how you might go about doing so. First, we’ll start with the bare bones necessities of playing MP3s in Flash, namely the ActionScript class Sound.

What you’ll need
•Adobe (Former Macromedia) Flash
Steps
Pushing buttons
Before we get started with the sound object itself, let’s think about the most stripped down possible MP3 player. What exactly do we need to present the user with? I’m going to go out on a rhetorical whim and say that its possible to use simply one button, or rather, two buttons in one. Namely, a play button that toggles itself back and forth between “play” and “pause” depending on the state it’s in. In other words, when no sound is playing, it appears as a play button to tell the user that pushing it will play some audio. Once the user pushes it and the track starts playing, our button will turn into a pause button. And that’s it. It’s small, lightweight, and offers the bare essentials of what the user needs.

Let’s get started. For the examples in this article, I’m using the most recent version of Flash, which is included in Macromedia Studio 8. There’s a demo available for download at Macromedia’s site if you don’t already have the software.

Open up a new Flash document and create a simple play/pause button using whatever design you would like. I modeled mine after the iTunes interface since it’s a fairly popular cross-platform application that most people will recognize. Hopefully, Apple won’t think I’m stealing their idea. I just happen to think that, when it comes to user interfaces, repetition and familiarity are good things.

Create two graphics, one for the play button and one for the pause button. Put the play graphic on the stage and resize the stage to match the dimensions of the graphic. Next, turn the graphic into a movieclip and give it an instance name of “play_mc.” Then, put the pause graphic on a new layer on top of “play_mc” and turn the pause graphic into a movieclip with an instance name of “pause_mc”.

The last thing to do is create an invisible button to place over the graphics. To create an invisible button, just choose “New Symbol” from the “Insert” menu, choose “Button” for the type and give it a self-explanatory name like “invis_btn.” Then, you will be taken to the button’s timeline. Insert a keyframe in the “hit” frame and draw the shape you want for your button. In this case, I drew a circle.

Go back to the main timeline and drag your new button out of the library and onto the stage. At this point, you should see a pale blue shape on the stage. This shape won’t show up when you publish your movie, it simply allows you to see the active area of the button. Give the button an instance name of “trigger_btn.”

Here is a screenshot to give you an idea of how things are looking so far.

Hit me with music
The next step is to write some pretty basic code. Some people would even consider this the “fun part.”

Create a new layer on your main timeline and label it “actions.” Select the first frame and open the Actions panel.

OK, now hold up for a minute. Before we get down to the actual code, let’s think about what we need our bare bones MP3 player to do. We need to load an MP3 file, and then we need to play and pause that file. Pretty basic, right? Luckily for us, the good folks at Macromedia have given us a built-in Class to handle sounds. Naturally, it’s called Sound. It’s already part of ActionScript, so all we have to do is create an instance of the Sound class and assign the controls to our invisible button. But first things first. Let’s add a line of code to set the initial state of our pause button to hidden.

pause_mc._visible = false;

We are going to present the user with a simple play button which, when pressed, will start playing an MP3 file. We need to write a function to load the MP3, a function to stop the MP3 and a function to start the MP3. Now, because we’re using one button to both play and pause, we’ll need a fourth function to act as an intermediary to determine whether the user wants to play or pause based on the current state of our sound. Here are the four main functions we’ll use to control our MP3 player. Copy and paste this code into the first frame of the actions layer:

function getSound(url:String) {

sound.stop();

delete sound;

sound = new Sound();

sound.onLoad = function(success:Boolean) {

if (success) {

trace(“[MP3 Player]:file loaded”);

} else {

trace(“[MP3 Player]:Could Not load Sound Data from file,

please try again”);

}

};

sound.loadSound(url, true);

}

function audioStop() {

sound.stop();

$marker = sound.position/1000;

$state = false;

}

function audioPlay() {

sound.start($marker);

$state = true;

}

function checkState() {

if ($state == true) {

pause_mc._visible = false;

audioStop();

} else {

pause_mc._visible = true;

audioPlay();

}

}

Now let’s go through each function and examine what’s happening.

The getSound(url) function is what initially loads the MP3. It takes one parameter:a string representing the path to the actual MP3 file.

The first thing we do in this function is stop the sound object and then delete it. Now why would we stop and delete an object we haven’t even created yet? Well, in the future, you may want to write some code that calls this function to load a second MP3. The sound object is quite happy to load several MP3s on top of one another and play them all simultaneously (as you might want to do in video game, for instance). However, for our purposes, this is no good. So before we create the sound object, we make sure we destroy the old instance if one exists.

Next, as the third line says, we create a new sound object. In the code, I have chosen to give the sound object the rather uncreative name “sound.” The Sound class that’s built into ActionScript has some standard methods such as onLoad(). In this case, I haven’t really done anything with the onLoad method other than trace some output so you can see whether or not your MP3 has loaded when you test your movie. However, if we were making something more complex, we might actually have some code that is triggered when the sound object finishes loading the MP3.

There are some other handy methods that come with the sound object. onSoundComplete(), for instance, triggers an event when the sound file is finished playing. This can be very handy for something like a jukebox type application where you want to move to the next sound as soon as the current one finishes.

The next line we’re going to look at uses the loadSound() method. The Sound class has some other methods as well. See the ActionScript reference panel in Flash for more details.

After the onLoad method, we have the meat of the function. The line sound.loadSound(url, true); is what actually loads the MP3. This method takes two parameters. The first is the path to the MP3 file, with which we pass on the variable “url” from our function parameter. The second parameter of loadSound controls whether or not the sound is “streamed.” I think this is poor semantics on Macromedia’s part since this does not really control true streaming. This parameter simply controls whether or not the sound starts playing as soon as it can or waits until the entire file is loaded before starting to play. True streaming, (i.e. not downloading), requires server side software and is way too complicated to get into in this article. While it may appear that our MP3 is streaming since it starts playing right away, it’s really just downloading into the user’s browser cache, which true streaming media does not do. So, despite the poor word choice, we want our sound to start playing as soon as it can, thus we set the parameter to “true.”

Alright, we’ve gotten the MP3 to load and to start playing as soon as it can. On the next page, we’ll look at the rest of the code, including that good ol’ button magic.

Make it stop (and start again)!
Onward! Referring back to the code on the previous page, we’ve already demonstrated how to load our file and get it to start playing.

The next two functions are the audioStop() and audioPlay() methods. These methods will be triggered by the fourth function. They are essentially wrapper functions for the Sound class’ built in Sound.stop() and Sound.start() methods. However, our functions do one additional and very important thing:they control the state of a Boolean variable (a variable that can either be true or false) named $state. I have added the $ prefix to the variable name because, were we creating a custom class out of this code, $state would be what’s called a class variable. It’s sort of a programming convention – at least in Java – to prefix class variables with a dollar sign. If it bothers you just pick a different name, but don’t simply call it “state” without the $, which happens to be a reserved word in ActionScript. This variable is the logic of our code. It keeps track of whether or not the MP3 is playing and allows our last function to determine whether or not the user is trying to play or pause the player.

You might notice that audioPause has an additional line of code that sets a variable “$marker”. This variable keeps track of where the playhead is resting. The built-in function Sound.start() can take a position parameter like so:Sound.start(position). If the position parameter is left undefined, then the track plays from 0, or the beginning. This is obviously not what we want. If our user is near the end of the track and pauses it to go make a banana split, when he returns and hits play, he does not want the sound to start over from the beginning. So, we need to find out where we are when the user presses pause. To do this, we will grab the read-only parameter Sound.position. For whatever reason, this parameter is read in milliseconds, but the Sound.start() method expects a number in seconds. Solution? Divide by one thousand.

The last function we’ll use is called checkState(). This will be the function that our button calls when it is pressed. All this function does is check to see whether our sound object is currently playing or not. It then acts accordingly to change that state by calling either audioPlay() or audioStop().

OK, those are the major functions. Now, we just need to add a few lines at the top of all this to initialize our variables and call our functions. Cut and past the following lines of code into frame one of the actions layer. It doesn’t really matter if put it above or below the prior code.

getSound(“myMP3.MP3″);

sound.stop();

var $state = false;

var $marker = 0;

trigger_btn.onRelease = checkState;

So, what does it do? The first line here calls our getSound function and passes it the path to the MP3 file on the server. Next, we tell our sound object to stop playing. So it finds the file, starts to load it, tries to play it, and then gets told to stop. This line is up to you. I don’t like pages that automatically start playing sounds at me, so I make the starting of the sound a user action. But you may want to take it out, because if the user doesn’t press the play button, they’ll never hear anything. If you want the sound to start automatically, just omit this line and change the next line to var $state = true;.

Why not just make the play button start the whole loading process you ask? Well, I like to initialize the loading in the background. That way, by the time the user gets around to actually pressing the play button, the whole file may be loaded and the user experiences no load time at all. The code that controls this sets the $state variable to “false” since the sound has been stopped.

Next, we create the $marker variable and set its value to “0”. We do this because the first time the user pushes the button, we want the sound to start from the beginning. The last line sets our invisible button’s release event to the function checkState.

Pretty simple, eh? Let’s look at some of the more heavy duty features you can add to this simple player.

Save time for a slow dance
And there you have it, a quick and extremely simple MP3 widget you can drop into your page.

Now, for those of you looking to build something a little bigger and slightly more complete, I have a few suggestions. The Flash Sound class does not have built in fast-forward or rewind methods. The best way to add this functionality is by using the setInterval method of a movieclip.

Create a button and attach a setInterval call to its onPress event. Set the interval to call a function ff() which will fast-forward the track. I’ve found that an interval of 500 milliseconds produces the desired effect without disorienting the user. Next, you need to clear the interval with the release event of the same button. As for the ff() function itself, you might want to consider using sound.position much as we did earlier for our $state variable. In this case, you would want to find the position of the playhead, stop the track, advance the playhead and then restart the track. Something like this will work with what we have so far:

function ff () {

var old = sound.position/1000;

sound.stop();

new = old+5;

sound.start(new)

}

Another feature you might want to add:volume controls. You could use simple buttons or get fancy and use a sliding bar. Both of these are left as exercises for the reader, but I will tell you that the Sound object has two built in methods called getVolume() and setVolume() which should help get you started.

We also shouldn’t overlook the question of playing multiple tracks within the same movie. There are about a dozen ways you could handle this, though from my own experience a separate XML file is usually the way to go. Just load the XML file into Flash and parse out the info you need. Include the path to the file, the title, artist, album, and any other information you’d like to display. Finally, just pass the path along to our getSound() function. This works very nicely if you’d like to add a podcast link to your site, since podcasts are RSS files and RSS is really just XML.

As you can see, it’s possible to make some very fancy MP3 players using Flash. In fact, you can recreate just about all of the functionality of popular desktop players like iTunes or WinAmp using only Flash and ActionScript. Hopefully, this article has allowed you to develop a very simple way to give your web audience some music to listen to – and whetted your appetite to perhaps build a full-blown audio application.