Rocking Mars with Streaming Shockwave

A streaming Shockwave tutorial

By Bob Schmitt
January 9, 1998

Since the introduction of Shockwave in 1995, CD-ROM-quality multimedia has always seemed out of place in the low-bandwidth world of the Web. Just like Web designers coming from the print world, Shockwave developers coming from the world of CD-ROM multimedia have had to learn a variety of techniques to reduce the file sizes of their media. They have had to make numerous sacrifices in the quality of their presentations in order to balance the richness and depth of their projects against the patience of the end user in downloading it.

The initial releases of Shockwave offered some help in reducing the required bandwidth with an excellent compression scheme, but large projects still required a lot of patience on the part of the end user. When Shockwave was first developed, Macromedia's engineers were primarily concerned with merely providing playback for Director movies on the Web. Director, being originally designed for disc-based delivery, didn't address the special requirements of the Web. With Director 6, Macromedia has designed many new features to address the unique needs of the Web while freeing developers from time-consuming tricks and workarounds.

A Look at Streaming Shockwave

A Shockwave movie isn't streamed in the definitive sense of the word — a more descriptive phrase would be selective, or preferred, downloading. In a way, a Web page is "streamed." The HTML file is downloaded first and "read" by the User Agent (UA). The UA (a browser in this case) interprets the file and calls for the rest of the media (typically images), displaying it on the page as each element is fully downloaded. This is how Shockwave "streams" — the Score of the movie is downloaded first, and is then interpreted by the UA (the Shockwave plug-in or ActiveX control) and media is downloaded and displayed in the order it appears in the Score.

As with an HTML document, media elements only become available when they have fully downloaded. That is different from true streaming technologies, which allow access to partial "chunks" of media elements.

How well a Shockwave movie streams is based on how well the movie is structured. Understanding how Shockwave streaming works will help you determine the best way in which to construct your movie. Let's look a few techniques for setting up a streaming Shockwave project.

Setting Streaming Playback Options in Director

Director offers several basic options for streaming playback of Shockwave movies. To access the settings, from the menubar select Modify/Movie/Playback. This opens the Movie Playback Properties dialog box show below.

Movie Playback Properties

The Movie Playback Properties Window.

There are three options under Streaming: Wait for All Media, Use Media as Available, and Show Placeholders. The default setting is Wait for All Media, which basically means "No Streaming," as the movie will wait for all the media to download before starting. With Use Media as Available, playback of the movie begins immediately. The empty Stage appears first, and as each piece of media finishes downloading, it appears in place on the Stage. The next option, Show Placeholders, indicates missing or partially downloaded media with thick-bordered boxes that take on the size and shape of the missing graphic.

Take a look at these three examples of a streaming movie which demonstrates these settings:

Wait | Use | Show

The final streaming setting is Pre-Fetch. This option allows you to specify a number of frames to download before playback of the movie begins. This allows you to display the first frames of a movie while the rest of the movie downloads. This option could be used to display a message to the user, such as "Be patient the movie is downloading" or a short animation to entertain them before the real show begins. In a later section, I'll show how you can use this option to create a status bar in the first frame of your movies.

That's it for streaming options with Director itself. Pretty basic stuff, huh? With such basic control over the order in which elements stream, how can you get control over what aspects of the movie your users will be able to access and when? That's where Lingo comes in. Introduced with Director 6 are several new Lingo commands created to give some control over your streaming Shockwave movies. Let's take a look at how to use these new commands and some discuss some techniques in constructing streaming movies.

Using frameReady and mediaReady

Just as its name would indicate, the first of these commands, frameReady, tests whether or not all the media needed for a particular frame is ready. By using this command, you can determine which parts of the movie are ready and display them to the user.

Let's use the Mars Rocks! sample above to show how this command can be used.

In Mars Rocks!, I offer the user a choice of four thumbnails of the rocks of Mars. Clicking on any of the thumbnails takes the user to a larger image of the rock. This is an example of the simplest form of branching in Director — clicking on a thumbnail issues a go frame command jumping the movie to the proper frame with the bigger photo in it.

For example, on the "Yogi" thumbnail, I have attached a sprite script with the command:

on mouseUp
  go frame "yogi"
end

FrameReady

In a streaming movie, if a user clicked on a thumbnail that lead to a frame that was not yet ready, they'd get a blank screen. Using frameReady, we can check to make sure that the Yogi frame is ready and alert the user if it is not. Like so:



