| Video and Media Components 3 |
| notes for Flash 7 Pro only |
This is a continuation from Video and Media Components, part 1 and part 2
In Video and Media Components, part 3, we look at using the Media Components to load and control playback of FLV (and MP3) files.
For greater control over the Media Components than can be provided by the Component Inspector or Properties Inspector alone, ActionScript and to some degree Behaviors can prove invaluable.
Actions
Display
Controller
There is no specific requirement for the components to be on the same layer, or on different layers.
With the MediaPlayback component, the control and display elements already communicate with each other. With the separate MediaDisplay and MediaController components, we need to make them aware of one another. This is a piece of cake with the Behaviors panel.
You only need to perform one of the two following steps:


Don't forget: You only need to associate one of these two components with the other; you do not perform both associations.

For this experiment, it can be any FLV you have created or have available
Reminder: If you use the Flash Video Exporter, the video length is included in the exported FLV's metadata, and is automatically used by the Media Components, so that you do not need to enter the Video Length value by hand in the Component Inspector. The Flash Video Exporter ships with Flash MX 2004 Professional, and installs as part of a system-wide codec available to certain video editing tools: QuickTime Pro (Windows and Macintosh), After Effects (Windows and Macintosh), Avid Xpress DV (Windows and Macintosh), Discreet Cleaner (Windows and Macintosh), FinalCut Pro (Macintosh), Anystream Agility (Windows).
The external FLV is loaded into the MediaDisplay and begins playing; the Controller reflects and controls the display. By associating the two media components, and configuring just the MediaDisplay component, the two components now work together: the information used to configure the MediaDisplay instance is used by the MediaController.

