Articles Archive
Articles Search
Director Wiki
 

On the Web, Can Anyone Hear You Stream?: Streaming Playback in Shockwave, Part II

March 28, 2001
by Darrel Plant

Last week, we took a look at what streaming means for multimedia files, how file structure affects streaming, and saw a brief glimpse of a four-year-old Shockwave movie that streams both images and sound. (approximately 700k download). The movie consists of a 4x4 grid of images that are animated using up to 102 different pictures as they stream from the server. This week, let's get into the specifics of how to make the media stream.

The Least of Our Problems

Shockwave Audio (SWA) is a variant of the MP3 format. To play a SWA file while it's streaming, the file needs to exist outside of the Shockwave movie DCR, as a linked cast member. Since Shockwave Audio streaming can use either a SWA file (created using Peak on the Mac or the WAV to SWA Xtra on Windows) or an MP3 (created with just about everything that can touch an audio file, these days), your options for creating the streaming sound are varied. The wave99.swa file used in this example was made with Macromedia's old SoundEdit tool.

Using the Insert menu, a Shockwave Audio Media element is inserted into the cast.and given the name soundtrack. At the time it's added to the cast, the audio file isn't associated with a file. It lies dormant until we tell it what to do. That happens in the first frame of the movie in the Script channel:

on exitframe

  if the state of member "soundtrack" = 0 then
    set the URL of member "soundtrack" = "wave99.swa"
    set the preloadtime of member "soundtrack" = 5
    preloadBuffer (member "soundtrack")
  end if

end exitframe

The state property returns several possible values depending on the status of the SWA. Before we do anything else, the state of the SWA is checked to see if it is stopped (i.e. not already streaming).

The URL property of the SWA cast member is assigned a value pointing to a sound file in same directory as the DCR. The cast member is told to wait for 5 seconds of music to download before playing, and then the buffering is initiated with the preloadBuffer command. Fom the fact that this works, we can infer that one of the things that's downloaded in the first portion of the streaming file, along with the scripts and Score information is the data for linked cast members, otherwise this script would generate an error.

The third and final frame of the movie contains a looping script that initiates all of the animation sequences.

global gTransitions, gNumTransitions

on exitFrame
  if the state of member "soundtrack" <> 3 then play (member "soundtrack")
  set whichtrans = random (gnumTransitions)
  set aTrans = getAt (gTransitions, whichtrans)
  case whichtrans of
    1: do aTrans && string (random (16))
    2, 3: do aTrans && string (random (4))
    otherwise
      do aTrans
  end case
  go the frame
end

The script just picks a transition from a pre-established list, adds the necessary parameters where needed, and uses a do statement to execute the specific transition. Before each transition, a check of the audio file's state is made, and if it's not currently playing (state = 3), then the play command is issued. This can (and should) be made much more robust, but as an example of how to get basic audio streaming initiated, it works just fine.

In Transition