In this case, when the Yogi thumbnail is clicked on, Lingo checks to see if all the media for the frame called "yogi" is ready. If it is, it sends the movie to the yogi frame — if not, it pops up an alert box informing the user that the frame is not ready.

See this sample in action:

FrameReady

source MAC | source WIN

MediaReady

MediaReady is similar to frameReady but, where frameReady only checks whether an entire frame is ready, mediaReady lets you be a little more selective by allowing you to test whether media is ready on a Cast member by member basis.

To illustrate this, in this next sample, I've constructed the movie a little differently. Instead of sending the user to a different frame when they click on the thumbnail, I'm keeping them in the same frame and just turning the larger images of the four rocks visible when they are clicked on. In order to make sure the large image is completely downloaded before making it visible, I use the mediaReady of member syntax as seen here:



As you can see the structure is very similar to the frameReady usage, but in this case I'm checking to see if the media for the large photo of Yogi is completely downloaded. If it is, I make the sprite channel that holds the image visible; if the media is not ready, I alert the user.

See this sample in action:

MediaReady

source MAC | source WIN

In the sample above, if you clicked around a bit, you may have noticed that the image of Yogi was the first to arrive followed by Barnacle Bill, Little Matterhorn and Flat Top. This is a good example of the order of loading I mentioned at the beginning of this article. Media is downloaded in the order in which the Cast members appear in the score — starting with frame 1, sprite channel 1 and moving down through the channels and horizontally through each frame. Because the large photo of Yogi appears in the Score before the other large photos, it is the first to download. Understanding how this works will help you to order your Shockwave movie to fit the needs of your project. Place the elements you want to appear first (such as the thumbnails in the Mars Rocks! sample) higher up in the Score and place elements that can be deferred until later, lower in the Score.

Creating a Status Bar Using streamStatus

One of the surest ways to keep a user on the hook through the download process is to provide them with up-to-date feedback on how long the download will take. Nothing does that better than a good-old thermometer-style progress bar.

In this technique, I'll show you how to create a loading-status bar by pre-fetching the first frame of a movie which contains the status bar graphics. The Lingo, streamStatus is used to monitor the download of the movie and create the necessary information to update the status bar.

See this technique in action:

StreamStatus

source MAC | source WIN

First, let's look at how the first frame is set up.

Red bar graphicThe red bar is a graphic 150 pixels wide x 10 pixels high, as seen here. This graphic is intentionally kept very basic to keep the file size as small as possible in order to insure a quick download of the first frame. Next, in a movie script, I've placed a prepareMovie script. In this script, which is activated before the movie starts playing, I set the width of the red bar (sprite 22) to zero (see script below). What we'll be doing here is, using the information reported by streamStatus, calculate the percentage of data that has been downloaded so far. Using that percentage, set the width of the red bar graphic to the percentage of its full width (150 pixels). This will be done within the streamStatus handler.



In addition to setting the width of the red bar to zero, the prepareMovie handler does two more important things. First, it issues the tellStreamStatus(TRUE) command. This command turns on (enables) the streamStatus reporting. Without this command, nothing would be reported using streamStatus. And secondly, the text of the field called "Percentage" is emptied. This field is a text field that appears on Stage that will contain the numerical percentage as the movie streams.

Let's take a look at the streamStatus handler:



Before we discuss the handler, let's talk a bit about how streamStatus works. Like other event handlers (such as startMovie or exitFrame) that are triggered by events that take place in the movie, streamStatus runs continuously as the file is streamed. But unlike other event handlers, it also gathers some very useful information about the file being streamed.

As you can see from the above example, streamStatus reports the URL of the data being streamed, the state of the streaming data, the number of bytes streamed so far, the total number of bytes in the file to be streamed, and an error check. We'll only be using a few pieces of this information, specifically: state, bytesSoFar and bytesTotal.

In the first line of the streamStatus handler, we check the state of the streaming file. The state parameter reports back a variety of conditions: Connecting, Started, InProgress, Complete, and Error. In this case, I want to simply check to see if the streaming is complete. If it is, I send the movie to frame 2 which contains the four thumbnails. If the state parameter does not equal complete, the status bar and percentage field are updated in the else portion of the if...then statement.

This is done by first setting a variable called percentNow to equal the bytesSoFar divided by the bytesTotal. For example, if the total byte size of a movie is 100,000 bytes and 20,000 bytes have been downloaded so far, the value contained in percentNow would be 0.2 (or 20 percent). Note: the numbers contained in bytesSoFar and bytesTotal are just strings of text to Lingo, it doesn't know we want to use them as numerals in a mathematical expression. Using the float command converts the strings into floating-point numbers, so they can be mathematically divided.