The options are either pause or play (display the pause button or the play button)
The options are either default or none (default displays the chrome around the controls, while none removes the chrome)
The options are auto (display controls when user cursors over the controller); on (controls always visible); off (controls always hidden)
The options are true or false (true displays the controls horizontally)
The external FLV is loaded into the MediaDisplay and begins playing ... but when we click on the play button, the pause button appears and the FLV continue to play, even though we set the Controller's activePlayControl parameter to play. This is because the activePlayControl determines the visual look of the pause/play button, and has nothing to do with the actual control of playback of the FLV.
Notice that the FLV is now paused at the beginning, and the Controller is displaying the Play buttton. Clicking on the Play button starts the FLV.
The activePlayControl setting on the Controller is NOT controlling the playback ... it is establishing the visual look of the combined pause/play button. This means that the Automatically Play setting of the Display actually controls the initial PLAYBACK of an FLV. The activePlayControl setting of the Controller actually only controls the initial LOOK of the pause/play button on the controller.
Any video element, whether an embedded video or an FLV streamed through an instance of the empty embedded video or MediaDisplay objects, is like any other complex (non-shape) graphical element in Flash. This means that any design technique can be applied successfully to the MediaDisplay or embedded video instances.
You should see a round-cornered video stream, instead of a purely-rectangular stream
This is to remind you that you can treat the Display component (or embedded video instance) as you would any other visual element ...
Feel free to use your own values for the drop shadow ... these are just suggestions ...
This is meant to suggest that you can use the video stream as just another graphical element in a project ...
This brief detour was meant to squeeze in an example of working with the two individual media components.
Each of the Media Components has it's own collection of Events, Methods, and Properties; some of these are shared with other Media Components, some are unique to a specific component. All of the parameters that can be set in the Property or Component Inspectors can be set with ActionScript, sometimes with greater finesse. Some parameters cannot be set at all without the use of ActionScript.
What follows is an introduction to some of the events, methods and properties of the Media Components.
Actions
Playback
With the Property Inspector, we can set the X and Y location of Media Component, as well as set the Horizontal and Vertical size without scaling (stretching). To do this with ActionScript:
// Property Inspector: size and location
my_playback.setSize(336 ,326);
my_playback.move(107 ,70);
Using the same name DOT property/method notation that is ubiquitous in current scripting and programming languages, we are accessing methods of the UIComponent class, from which v2 components are derived (meaning that the v2 components inherit common events/methods/properties). The setSize(width, height) method changes the size of the component to the specified width and height, without scaling (stretching) the component. The move(x, y) method moves the instance (based upon it's registration mark) to the specified horizontal and vertical position.
The Playback component should be resized (to a size which will contain a 320 x 240 FLV), and moved to where the video display area is roughly centered on a 550 x 400 stage (the controller part will be below that, and when extended, will be closer to the bottom of the stage than the top of the display area is to the top of the stage).
It is worth noting that the MediaPlayback component itself adds about 70 K to the overall file size of the project. Check the size of the flv_video_as.swf file at this point.
In this next section, we will use ActionScript to duplicate these settings in the Component Inspector:

The ActionScript statements which follow will be applied to frame 1 of the Actions layer
// Component Inspector
my_playback.autoPlay = true;
The autoPlay property can be assigned one of two possible Boolean values: true (the default) or false ... this must be set before setMedia() to be effective
// Component Inspector
my_playback.autoPlay = true;
my_playback.setMedia("step1.flv" , "FLV");
The setMedia(URL, filetype) has two string arguments: URL, which is a string representing the URL of the external FLV (or MP3) file; and filetype, which is one of two strings: "FLV" or "MP3".
We previously exported this step1.flv file in part 2 of this tutorial ... make sure that that file is copied to the folder containing this FLA, or the folder that the SWF of this project will be exported to, if it is not there already. Otherwise, change (add a path to) the URL to reflect the location of the FLV.
// Component Inspector
my_playback.autoPlay = true;
my_playback.setMedia("step1.flv" , "FLV");
my_playback.totalTime = 6.166;
The totalTime property (Video Length fields in the Component Inspector) is assigned a numerical value representing the number of seconds (video length) of the FLV. If an FLV runs 2 minutes, 12 seconds, 15 milliseconds, then you would assign the value 132.15 (2 x 60 = 120 seconds; 120 + 12 = 132 seconds; 132 seconds + 15 milliseconds (.15 seconds) = 132.15 seconds).
We previously exported this step1.flv file in part 2 of this tutorial ... make sure that that file is copied to the folder containing this FLA, or the folder that the SWF of this project will be exported to, if it is not there already. Otherwise, change (add a path to) the URL to reflect the location of the FLV.
This is one of the only cases I have ever come across where a control is exposed which cannot be accessed by ActionScript. According to the Help panel:
• With the file type set to FLV, you'll notice a Milliseconds option and (if Milliseconds is unselected) a Frames Per Second (FPS) pop-up menu. When the Milliseconds option is selected, the FPS control is not visible. In this mode, the time displayed in the playbar at runtime is formatted as HH:MM:SS.mmm (H = hours, M = minutes, S = seconds, m = milliseconds), and cue points are set in seconds. When Milliseconds is unselected, the FPS control is enabled and the playbar time is formatted as HH:MM:SS.FF (F = frames per second), while cue points are set in frames.
Note: You can only set the FPS property by using the Component Inspector panel. Setting an fps value by using ActionScript has no effect and will be ignored.
So if you want the frames per second to be displayed in the milliseconds field, you will have to set it in the Component Inspector by deselecting the Milliseconds checkbox.
// Component Inspector
my_playback.autoPlay = true;
my_playback.setMedia("step1.flv" , "FLV");
my_playback.totalTime = 6.166;
my_playback.autoSize = true;
The autoSize property can be assigned one of two possible Boolean values: true (the default) or false
When set to true (the default value), Flash will display the media at its preferred size unless the playback component media area is smaller than the preferred size. If this is the case, Flash will shrink the media to fit inside the instance and respect the aspect ratio. If the preferred size is smaller than the component media area of the instance, part of the media area will go unused.
Selecting the Use Preferred Media Size checkbox in the Component Inspector is the same as assigning true to the autoSize property in ActionScript
// Component Inspector
my_playback.autoPlay = true;
my_playback.setMedia("step1.flv" , "FLV");
my_playback.totalTime = 6.166;
my_playback.autoSize = false;
my_playback.aspectRatio = true;
The aspectRatio property can be assigned one of two possible Boolean values: true (the default) or false.
If the autoSize property is set to true (if the Use Preferred Media Size checkbox is selected), then the aspectRatio property (Respect Aspect Ratio control) is meaningless, and is grayed out in the Component Inspector. If autoSize is set to false (if the Use Preferred Media Size checkbox is de-selected), then the aspectRatio property (Respect Aspect Ratio control) makes sense. With autoSize set to false, the FLV will be scaled to the size of the display area of the component.
Assigning the value true to the aspectRatio property will cause the aspect ratio of the FLV to be honored, and instead of filling the component's media display area, it will expand it only to the limiting dimension.
// Component Inspector my_playback.autoPlay = true; my_playback.setMedia("step1.flv" , "FLV"); my_playback.totalTime = 6.166; my_playback.autoSize = true; // my_playback.aspectRatio = true; my_playback.controlPlacement = "bottom";
The controlPlacement property can be assigned one of four possible strings: "bottom", "left", "top", and "right". The default is "bottom".
This determines the placement and orientation of the controller portion of the MediaPlayback component.
// Component Inspector
my_playback.autoPlay = true;
my_playback.setMedia("step1.flv" , "FLV");
my_playback.totalTime = 6.166;
my_playback.autoSize = true;
// my_playback.aspectRatio = true;
my_playback.controlPlacement = "bottom";
my_playback.controllerPolicy = "on";
The controllerPolicy property can be assigned one of three possible strings: "auto", "on", and "off". The default is "auto".
This determines the visibility of the controller portion of the MediaPlayback component; "on" makes the controller portion always visible; "off" makes it always tucked away (not visible); and "auto" hides and reveals it, based upon the position of the cursor hovering over the controller area.
// Component Inspector
my_playback.autoPlay = true;
my_playback.totalTime = 6.166;
my_playback.autoSize = true;
// my_playback.aspectRatio = true;
my_playback.controlPlacement = "bottom";
my_playback.controllerPolicy = "on";
my_playback.setMedia("step1.flv" , "FLV");
In limited testing, the only order of statements that seemed to matter was that the autoPlay property be set before the setMedia() method was called. While it might not matter with any of the other properties.
If you run into problems where it seems that one or more of the properties is not being respected, you might try issuing the setMedia() method after all of the property settings.
// Property Inspector: size and location my_playback.setSize(336 ,326); my_playback.move(107 ,70); // Component Inspector my_playback.autoPlay = true; my_playback.setMedia("step1.flv" , "FLV"); my_playback.totalTime = 6.166; my_playback.autoSize = true; // my_playback.aspectRatio = true; my_playback.controlPlacement = "bottom"; my_playback.controllerPolicy = "on";
Everything that was previously accomplished using the Property Inspector and Component Inspector has been replicated using ActionScript.
When this movie begins playing, the external file step1.flv (located in the same folder as the flv_video_as.swf) is loaded. The loading process is correctly displayed in the controller portion. The playback process begins and is also accurately displayed in the controller area.
The final frame 1 ActionScript:
// Property Inspector: size and location my_playback.setSize(336 ,326); my_playback.move(107 ,70); // Component Inspector my_playback.autoPlay = true; my_playback.setMedia("step1.flv" , "FLV"); my_playback.totalTime = 6.166; my_playback.autoSize = true; // my_playback.aspectRatio = true; my_playback.controlPlacement = "bottom"; my_playback.controllerPolicy = "on";
While in most cases the Component Inspector and Property Inspector are far easier to work with, there may be times where a design or requirement may lead to the need to dynamically assign one or more values while the movie is running.
It is important to the functioning of the Media Components that you supply the correct FLV video length. If the FLV is created using the Flash Video Exporter, then the video length is encoded in the file's metadata. However, when exporting the FLV from within Flash itself, that metadata is not included. That means you need to determine it, and enter it by hand in the Component Inspector, or assign that value to the totalTime property by means of ActionScript.
What we will be working on next is a little Flash utility that will ultimately display the video length of an external FLV.
Actions
Dynamic Text
Playback
With the Text tool selected, and with the Text Type set to Dynamic in the Property Inspector:
Note: This will be dependent upon your layout. If the url_txt and video_length_txt fields are side by side, establish the length of the url_txt field so that it's left edge is aligned to the same horizontal position as the left edge of the my_playback instance
You can either do this manually by dragging and using the Property Inspector, or by means of ActionScript:
// Property Inspector: size and location
my_playback.setSize(336 ,326);
my_playback.move(107 ,70);
The size and placement aren't critical, just as long as you can see the dynamic text fields
You can either do this manually by selecting (enabling) the Automatically Play and Use Preferred Media Size checkboxes in the Component Inspector, or by means of ActionScript:
my_playback.autoPlay = true; // must be set before setMedia() my_playback.autoSize = true; // Use Preferred Media Size
We are going to be specifying the FLV dynamically at runtime, so we won't be using the Component Inspector.
my_playback.autoPlay = true; // must be set before setMedia() my_playback.autoSize = true; // Use Preferred Media Size url = "step2.flv"; // temporary, for intial testing my_playback.setMedia(url, "FLV"); // expected argument as query string
The MediaPlayback.setMedia() method loads the specified URL and tells the component that it is loading either an FLV or an MP3.
The url = "step2.flv"; statement is temporary, to help with the initial testing of this project ... it will be deleted once we have everything working.
my_playback.autoPlay = true; // must be set before setMedia() my_playback.autoSize = true; // Use Preferred Media Size url = "step2.flv"; // temporary, for intial testing my_playback.setMedia(url, "FLV"); // expected argument as query string url_txt.text = url + ":"; // display file name
This is a simple string assignment to the text property of the dynamic text field url_txt
Make sure that the file step2.flv is in the same folder as the test SWF, flv_video_length.swf
When this movie plays, the specified external FLV should be automatically loaded, and should begin playing.
on(change) {
trace(this.playheadTime); // display FLV's current time
}
The change event is constantly triggered while the media is playing. The this keyword forces the reference to the instance upon which this ActionScript is being applied (in this context). The MediaPlayback.playheadTime is a property that keeps track of where the media's playhead is currently at (as in: the media's elapsed time).
As the FLV is playing, the elapsed time is sent to the Output window.
on(change) {
// trace(this.playheadTime); // display FLV's current time
_parent.video_length_txt.text = this.playheadTime;
}
This sends the value of the MediaPlayback.playheadTime property to the Dynamic Text field whose instance name is video_length_txt. We prefix the name with the addressing information _parent, because components are like movie clips: if you need to target something outside of the component/clip, you first must leave the component/clip's timeline. To send a string of information (the numerical value is automatically converted to a string in ActionScript 1.0) to a Dynamic Text field, we send it to the Dynamic Text field's text property.
trace() statement by putting two forward slashes in front of it As the FLV is playing, the elapsed time (current playback time) is sent to the Dynamic Text field (instance name: video_length_txt). This means we can find out the video length outside of the Flash authoring system (the only place the Output window is available).
Applying ActionScript directly to instances is an efficient way to apply script. Unfortunately, that ease comes at a very high price: the difficulty of maintaining the project. Once out of the classroom, this becomes a very big concern.
While it takes extra work up front, planning for future maintenance or modification is a good practice to undertake. Let's take the functionality of the on(change) event handler applied to the my_playback instance, and move it to the main timeline:
/*
on(change) {
// trace(this.playheadTime); // display FLV's current time
_parent.video_length_txt.text = this.playheadTime;
}
*/
A forward slash-asterisk combination begins a block (multi-line) comment. An asterisk-forward slash ends a block comment. All script in between will not be acted upon and is treated as a comment. It is a non-destructive way of getting rid of things.
Listeners are a more object-oriented way of applying event handlers to instances. In this case, "object-oriented" is going to translate into "easier to maintain" (which is an inherent aspect of this system).
Constructing a listener requires you to follow the same three-step process:
In the steps below, the remaining ActionScript statements will be applied to frame 1 of the Actions layer
myPlaybackListener = new Object(); // 1) establish generic Object
new is the constructor; Object is the name of the class; () completes the contructor function; myPlaybackListener is the instance name (that we just made up) of the instantiated Object
myPlaybackListener = new Object(); // 1) establish generic Object // 2) establish listener callback function (event handler) myPlaybackListener.change = function(eventObject){ // steps to take }
Much like a callback function for remotely scripting a button action with onRelease, this establishes a function which will be called when the change event is "heard". This function will then execute whatever actions (ActionScript statements) you wish to take place when the specified event is heard.
function is the keyword for declaring a new function/sequence of steps; eventObject is the placeholder name for the object that gets passed to the listener (is broadcast from the component in this case); { } the open and close braces/curly brackets delimit the beginning and ending of the ActionScript statements that make up the steps to take when the event is heard; myPlaybackListener is the instance name of the generic object which will be listening for events to be broadcast; change is the event which is being listened for.
Components and other objects are capable of producing more than one event ... all you have to do is think of a button, which can produce onPress, onRelease, onRollOver and other events.
myPlaybackListener = new Object(); // 1) establish generic Object // 2) establish listener callback function (event handler) myPlaybackListener.change = function(eventObject){ // steps to take } // 3) associate event broadcaster with listener my_playback.addEventListener("change", myPlaybackListener);
In this case, the broadcaster is the MediaPlayback component, specifically the one with the instance name my_playback. We are using the addEventListener() method to do the association. The addEventListener(event, listenerObject) method takes two arguments: a string representing the event to listen for, and the instance name of the listener. In this case, we are listening for the "change" event, and the listenerObject is: myPlaybackListener.
Right now, the listener callback function isn't doing anything.
eventObject:
When an event is broadcast from a component, the Flash system sends along a complex identifier. This complex identifier contains two pieces of information: who is sending/broadcasting the event, and what event is being broadcast.
This complex identifier is received by the listener callback function. When we want to "catch" or receive a value in a function, we do so by supplying a placeholder name within the function declaration's open and close parentheses.
When we create a function - as we are here - we simply create a name as part of our name/value associations ... for all intents and purposes, this placeholder is just a variable which only exists while the function is executing ... this placeholder variable does not exist outside of the function declaration.
The eventObject placeholder variable (the most accurate terminology is "parameter") will receive a complex piece of information. In ActionScript terms, complex data is represented as arrays, or objects which contain a number of properties. There is no ActionScript keyword named "eventObject" ... it is, in essence, a variable name we just made up when we were creating the callback function. The eventObject will store the complex piece of information, and contains two properties: type, which is a string indicating the name of the event; and target, which is a reference to the component instance broadcasting the event.
Before we attempt to display the playheadTime, let's first make sure that we are receiving the information correctly:
myPlaybackListener = new Object(); // 1) establish generic Object // 2) establish listener callback function (event handler) myPlaybackListener.change = function(eventObject){ trace(eventObject.target); // reference to source/broadcaster trace(eventObject.type); // type of event } // 3) associate event broadcaster with listener my_playback.addEventListener("change", myPlaybackListener);
Here we are sending the two properties of the eventObject to the Output window: target is the property which stores a reference to the component instance broadcasting the event; type is the property which contains a string representation of the event (what kind of event was the trigger). We are accessing this object's properties using normal dot syntax, and sending the results to the Output window.
The Output window should show a repeating sequence:
_level0.my_playback change _level0.my_playback change _level0.my_playback change
The eventObject.target value is a reference to the broadcasting component instance, and so we get the complete reference: where it is as well as it's name. The eventObject.type specifies the triggering event.
eventObject.target reference
Once we have a reference to the broadcasting instance, we can use that reference as if we were working directly with an instance name. Most complex graphical elements (ie, non-shapes, or anything that can have an instance name applied to it) share common attributes (properties), such as horizontal and vertical position. These are accessed with the _x and _y properties.
Comment out the .type trace() statement, and modify the remaining trace() statement so that the _x property of the broadcasting (MediaPlayback) is displayed in the Output window:
myPlaybackListener = new Object(); // 1) establish generic Object // 2) establish listener callback function (event handler) myPlaybackListener.change = function(eventObject){ trace(eventObject.target._x); // reference to source/broadcaster // trace(eventObject.type); // type of event } // 3) associate event broadcaster with listener my_playback.addEventListener("change", myPlaybackListener);
eventObject.target is a reference to the my_playback instance. Adding the dot separator and the _x property name then allows us to access the horizontal position of that instance.
Depending on where you placed your MediaPlayback instance, you should see something similar to:
107 107 107 107
The horizontal position of my_playback is: 107
eventObject.target reference
to access the property: playheadTime We've already successfully sent the value of playheadTime to the Output window, so all we have to do now is replace the property _x with the property playheadTime:
Delete the commented .type trace() statement, and modify the remaining trace() statement, replacing the _x property of the broadcasting (MediaPlayback) with the playheadTime property:
myPlaybackListener = new Object(); // 1) establish generic Object // 2) establish listener callback function (event handler) myPlaybackListener.change = function(eventObject){ // reference to source/broadcaster trace(eventObject.target.playheadTime); } // 3) associate event broadcaster with listener my_playback.addEventListener("change", myPlaybackListener);
eventObject.target is a reference to the my_playback instance. Adding the dot separator and the playheadTime property then allows us to access the current (elapsed) time while the media is playing.
0.25 0.5 0.833 1.166 1.416 1.666 1.916 ...
The playheadTime should now be sent to the Output window, just as we had it doing when we applied the script directly on the MediaPlayback instance. This is a little more work, but not by much, and it has the advantage of being much easier to maintain and modify.
playheadTime to a Dynamic Text field:
Instead of sending the playheadTime to the Output window, send it instead to the text property of the Dynamic Text field video_length_txt:
myPlaybackListener = new Object(); // 1) establish generic Object // 2) establish listener callback function (event handler) myPlaybackListener.change = function(eventObject){ // display elapsed time in DynText field video_length_txt.text = eventObject.target.playheadTime; } // 3) associate event broadcaster with listener my_playback.addEventListener("change", myPlaybackListener);
Which, if we remove all of the comments for a moment, boils down to:
myPlaybackListener = new Object();
myPlaybackListener.change = function(eventObject){
video_length_txt.text = eventObject.target.playheadTime;
}
my_playback.addEventListener("change", myPlaybackListener);
You can see that if we don't set the Video Length field, as soon as the FLV stops playing, we lose the elapsed time. By sending the playheadTime to a Dynamic Text field (and by making it selectable), we can find out what value to enter the Video Length field (without having to rely on the Output window, which is only available from the Flash authoring tool:

