Accessibility

Flash 8 template: Creating a dynamic playlist for streaming Flash video

Lisa Larson-Kelley

FlashConnections

Note: This article is legacy content. For the latest information, check out the latest version of the article.

As developers, we are often bogged down with mundane tasks such as site maintenance and updates. If we want to pass these tasks on to clients or colleagues who are not tech-savvy, we have to develop sophisticated interfaces to simplify the process for them and to give them easy access to the data. XML gives the power to control content back to the client, freeing us developers to do what we do best.

High-profile sites, most notably Google Video and Amazon.com, are taking advantage of the integration of Flash video with XML. By editing one flat file, you too can update your video content dynamically.

At a MAX conference, Chris Hock and Srinivas Manapragada from Macromedia (now Adobe) presented an XML-based solution for creating content-driven media players called VideoSource. Using their code as a foundation, you will develop your own dynamic video playlist in this article. This XML-based approach is perfect if you ever need to display multiple video clips but you don't want to edit your Flash source code every time you add new video content. As an extra bonus, the application actually generates thumbnail previews on the fly.

Note: This tutorial shows you how to create a dynamic playlist for streaming Flash video. To find out how to build a similar playlist using progressive download Flash video, see my article, Creating a Dynamic Playlist for Progressive Flash Video.

The basic framework of the VideoSource application consists of the following (see Figure 1):

Server/file diagram of the VideoSource application

Figure 1. Server/file diagram of the VideoSource application

You can download all source files for this project.

Requirements

To complete this tutorial you will need to install the following software and files:

Flash Professional 8

Flash Media Server 2

Sample files:

Prerequisite Knowledge

You should be familiar with Flash Professional 8 and understand the basics of delivering video through Flash and Flash Media Server (FMS). You should also have a basic understanding of XML.

Exploring the Video Player Interface

This section explains the structure of the finished player and walks you through creating the interface. You also create a very simple custom component that displays your dynamic thumbnails within the playlist.

The video player is a relatively simple interface, consisting of an embedded video object for playback and a List component for the video (see Figure 2).

Video player interface

Figure 2. Video player interface

(+) View larger

The List component is populated automatically from the contents of your XML file. You can extend the List object class to include an automatically generated thumbnail of the video for each list item. Each item links to the appropriate Flash video (FLV) file, which plays in the FLVPlayback component when clicked.

Follow these steps to create your interface:

  1. Open the Flash Professional 8 authoring environment and create a new Flash file.
  2. Save the file as VideoSource2.fla.
  3. Add an instance of the List component to the Stage and give it the instance name of list.
  4. Open the ActionScript panel and add code to call the external ActionScript file you'll be creating:

    #include "VideoSource.as"
    
  5. Create a new movie clip symbol called VideoHolder.
  6. Within this symbol, add a new instance of the Video component to the Stage.
  7. Click the menu on the Library tab and choose New Video. Name the instance video.
  8. Draw a box with an empty fill and an outside rule of 1 pixel that's the same size as your video component (160 x 120 pixels). Place it directly on top of your video component to give you a nice frame around your thumbnail videos.
  9. Create the VideoThumb component as follows:

    1. Go back up to the main Timeline and create a new symbol called VideoThumb.
    2. Within the symbol, add a stop(); action to the first frame.
    3. Create a new layer and add a blank keyframe at Frame 2. In this frame, add an instance of the VideoHolder movie clip. Call this instance VideoHolder. Change its size to 5 x 5 pixels, at x,y coordinates 0,0.
    4. Go back up to the main Timeline and select VideoThumb in the Library panel. Choose Component Definition from the Library menu. In the Component Definition dialog box, set the AS 2.0 Class to VideoThumb and add the following parameters (see Figure 3):

      • enabled, enabled, true, Boolean
      • visible, visible, true, Boolean
      • minHeight, minHeight, 0, Number
      • minWidth, minWidth, 0, Number

      Make sure that both the "Parameters Are Locked in Instances" and the "Display in Components Panel" options are checked.

      Component Definition dialog box

      Figure 3. Component Definition dialog box

  10. Save the file as VideoSource2.fla.

You'll need to wait until after you write the VideoSource.as file (see Step 3 in the section "Writing the Client-Side ActionScript") to publish the SWF file, so keep the interface file handy.

That's all there is to the interface. Provided that you don't decide to change your layout, you won't need to edit the file again. You just make all future updates in your XML file. It's truly a thing of beauty.

The next section shows you how to set up the application on your server.

Setting Up Flash Media Server