Next, we set another variable called spritePercent to equal the number contained in percentNow (0.2 in our example) multiplied by 150, which is the full width of the red bar (the width it will be at 100% completion). The integer command is used here to convert the resulting calculation to a whole integer, rather than a floating point number. In our perfect little example above (where the percentage equals 0.2) the spritePercent variable would equal a nice round 30, unfortunately in the real world things would not be so clean. If the total file size of the movie was, say, 102,546 bytes, and the bytes so far were 20,354, using these numbers as an example, the resulting number in percentNow would be .1984865, multiply that by 150 and spritePercent equals 29.772975. Using the integer command converts that number to a nice round 30.

Next, the script sets the width of the red bar (sprite 22) to equal the number in spritePercent (in our example 30 pixels). After that, the script multiplies percentNow by 100 (essentially moving the decimal point over two spaces), makes a whole integer out of the number and sticks it, and a percent sign (%), into the field called "percentage." In the example above (where percentNow equals .1984865) the result in the percentage field would be "20%." Her again, the integer command rounds out the number.

Lastly, once all these calculations are done and the changes made, the Stage is redrawn using the updateStage command.

Loading Cast Members on an as Needed Basis

The last technique I want to discuss concerns the idea of downloading media on demand (only as needed). Using this technique, you can set up a situation where you load a portion of the movie to start with and download other portions only as requested by the user. Take a look at this sample, to see what I mean:

PreloadNetThing

source MAC | source WIN

In this movie, only the thumbnail interface was downloaded, and the large images downloaded and displayed only when requested by clicking on the thumbnails. This results in a much smaller file size, than in the previous six examples (30 Kbytes vs 265 Kbytes).

This technique is accomplished with two Lingo commands: preLoadNetThing and netDone. Let's take a look at how these commands work together in downloading the large images.

When any of the thumbnails in this movie are clicked on, it calls an attached sprite script. For example, here is the script for the Yogi thumbnail:



The first thing this script does is set a variable called myFileName to the location of the large file on the Internet. This is done so the URL can be used with the preLoadNetThing command in the next line of the script, and in the enterFrame script discussed next. (Note that the three variables in this script are all global variables and therefore must be declared before they are used. See source code for usage.) In this next line, a variable called myNetID is set to a unique ID for this download. Each download called by preLoadNetThing is automatically assigned a unique ID number by Director (i.e., 1, 2, 3, 4, etc.). This line of the script, then, serves two purposes: First, to put this unique ID number into myNetID; and second, to start the download of the file.

The last line of this script sets another variable called clickFlag to one (1). If you examine the source code for this movie, you'll see that at the start of the movie, clickFlag is set to equal zero (0). This variable is simply used as a flag for the script in the enterFrame handler which I'll explain next.

The EnterFrame Handler

In the Score Script channel of the frame that contains the thumbnail images is the following enterFrame script. This script is executed each time the playback of the movie passes through the frame (roughly 30 times per second depending on the speed of the user's machine).



The first line of this script checks to see if the clickFlag variable equals one (1). If so, it executes the remaining commands; if not, nothing happens. The reason for this flag is that we want the commands to be executed only if the user has clicked on one of the thumbnails. Setting the flag to one when the thumbnail is clicked on, and back to zero when the script is done, ensures that the commands will only be executed when appropriate.

The next line checks to see if the download of the file is complete. This is done with the netDone command. The netDone command returns TRUE if the download identified by the unique ID number contained in myNetID is complete.

If the download is complete, the filename of the Cast member called "placeholder" is replaced with the file name of the URL contained in the variable myFileName (set earlier in the mouseUp handler). The place holder graphic is just a simple, blank graphic positioned on the Stage and turned invisible. This place holder gives the movie a positioning in which to place the incoming graphic. Once the new downloaded graphic is in place, the channel which contains the place holder (sprite 10) is turned visible, making it appear on the Stage.

Lastly, the clickFlag variable is set back to zero.

Using These Techniques in Your Projects

By now you should have a decent understanding of many of the strategies for streaming movies and graphics using Shockwave. Of course, the solution you use will depend solely on the nature of your movies. In general, these are some of the basic techniques that you can use to build upon to solve the unique needs of your projects. Please download and examine the source code for these examples and feel free to use any of the scripts in your projects. If you come up with any clever uses of these techniques, be sure to let me know about them.