Now that we can send the playheadTime to a Dynamic Text field, let's take the next step: remove the hard-coded URL, and pass a filename/url to the SWF when it loads in a browser window!
Here's the ActionScript at this point in time (there are a few more comments than you were directed to enter):
// size and location of MediaPlayback component my_playback.setSize(336 ,326); my_playback.move(107 ,70); // play automatically; use source dimensions my_playback.autoPlay = true; // must be set before setMedia() my_playback.autoSize = true; // Use Preferred Media Size // load external FLVurl = "step2.flv";// next step, remove this statement my_playback.setMedia(url, "FLV"); // expected argument as query string url_txt.text = url + ":"; // display file name /*** listeners ... a good alternative to: on (event) ***/ myPlaybackListener = new Object(); // 1) establish generic Object // 2) establish listener callback function (event handler) myPlaybackListener.change = function(eventObject) { // display elapsed time in DynText field video_length_txt.text = eventObject.target.playheadTime; } // 3) associate event broadcaster with listener my_playback.addEventListener("change", myPlaybackListener);
url = "sept2.flv"; statement (as indicated in the red comment above)
You might be wondering: how is our Flash movie going to know what FLV to load? We are using the value stored in the variable url in the setMedia() method that follows ... and we just got rid of it???

Now, look in the Address/Location bar. After "search" is a question mark, followed by a variableName = value pair (hl=en) separated by the & delimiter followed by another varaibleName2=value2 pair (ie=UTF-8) separated by the & delimiter followed by another ...
Everything after "search" is called a query string, and it is one of two ways of passing information from the client browser to the server and back.
This is going to be our first method of getting the FLV filename into Flash.
NOTE: The next step will only work if you are on a Macintosh ... if you are on a Windows machine, you will still be able to follow along, you'll just have to do a little more work. But if you are on a Windows machine, you are probably used to having to do a little more work ... ;)
File -> Open File ... , and navigate to and select: flv_video_length.swf
The SWF loads into the browser, but with no FLV to display, all you should see is an empty MediaPlayback component

