How to Tell a SWF What File(s) to Load — From the Outside

ActionScript 2.0 Flash

A number of people have asked how I handled the microphone icons in my last post, Papi’s Wah-feh (An Audio Guide).  Did I simply use Save As a bunch of times to create eight separate SWFs, each with its own imported audio?  I certainly could have done that, but I decided instead to create one single SWF that could be told from the outside which MP3 to play.  Not only does this mean I can re-use that SWF as often as I like — without recompiling, by the way! — but it also reduces download time, because the SWF is only retrieved once (only 407 bytes, at that!), and the MP3s only load as needed.

The following technique can be used for graphics, too — really, for any file a SWF can load at runtime, from CSS to video (FLV), to other SWFs.  Let’s take a look. 

An answer, moderately long and sweet (and how it works)

It’s a good idea in general to load external files for audio, unless you need tight synchronization, such as for cartoon lipsynching.  Why?  Well, again, a SWF by itself has a much smaller footprint without the extra weight of imported sound files.  Besides, if the user happens not to venture down a particular path in your movie, why force the download for that section?  Let the user download files as they’re needed.  ;)

Under normal circumstances, I might have programmed the microphone graphic (a button symbol) with my ActionScript in a keyframe like this:

var s:Sound = new Sound();
iconButton.onRelease = function():Void {
 s.loadAudio("path/to/audio/sound.mp3", true);
}

Note:  For a look at this code in the AS3, see “How to Retrieve FlashVars Data in ActionScript 3.0.”

In the first line, an arbitrarily named variable, s, is declared and set to an instance of the Sound class.  In line 2, a function literal is assigned to the Button.onRelease event of a button symbol whose instance name is iconButton.  This function literal calls the Sound.loadSound() method on the s instance and supplies the path to an external MP3 file.  The second parameter, true, tells Flash to start playing the audio as soon as enough data are available — even if the file isn’t yet completely downloaded.

But clearly, this approach is hard coded.  In order to open up the possibilities, replace the path reference with a variable — let’s just call it audio.

var s:Sound = new Sound();
iconButton.onRelease = function():Void {
 s.loadAudio(audio, true);
}

Note, the quotation marks are gone, because the audio variable now contains that string.  But wait, where is this variable declared?  Currently, it’s undefined, right?  Right.  We’re going to pass in the desired string from outside the SWF.

There are a number of ways to do this, but in this article, we’ll look at the FlashVars approach.  SWF files are embedded into HTML via the <object> and <embed> elements.  The <object> element contains several child <param> elements, and these contain attributes that set various properties of the SWF, such as where the SWF file is located, its width and height, quality settings, and so forth.  Internet Explorer reads the <object> element and other browsers read <embed>, so if you look carefully at a working sample, you’ll notice that <object>’s <param> attributes are basically mirrored in the <embed> attributes.  With FlashVars, you simply need one additional <param> element and one additional <embed> attribute to match, both of which can be tossed into the mix wherever you please.

Here’s the skeleton of a typical <object>/<embed> pair.

<object [several attributes, including width and height] >
 <param name="movie" value="movie.swf" />
 <embed [attributes, including width, height, and src]></embed>
</object>

FlashVars effectively allow you to declare a SWF’s variables from the HTML.  Note:  these will be strings only, so if you want to pass in a number, you’ll have to cast it as such inside the SWF (parseInt() or parseFloat(), for example).  These variables will be scoped to the main timeline, so using FlashVars is the equivalent of typing …

var audio:String = "path/to/file/audo.mp3";

… in frame 1 of the main timeline.  Here it is.

<object [attributes] >
 <param name="movie" value="movie.swf" />
 <param name="FlashVars" value="audio=path/to/file/audio.mp3" />
 <embed [attributes] FlashVars="audio=path/to/file/audio.mp3"></embed>
</object>

Again, note that both the <param> and <embed> elements need the same information.  The above creates a string variable audio in the main timeline — which is the variable reference in the Button.onRelease handler above!  So there it is.

If you want to pass in a number of variables, separate each name/value pair with an ampersand (&).

audio1=aaa.mp3&audio2=bbb.mp3&audio3=ccc.mp3

What about SWFObject?

If you’re using Geoff Stearns’ SWFObject to get around the IE “click to activate” issue, simply use his object’s addParam() method to add your FlashVars virtually.

<script type="text/javascript">
 var so = new SWFObject(
  "movie.swf", "mymovie", "200",
  "100%", "7", "#336699"
 );
 so.addParam("FlashVars", "audio=music.mp3");
 so.write("flashcontent");
</script>

Update!  Here‘s a sample file (thanks for the suggestion, Amy!) to illustrate what‘s shown above.  The sample shows an MP3 file specified from the HTML, using traditional embed and SWFObject.  The SWFObject example uses addVariable() instead of addParam(), as shown above.

Leave a Reply