This article assumes that you are running Flash Media Server locally, but the application setup would be the same if you were using a remote server:

  1. Create a folder under the applications folder in Flash Media Server called VideoSource.
  2. Create a streams folder inside VideoSource.
  3. Create a _definst_ folder inside the streams folder.
  4. Place the Flash video files that you wish to appear in your playlist in this _definst_ folder.

That's all the setup required on the server side.

In a bit, you'll construct the VideoSource.as ActionScript code. However, let's first take a look at the XML file you will use to dynamically build your video playlist.

Understanding the XML Data Source

In this section, I explain the structure of the sample XML data file, playlist-demo-1.xml, which is included in the sample file ZIP for this tutorial.

To add new videos to your playlist dynamically, simply edit this file:

<xml>
   <listitem name="Wind Sculptures" url="rtmp://localhost/videosource/">
      <stream name="wind" start="0" len="-1"/>
   </listitem>

   <listitem name="The Trike" url="rtmp://localhost/videosource/">
      <stream name="trike_final" start="0" len="-1"/>
   </listitem>
      <listitem name="Fluffy Hammer" url="rtmp://localhost/videosource/">
      <stream name="fluff_hammer" start="0" len="-1"/>
   </listitem>

   <listitem name="Fluffy Crash" url="rtmp://localhost/videosource/">
      <stream name="fluffy_crash" start="0" len="-1"/>
   </listitem>
   <listitem name="SuperSkate" url="rtmp://localhost/videosource/">
      <stream name="discodance" start="0" len="-1"/>
   </listitem>
   <listitem name="The Fish" url="rtmp://localhost/videosource/">
      <stream name="fish" start="0" len="-1"/>
   </listitem>
      <menu>
      <listitem name="Wind Sculptures"/>
      <listitem name="The Trike"/>
      <listitem name="Fluffy Hammer"/>
      <listitem name="Fluffy Crash"/>
      <listitem name="SuperSkate"/>
      <listitem name="The Fish"/>
   </menu>
</xml>

Notice that the file has a very basic XML structure, holding two main things:

The url attribute must point to your server running Flash Media Server. (For the purpose of this article, I assume you are doing so locally.) To point to your own FLV files, change the stream name to your FLV filename (omitting the .flv extension). These filenames should correspond to those you placed in the "streams" folder on the FMS server in the previous section. Just remember to leave off the .flv extension in the XML file, as shown in the example.

OK, ready for the fun part? The next section gets into the meat of the application—the client-side ActionScript.

Writing the Client-Side ActionScript

This section explains how to parse the XML document and create the dynamic playlist.

As I mentioned, all the ActionScript you are using for this project is contained in external files. Begin by creating an ActionScript file called VideoSource.as in Dreamweaver or in your favorite text editor.

Step 1: Format the Playlist Box

Assign values to the rowHeight and Selectable list properties, and then call the function VideoThumb to create the actual thumbnails:

list.rowHeight = 70;
list.cellRenderer = "VideoThumb";
list.selectable = true;

I address this function later in detail in the next section, "Generating Dynamic Thumbnails."

Step 2: Handle the Playlist Selections

To detect when clips are selected from the playlist, you need a listener object. Create a new empty listener object called listListener:

//create new empty listener object
listListener = {};

Now create a function to control what happens when an item in the playlist is selected:

listListener.change = function( evtobj ) {
var nav = list.dataProvider[list.selectedIndex];
   var reset = true;
   for ( var i = 0; i < nav.childNodes.length; i++ ) {
      var stream = nav.childNodes[i];
      if ( stream.nodeName == "stream" ) {
         attachMovie("FLVPlayback", "my_FLVPlybk", 10, {width:320, 
height:240, x:90, y:100});
         
         //center the FLVPlayback component when FLV is ready to play
         var listenerObject:Object = new Object();
         listenerObject.resize = function(eventObject:Object):Void {
            //center video in playback area
            newx = (460 - my_FLVPlybk.preferredWidth)/2;
            newy = (470 - my_FLVPlybk.preferredHeight)/2;
            my_FLVPlybk._x = newx;
            my_FLVPlybk._y = newy;
         };
         my_FLVPlybk.addEventListener("resize", listenerObject);    
         listenerObject.ready = function(eventObject:Object):Void {
              my_FLVPlybk.setSize(250, 350);
         };

         my_FLVPlybk.skin = "SteelExternalAll.swf";
         my_FLVPlybk.clear();
         my_FLVPlybk.contentPath = nav.attributes.url + "/_definst_/" + stream.attributes.name+".flv";
         my_FLVPlybk.autoSize = true;
         //trace(my_FLVPlybk.contentPath);
         reset = false;
      }
   }
}

