How to Build a Flash Video (FLV) Progress Bar (Part 1)

ActionScript 2.0

Following on the heels, at least conceptually, of “How to Control Video (FLV) without a Component” here’s a quick look at how to indicate the progression of an FLV by way of a custom made progress bar (thanks for the suggestion, Rick!).  In a follow-up article, I’ll show how to make the progress bar interactive by having the draggable knob seek to keyframes in the FLV.  It turns out that much of the code for this first part derives from “How to Determine the Completion of a Flash Video (FLV) File,” which shows how to determine video length, with and without the use of Components, in ActionScript 2.0.  In this article, we’ll be going the non-Component route, because FLVPlayback already has a progress bar.  Before we delve into the code, we need to prepare two small movie clips.  

Creating the progress bar itself

The artwork can get as pretty as you like, but for illustrative purposes, all you need for the progress bar’s track is a rectangle.  Mine happens to be 12 x 180.  Draw the rectangle and convert it to a movie clip, making sure the registration point is in the upper left corner.  Give it the instance name track.  For the knob, draw a smallish circle or almond shape.  My circle is 15 x 15.  Convert it to a movie clip, making sure the registration point is in the center, and give it the instance name knob.  These can be on separate layers or the same, it doesn’t matter; just make sure the knob is above the track and the registration points are set as described.  Position the knob at the left edge of the track.

I’ve you’ve been reading the other video-related articles on this blog, you’ll already be familiar with the non-Component display of FLVs.  If not, you may want to give a quick read through the previous material.  In addition to the two movie clips that comprise the progress bar, you’ll also need a Video object on the Stage.  In this example, we’ll use the instance name videoPlayer.

An answer, short and sweet

Here’s the ActionScript, and we’ll step through it afterward.

var duration:Number = 0;
var ratio:Number = 0;
var id:Number = 0;

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
videoPlayer.attachVideo(ns);
ns.play("externalVideo.flv");

ns.onMetaData = function(evt:Object):Void {
  duration = evt.duration;
  ratio = track._width / duration;
  id = setInterval(
    function ():Void {
      knob._x = track._x + ns.time * ratio;
    }, 50
  );
};

ns.onStatus = function(evt:Object):Void {
  if (this.time > 0 && this.time >= (duration - 0.5)) {
    trace("Video complete");
    clearInterval(id);
    delete this.onStatus;
  }
};

How it works

The first three variables, duration, ratio, and id, prepare the way for three values used later in the code.  The duration value is later determined in a NetStream.onMetaData event handler as described in the article on determining video length.  The ratio value — this is the new part — is also set in the same event handler.  id is used to track a setInterval() timer loop, which is also introduced in the event handler.  The zeroes, for now, simply give these numbers a default value.

The next block (five lines beginning with var nc) prepares the Video object for play and loads an external FLV file.  This block of code was originally explained in “How to Load External Video (FLV).”

Now comes the brains of it.

ns.onMetaData = function(evt:Object):Void {
  duration = evt.duration;
  ratio = track._width / duration;
  id = setInterval(
    function ():Void {
      knob._x = track._x + ns.time * ratio;
    }, 50
  );
};

As recounted elsewhere on this blog, the onMetaData event is dispatched as an FLV file begins to play.  Depending on how a video file is converted to FLV, it may be given a handful of extra descriptive information, including the video’s duration.  In the above code, this information gets a free ride in via the arbitrarily named parameter evt.  This incoming object carries with it a duration property that is:  a) passed to the previously declared duration variable and b) used to determine a ratio between the width of the track movie clip and the length of the video.  Thanks to this ratio, the knob movie clip can be sent to any location between the left and right edges of the track movie clip in correspondence with how much of the video has been played.  Let’s see how that works.

The id variable is simply a value that keeps track of setInterval() loops.  The setInterval() function returns a value, much like the Math.round() method.  With Math.round(), you feed in a number, and the value you get back is the nearest integer.  With setInterval(), you feed in a) a function to perform and b) in interval in which to perform it.  The function gives back a number that says, “Okay, this is the identifier for the particular loop you just started.”  And what function have we fed in?  In this case, we’re setting the MovieClip._x property of the knob instance to the horizontal position of track plus the result of the video’s current location (the NetStream.time property of the ns instance) multiplied by the ratio variable.  This is performed every 50 milliseconds once the video begins.

To save on processor cycles, the looping should stop when the video ends, so the final block of code uses clearInterval(), with id as a parameter, to do just that.  This happens in response to a NetStream.onStatus event that checks if the video’s progression is both past zero and equal to or greater than a half second shy of the duration value.

Leave a Reply