?
flv_video_length.swf?
url
flv_video_length.swf?url
=
flv_video_length.swf?url=
step2.flv
flv_video_length.swf?url=step2.flv
Remember, we are replacing the ActionScript statement:
url = "step2.flv";
When we work with query strings, everything is a string, so we don't need to put the quotation marks around the filename as we do in ActionScript. Also, because this is not ActionScript, we don't need to end an expression with a semicolon.
This should reload the SWF, and pass to the SWF the query string, which the Flash SWF will interpret as a variable assignment statement on the main timeline (just like the one we deleted previously).

Of course, this won't work if the FLV is not in the same folder as the SWF (or if you don't establish the appropriate path from the SWF to the FLV), but that was true when we weren't using the query string method.
Really, that's all there is to it!
You can do the exact same thing on a Windows machine ... you just have to do a little extra work.
Here's the deal: if you are working on a Windows machine, you'll need the intercession of a server. It can be any server, but for this to work from the desktop on Windows, you'll need to work through a server.
While Windows XP users are completely out of luck, one reason to have XP Pro is that this version comes with a small scale IIS server, although it's not part of the normal installation.
If you are using a version of Windows previous to XP, then you are in luck: track down Windows NT 4.0 Option Pack and download it. Somewhere in the service pack is the Personal Web Server.
Once the server is installed on your machine, a few folders/directories are established for you. Somewhere close to the root level of your hard drive will be the folder: Inetpub, and inside that folder is a folder named: wwwroot.
Files located in the wwwroot folder can be served through the Personal Web Server by entering http://localhost/ ... and then the filename (if the file is located directly inside the wwwroot folder), or the path and filename (if the file is in a subfolder of wwwroot).
http://localhost/
- or -
http://127.0.0.1/
This will point the browser to the server's home folder, which is the wwwroot folder
If you placed the SWF file directly in the wwwroot folder, enter the SWF's filename:
http://localhost/flv_video_length.swf
?url=step2.flv
http://localhost/flv_video_length.swf?url=step2.flv
Once we bring the local server into play, this should work just like it does on a Mac