This function accomplishes the following:

  1. Creates the nav variable, which holds the XML data for the selected list item, providing access to all attributes of the selected item.
  2. Dynamically creates an instance of the FLVPlayback component, called FLVPlybk.
  3. Walks through the XML for the chosen item and assigns its URL to the contentPath property of the FLVPlayback component and begins playback.
  4. Creates a listener that detects when the FLV is ready to play, and then recenters the FLVPlayback component on the Stage.
  5. Creates the reset variable and initially sets its value to true. This variable will be used in the ns.play method three lines below. This causes the existing NetStream instance to be flushed, stopping any video currently being played and immediately playing the newly selected video. The reset variable is then set to false for the rest of the files in the playlist.

If nodeName is stream, the clip is played. To implement the listListener function, you must associate it with the playlist. Then when it triggers, the listListener function is called, repopulating the list:

//Add an event listener on the list, when it triggers, 
//run the listListener function to repopulate the list
list.addEventListener("change", listListener);

Step 3: Parse the XML File and Populate the Playlist

Now it's time to dive into the lengthiest function. This one accomplishes a lot:

  1. Loads the XML file.
  2. Parses the XML file.
  3. Builds the playlist.

I'll break it up and explain what happens in each operation.

Create a new XML object, called xmllist. Add the standard ignoreWhite=true command to strip out extra white space from the XML file. Finally, load the XML file into the XML object:

var xmllist = new XML();        //setup a variable to hold the XML
   xmllist.ignoreWhite = true;
   xmllist.load( "playlist-demo-1.xml" );    //load the XML file

Congratulations, you now have your XML data in Flash. But that's just the beginning.

You need to parse that data into a format that Flash can use to populate the playlist. The following function is called when the XML has been successfully loaded:

xmllist.onLoad = function( status )  {
   if ( !status )
      trace( status );
   var entries = this.childNodes[0];
   var playlists = {};
   var nav = [];

The code passes status to this function and traces it for debugging purposes. Create three variables to hold the XML data for each video clip:

Next, create a for loop that steps through the XML and builds the data arrays:

for ( var i = 0; i < entries.childNodes.length; i++ ) {
      var entry = entries.childNodes[i];
      if ( entry.nodeName == "listitem" )
         //builds array of video clip names
         playlists[entry.attributes.name] = entry;
      else if ( entry.nodeName == "menu" ) {
         //builds array of available videos
         for ( var j = 0; j < entry.childNodes.length; j++ )
         nav[j] = playlists[entry.childNodes[j].attributes.name];
      }//end else if
   }//end for

As the loop steps through the XML, it builds an array of video clip names (playlists) and an array of available videos (nav). The array of videos is then sent to your List component for display purposes:

//sends the array of videos to the listbox UI
   list.dataProvider = nav;
}//end xml onload

Save this file as VideoSource.as in the same folder as VideoSource2.fla. Also place a copy in your application's web-accessible directory.

You've now successfully imported your XML data, built the playlist, and implemented the clip selection function. The next operation tackles creating dynamic thumbnails.

Generating Dynamic Thumbnails

The playlist so far is pretty snappy, but let's not stop there. Jazz it up even more with thumbnails generated on the fly.

The purpose of this external ActionScript file (videothumb.as) is to create thumbnails dynamically of each video in your list.

Because this article focuses mostly on using XML to deliver video dynamically, I won't go into too much detail about creating and extending the List component class. In this section, I include all the code you need to extend the normal List component to display the thumbnails and provide a brief description of how it works. If you'd like to find out more about creating and extending classes, read Exploring Version 2 of the Flash MX 2004 Component Architecture by Waleed Anbar.

This application uses the List component for displaying the playlist. In this bit of ActionScript, a class is created that extends mx.core.Uicomponent to include a thumbnail. Here is the code in its entirety:

class VideoThumb extends mx.core.UIComponent
{
   static var symbolName = "VideoThumb";
   var label : Object;      // the new text label we'll use
   var listOwner : Object; // reference to the tree - supplied by the tree
   var thumb;
   var nc;               // NetConnection
   var ns;               // NetStream
   var streamurl;
   
   function VideoThumb()         //define constructor
   {
      // nothing needed - we're extending v2;
   }

   function init()            //initialize
   {
      // nothing needed - we don't have any instance variables to initialize
   }

   function createChildren(Void) : Void
   {
      var v = this.attachMovie( "VideoHolder", "thumb", 0 );
      v._width = 80;
      v._height = 60;
      v.styleName = listOwner;

      var c = createLabel("label", 1);
      
      c.styleName = listOwner;
      c.selectable = false;
   }
   // pass all sizing from the tree to the cell
   function size(Void) : Void
   {
      label.setSize(label.getPreferredWidth(),label.getPreferredHeight());
      label._x = thumb._width + 10;
      label._y = thumb._height/2 - label._height/2;
   }
   function setValue(str : String, item, sel)
   {
      _visible = item != undefined;
      if ( !_visible )
         return;
      
      label.setValue( item.attributes.name );
      // Thumbnail is picked up as the first frame of the playlist
      var url = item.attributes.url;
      var stream = item.attributes.thumb;
      var start = item.attributes.thumbpos;
      
      // If explicit thumb is not specified in XML
      // use the first frame of the video
      if ( stream == undefined ) {
         stream = item.childNodes[0].attributes.name;
         start = item.childNodes[0].attributes.start;
      }
      
      // Give up if we still don't have valid thumb info
      if ( stream == undefined )
         return;

      // Render the thumbnail only if necessary
      if ( streamurl == url + "/" + stream )
         return;
      
      streamurl = url + "/" + stream;
      
//get first frame of video
      nc = new NetConnection();
      nc.connect( url );
      
      ns = new NetStream(nc);
      ns.onStatus = function(info) {
         // if video has stopped playing, reset nc and ns
         if ( info.code == "NetStream.Play.Stop" ) {
            nc = null;
            ns = null;
         }
      }
      thumb.video.attachVideo(ns);
      ns.connect();
      //grab the first frame
//begin at the specified start point, and play one frame
      ns.play( stream, start, 0 );
   }
   .
   function getPreferredHeight()
   {
      return 60;
   }

   function getPreferredWidth()
   {
      return label.getPreferredWidth();
   }
}

The basic purpose of VideoThumb.as is to specify the appearance and contents of the ListBox and create a thumbnail preview of the video file. The script performs these specific operations:

Save a copy of VideoThumb.as in the same folder as VideoSource.as and VideoSource2.fla. With all your ActionScript now in place, you can go back to VideoSource2.fla and publish the SWF file. Place a copy of your SWF file into your web-accessible directory.

The last step places your files on the server so you can watch VideoSource in action.

Testing the Application

In the beginning of this tutorial, you copied your FLV files to your Flash Media Server installation. You will now need to place your ActionScript and interface files in your web-accessible folder for testing.

These three files should be in your web-accessible folder on your server or localhost:

Because you already copied your Flash video files to FMS earlier in the article, you are ready to test your application. Using your favorite browser, navigate to VideoSource2.swf to test your playlist, now magically complete with thumbnails. Figure 4 shows the live application in action, loading Flash video files and generating thumbnails.

Final live SWF file in action

Figure 4. Final live SWF file in action

Creating Variations on a Theme

You've explored simple video clip playlist navigation using XML, but you could extend this basic framework to other applications as well:

Where to Go from Here

You have created a powerful XML playlist application that you can easily update, reuse, and reskin to your heart's content. Some very useful features that you could add include bandwidth detection, cue points, and video preloaders. Take this basic framework and be creative!

The following resources can help you get up to speed with Flash video and Flash Media Server:

About the author

Lisa Larson-Kelley began her career in print design, but was soon lured to digital media by a little application called Flash 4. In addition to hands-on development projects, she enjoys writing and teaching, with a knack for breaking down complex concepts and making them accessible. She has authored technical articles for the Adobe Developer Connection, and editorials and features for StreamingMedia.com; and coauthored the book, Flash Video for Professionals (Wiley, 2007). Lisa has also presented at numerous industry conferences around the world and is an active member of the FlashCodersNY user group. A graduate of Wayne State University in Michigan with a BFA in Graphic Design, Lisa received a New Media Certification from the Rhode Island School of Design/Fraunhofer CRCG in 2003. After spending two years as a freelance designer/developer, she went on to become the technical director and cofounder of go:toGroup, a new-media firm based in New York City specializing in Flash video applications. She now consults, teaches, and develops iFoxCam, a consumer video surveillance product using Flash Media Server. While with go:toGroup, Lisa worked with many video-centric startups as well as companies such as Adobe, Microsoft, and L'Oréal. She shares news and musings about Flash video, web development and life in the big city on her blog, flashconnections.com.