The movie creates transitions by using a randomized list of the 102 images in the cast (cast member 1 to 102, for simplicity's sake) to determine what the next image to be displayed will be. The startMovie handler sets up two list that are used in the transitions: gRandom and gTransitions. The gRandom list is simply a jumbled list of numbers from 1 to 102. Each time a cell in the 4x4 grid is changed, the next item from the randomized list is used. The items in the transition list correspond to the names of handlers in the same movie script. If you're wondering why there's one big line of code setting the list with other items added in separate lines, remember that this is from a version of Director where the longest code line allowed was 256 characters!

global gRandom, gIndex, gTransitions, gNumTransitions

on startmovie
  set aList = []
  set gRandom = []
  repeat with i = 1 to 102
    add aList, i
  end repeat
  set stillinlist = 102
  repeat while stillinlist > 0
    set aPos = random (stillinlist)
    set aVal = getAt(aList, aPos)
    deleteAt aList, aPos
    add gRandom, aVal
    set stillinlist = count (aList)
  end repeat
  set gIndex = 0
  repeat with i = 1 to 16
    puppetSprite i, TRUE
  end repeat
  preLoadMember member 1, 102
  set gTransitions = ["modCell", "modRow", "modCol", "modInRing", "modOutRing", "modCorners", "modTop", "modBottom", "modRight", "modLeft", "modAllEdges", "modTopBottom", "modLeftRight", "modSpiralInClock", "modSpiralInCounter", "modSpiralOutClock", "modSpiralOutCounter", "modFlipTop"]
  add gTransitions, "modFlipBottom"
  add gTransitions, "modFlipLeft"
  add gTransitions, "modFlipRight"
  add gTransitions, "modAll"
  set gnumTransitions = count (gTransitions)
end startmovie

Are We Streaming Yet?

So where's all the code needed for streaming? With something as complex as streaming, we've got to start working with it soon or we're going to run out of space, aren't we?

Cast members 101 and 102 are on the Stage in frame 1. They're going to get included in the DCR file ahead of the other media, and will be available from the beginning. The other 100 images will become available during playback as their media is received by the client computer.

All of the transitions use the same routine to change a single cell in the grid. The cells are numbered from 1 to 16, beginning at the top left, running across the row to the right, and so on. The cell numbers correspond to the sprite channels for the images. Each transition just combines a series of single-cell animations in a particular order of cells.

on modRow aRow
  set startRow = (aRow - 1) * 4
  modCell startRow + 1
  modCell startRow + 2
  modCell startRow + 3
  modCell startRow + 4
  updateStage
end modRow

As a sample this is the modRow handler. It uses a parameter (aRow) to determine which of the four rows to modify, then just changes four cells by referring to the correct numbers. The other multi-cell transitions are much the same. Some of the transitions call other, less-complex transitions.

The cell modification handler, cellMod, is where everything happens.

on modCell aCell
  set aIndex = gIndex + 1
  set gIndex = ((aIndex) mod 102)
  repeat while not (the mediaReady of member aIndex)
    set aIndex = gIndex + 1
    set gIndex = ((aIndex) mod 102)
  end repeat
  set the memberNum of sprite aCell = aIndex
  if the percentPlayed of member "soundtrack" > 98 then
    set the memberNum of sprite 6 = 101
    set the memberNum of sprite 7 = 102
  end if
end modCell

This handler examines the randomized list of images (referenced by cast member number), beginning at the position gIndex + 1. It checks to see if the image has been received by the Shockwave Player by examining the mediaReady property. The result is a simple true or false. If the cast member isn't yet available, the next item in the list is examined, until an available cast member is found or the end of the list is reached, in which case the search begins from item 1. Since the playback of the movie begins after cast members 101 and 102 are downloaded, there are always at least two images available. Once an image is found, the global gIndex is set, and the next search begins from that point in the list.

The final portion of this handler waits for the end of the streaming audio cast member, then sets the sprites in the upper center of the Stage to display cast members 101 and 102. Once the song has stopped playing, the script in frame 3 of the Script channel will start it back up again.

If you're wondering what else there is to streaming, you're out of luck, because that's all there is for this movie. What it takes is an understanding of how streaming works, and an application of that knowledge by checking for media that you want to use.

To be sure, there are a lot of caveats to keep in mind about streaming. In a more complex presentation (i.e. almost any other kind of movie) you need to be aware of whether a particular frame is loaded (the frameReady function) or the progress of a streaming operation (the streamStatus handler). It's not automatic, but for most purposes, you're simply determining whether something's available or not.

The trick lies in determining what to do when it's not. In the case of this movie, we just use something else. For a movie where a button would take you to a specific frame, you can modify the button's script to display an alternate graphic until the frame is downloaded, or you could put up an alert when the button is clicked to indicate that the action is invalid, that's really up to you.

The Director 6-compatible source file for this movie is available in both Mac (1.2MB) and Windows (1MB) formats. The download also includes the Shockwave Audio file.

The Shockwave DCR file made from the movie compresses to about 600K, but if you convert all of the images to 24/32-color (using the Transform Bitmap command) and use Director 8's Publish Settings to compress them as JPEGs, the Shockwave movie is significantly smaller. Better yet would be using the original high-color images rather than these dithered 8-bit graphics.

Happy streaming!

Darrel Plant is Technical Editor of Director Online. He is the Publisher at Moshofsky/Plant Creative Services in Portland, Oregon, and the author of or contributor to a number of books on Macromedia Director and Flash, including Special Edition Using Flash 5,, Flash 5 Bible, and Director 8.5 Studio..

Copyright 1997-2024, Director Online. Article content copyright by respective authors.