Since I do a lot of Web work, and since it is always handy to have a local server - especially on Windows, because you can install the .NET Frameworks and do a lot of your testing without having to transfer files to a host server - it just seemed to make sense to spring for the extra $$$ to get XPPro over the consumer XP. Especially when I found out that Microsoft made it so that regular XP can't run the Personal Web Server.
But whether you are on a Mac, or XPPro or an earlier version of Windows with the Personal Web Server installed, you can always do this the old fashioned way: upload and test from a real server.
http://somehost.com/flv_video_length.swf?url=step2.flv
The point of this part of the exercise is to give you an easy way to find out the Video Length of an FLV. The nice thing about this method is that it is relatively easy to implement, and it provides you with a tool that can find out the Video Length of any FLV file, simply by running the SWF in a browser, and supplying query string with the appropriate URL of an FLV file you want to get the length of. Plus, if you've got this SWF on a server, you can upload an FLV from wherever you are working, and get the Video Length of an FLV. (Also, because we made the Dynamic Text field selectable, all you have to do is copy the length, and paste it into an ActionScript statement, if you are not using the Component Inspector.
But wait, there's more! (Will this never end?)
Yes. Check out the Enter Key & Input Text mini-tutorial, which shows how to work with Input Text fields. Two techniques are shown: taking action when a user clicks inside an Input Text field, and taking action when the Enter key (Return key) is pressed. This will show you how to duplicate the functionality of an empty Instance Name field of the Property Inspector.
Based upon the Input Text and Enter Key tutorial, let's make this truly useful by allowing you to enter the URL of an FLV in a Flash Input Text field.
Select the field, and in the Property Inspector, choose Input Text from the Text Type dropdown menu.
We now have an Input Text field into which a user can enter the URL of an FLV to load
url_txt.text assignment string:
url_txt.text = url + ":"; // display file name
We want to change this so that it displays a prompt for the user to enter the URL of an FLV.
prompt_str = "<Enter FLV URL> "; // roughly 5 spaces
url_txt.text = prompt_str; // display prompt
url_txt.textColor = 0x808080; // color text gray
my_playback.setMedia() statement below all exisiting statements // size and location of MediaPlayback component my_playback.setSize(336 ,326); my_playback.move(107 ,70); // play automatically; use source dimensions my_playback.autoPlay = true; // must be set before setMedia() my_playback.autoSize = true; // Use Preferred Media Size// load external FLVmy_playback.setMedia(url, "FLV");// expected argument as query stringurl_txt.text = url + ":";// display file nameurl_txt.textColor = 0x808080; // color text gray prompt_str ="<Enter FLV URL> "; url_txt.text = prompt_str; // display prompt /*****************************************/ /********** establish listeners **********/ /*****************************************/ //********** listen for change in MediaPlayback **********/ myPlaybackListener = new Object(); // 1) establish generic Object // 2) establish listener callback function (event handler) myPlaybackListener.change = function(eventObject){ // reference to source/broadcaster //trace(eventObject.target.playheadTime); //trace(eventObject.type); // type of event // display elapsed time in DynText field video_length_txt.text = eventObject.target.playheadTime; } // 3) associate event broadcaster with listener my_playback.addEventListener("change", myPlaybackListener); // load external FLV my_playback.setMedia(url, "FLV"); // expected argument as query string

This was mostly a test to make sure we didn't break anything. Also to verify that the assignment statement to the (now Input Text) url_txt field worked as expected.
Several comments were modified or added.
setMedia() statement, add this ActionScript:
/********** detecting Input Text field gaining focus **********/
inputListener = new Object(); // establish listener (generic) object
// establish listener callback function (event handler)
inputListener.onSetFocus = function (oldFocus, currentFocus) {
if (currentFocus._name == url_txt._name) {
if (currentFocus.text == prompt_str) {
currentFocus.text = ""; // clear the initial prompt
currentFocus.textColor = 0x000000; // change text color
}
}
}
// associate/register Listener w/Selection obj
Selection.addListener(inputListener);
This follows the basic pattern for establishing a listener.
When the url_txt field gains focus, the onSetFocus() event callback function is invoked; it is passed references to old selected (text or component) instance as well as the instance that now has focus.
The instance name of the newly-selected instance is compared with the instance name of the url_txt field. If they are equivalent, then the content of the url_txt field is compared with the content of the variable prompt_str; if they are the same - and they should be initially, since we assigned the contents of prompt_str to the url_txt.text property earlier (a change we just made) - then we assign a null string (empty string) to, and change the text color of, the currentFocus instance.
That is what we did by means of ActionScript. In effect, when the user clicks on the url_txt field, the initial prompt is cleared, and anything that the user enters from that point on will be a different color (black).
Test to make sure that when you click on the url_txt field, the contents disappear.
setMedia() statement, add this ActionScript:
/************* listening for the Enter/Return key *************/
keyListener = new Object(); // establish listener (generic) object
keyListener.onKeyUp = function () { // when keyboard key released
if (Key.getCode() == Key.ENTER) { // if Enter key was pressed
// load user-entered FLV URL
my_playback.setMedia(url_txt.text, "FLV");
Selection.setFocus(null); // hide insertion bar
}
}
Key.addListener(keyListener); // register object to receive onKeyUp
This follows the basic pattern for establishing a listener.
When any key on the keyboard is pressed (regardless of which text instance has focus), the listener callback function is invoked. It checks to see if the last key pressed was the Enter/Return key.
If it was the Enter/Return key, the content of the url_txt field is used as the URL in the setMedia() method.
In this example, we did no error checking, and we didn't even check to see if it was the url_txt instance that currently had focus. We also are not checking to see if there was an FLV file to load. We would do these kinds of things in any regular project ... but since we were creating a utility for ourselves to determine the Video Length of an FLV file, we are not expecting anyone else to be using this SWF.
my_playback.setMedia(url, "FLV"); statement Assuming that you provide a valid URL for an FLV, this should cause that FLV to load and play, and when it's done, you have the Video Length time of the FLV.
// size and location of MediaPlayback component my_playback.setSize(336 ,326); my_playback.move(107 ,70); // play automatically; use source dimensions my_playback.autoPlay = true; // must be set before setMedia() my_playback.autoSize = true; // Use Preferred Media Size url_txt.textColor = 0x808080; // color text gray prompt_str ="<Enter FLV URL> "; url_txt.text = prompt_str; // display prompt /*****************************************/ /********** establish listeners **********/ /*****************************************/ //********** listen for change in MediaPlayback **********/ myPlaybackListener = new Object(); // 1) establish generic Object // 2) establish listener callback function (event handler) myPlaybackListener.change = function(eventObject){ // display elapsed time in DynText field video_length_txt.text = eventObject.target.playheadTime; } // 3) associate event broadcaster with listener my_playback.addEventListener("change", myPlaybackListener); /********** detecting Input Text field gaining focus **********/ inputListener = new Object(); // establish listener (generic) object // establish listener callback function (event handler) inputListener.onSetFocus = function (oldFocus, currentFocus) { if (currentFocus._name == url_txt._name) { if (currentFocus.text == prompt_str) { currentFocus.text = ""; // clear the initial prompt currentFocus.textColor = 0x000000; // change text color } } } // associate/register Listener w/Selection obj Selection.addListener(inputListener); /************* listening for the Enter/Return key *************/ keyListener = new Object(); // establish listener (generic) object keyListener.onKeyUp = function () { // when keyboard key released if (Key.getCode() == Key.ENTER) { // if Enter key was pressed // load user-entered FLV URL my_playback.setMedia(url_txt.text, "FLV"); Selection.setFocus(null); // hide insertion bar } } Key.addListener(keyListener); // register object to receive onKeyUp
This completes our exploration of working with video in Flash Pro. There is a lot more to explore, but this should be a good start.
Enjoy!
Completed as of Thursday, Apr 08, 8:30pm
| copyright© 2004 Stephen McManus | April 08, 2004 |
We are going to use a query string to send the name/value pair (that we just deleted) into the Flash SWF.
If you've done any work on the Web before, you already know about query strings, perhaps in conjunction with the GET method when working with FORM data. But even if you haven't you've already seen them, even if you didn't know what they were called.
In a browser, go to Google, and enter in the search field the terms: actionscript mediaplayback video and hit Enter: