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.

 

  1. Create a new Flash document
    1. Save the new document as: separate_components.fla
  2. Prepare the separate_components project:
    1. Insert two additional layers, and name them:

      Actions

      Display

      Controller

    2. From the Components panel, drag a MediaDisplay component onto the Display layer
      1. Instance Name: my_display
    3. Drag a MediaController component onto the Controller layer
      1. Instance Name: my_controller

      There is no specific requirement for the components to be on the same layer, or on different layers.

    Working with the separate Media components

    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.

    Associating the separate Media components
  3. Associating the separate media components:

    You only need to perform one of the two following steps:

    1. Associate the Controller with the Display:
      1. Select the MediaPlayer instance named my_display
      2. In the Behavior Panel: Add Behavior [+] -> Media -> Associate Controller
        1. From the Associate Controller (targeting) dialog box, select the Controller Component instance my_controller
      3. Click:  OK
    2. Associate the Display with the Controller:
      1. Select the MediaController instance named my_controller
      2. In the Behavior Panel: Add Behavior [+] -> Media -> Associate Display
        1. From the Associate Display (targetting) dialog box, select the Display Component instance my_display
      3. Click:  OK

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

    Configuring the MediaDisplay component
  4. Configuring the MediaDisplay component using the Component Inspector:
    1. Select the my_display MediaDisplay instance, and open the Component Inspector
      1. (Media type):  FLV  (*)   (selected)
      2. URL:  step1.flv

        For this experiment, it can be any FLV you have created or have available

      3. Milliseconds:  [x]   (selected)
      4. Video Length:  6.166    (your time/length will be different!)

        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).

      5. Automatically Play:  [x]   (selected)
      6. Use Preferred Media Size:  [x]   (selected)
    2. Save and test movie

      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.

    Configuring the MediaController component
  5. Configuring the MediaController component using the Properties Inspector:
    1. Select the my_controller MediaController instance, and open the Properties Inspector
      1. activePlayControl:  play

        The options are either pause or play (display the pause button or the play button)

      2. backgroundStyle:  default

        The options are either default or none (default displays the chrome around the controls, while none removes the chrome)

      3. controllerPolicy:  on

        The options are auto (display controls when user cursors over the controller); on (controls always visible); off (controls always hidden)

      4. horizonal:  true

        The options are true or false (true displays the controls horizontally)

    2. Save and test movie

      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.

    3. Modify the my_display parameters so that the my_controller controls the intial playback:
      1. Select the MediaDisplay instance my_display
      2. In the Component Inspector, deselect the Automatically Play checkbox
      3. Save and test movie

        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.

    4. Configure the two components to automatically play the FLV:
      1. Select the MediaDisplay instance my_display
      2. In the Component Inspector: Automatically Play:  [x]   (selected)
      3. Select the MediaController instance my_controller
      4. In the Properties Inspector: activePlayControl -> pause
      5. Save and test movie
  6. Any video element in Flash is like any other object

    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.

    1. Insert a new layer above the Display layer, and name it: Mask
    2. Select the my_display instance on the Display layer, so that the outline of the instance is visible
    3. Turn on the Rulers, and drag guides to each of the four edges of the my_display instance
    4. Select the Mask layer
    5. Draw a round-cornered rectangle, using the guides as ... well ... guides
      1. No stroke, Round Rectangle Radius: 10 pts (or so)
    6. Set the Mask layer properties to: Mask
    7. Set the Display layer properties to:  Masked
    8. Save and test movie

      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 ...

  7. For no particular reason, add a drop shadow
    1. Select and copy the round-cornered rectangle shape in the Mask layer
    2. Lock both the Mask and Display layers
    3. Insert a new layer below the Mask/Display layers, and name it: Drop Shadow
    4. With the new Drop Shadow layer selected, Edit -> Paste in Place  (the copied rectangle shape)
    5. Select the rectangle shape in the Drop Shadow layer
    6. Insert -> Timeline Effects -> Effects -> Drop Shadow

      Feel free to use your own values for the drop shadow ... these are just suggestions ...

      1. Color:  #333333
      2. Alpha:  75%
      3. Offset X: 3
      4. Offset Y: 4
      5. Click: OK
    7. Save and test movie

    This is meant to suggest that you can use the video stream as just another graphical element in a project ...

    Example 3

  8. Close the separate_components.fla document window

    This brief detour was meant to squeeze in an example of working with the two individual media components.

    Scripting the MediaPlayback component

    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.

    Example: Component Inspector Equivalents
  9. Create a new Flash document, and save it as:  flv_video_as.fla
  10. Prepare the flv_video_as project:
    1. Insert one additional layer, and name them:

      Actions

      Playback

    2. From the Components panel, drag a MediaPlayback component onto the Playback layer
      1. Instance Name: my_playback
    3. Drag the my_playback instance completely off of the Stage
     Property Inspector settings  

    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:

  11. Select frame 1 of the Actions layer, and apply this ActionScript in the Actions panel:
      // 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.

    1. Save and test movie

      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.

     Component Inspector settings  

    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

  12. Automatically Play:
     
      // 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

  13. URL and filetype:
     
      // 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.

  14. Video Length:
     
      // 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.

  15. Milliseconds:

    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.

  16. Use Preferred Media Size:
     
      // 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

  17. Respect Aspect Ratio:
     
      // 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.

  18. Control Placement:
     
      // 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.

  19. Control Visibility:
     
      // 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.

  20. Optional: Just in case, load the FLV after setting the properties
     
      // 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";
    
  21. Save and test movie

    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.

    1. If you have yours working, go ahead and close the file's document window in Flash
    Example: Determining FLV Video Length

    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.

  22. Create a new Flash document, and save it as:  flv_video_length.fla
  23. Prepare the flv_video_length project:
    1. Insert two additional layers, and name them:

      Actions

      Dynamic Text

      Playback

    2. From the Components panel, drag a MediaPlayback component onto the Playback layer
      1. Instance Name: my_playback
    3. Drag the my_playback instance completely off of the Stage
  24. Place two Dynamic Text fields on the Dynamic Text layer:

    With the Text tool selected, and with the Text Type set to Dynamic in the Property Inspector:

    1. Create one dynamic text field that is approximately 100 pixels wide
    2. Instance name: video_length_txt
    3. In the Property Inspector, select the Align Left control
    4. In the Property Inspector, set the Show Border around Text control to: selected
    5. In the Property Inspector, set the Selectable control to: selected
    6. Create a second dynamic text field that is approximately 160 pixels wide

      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

    7. Instance name: url_txt
    8. In the Property Inspector, select the Align Right control
    9. In the Property Inspector, set the Show Border around Text control to: deselected
    10. In the Property Inspector, set the Selectable control to: selected
    11. Position these fields so that the video_length_txt field is to the right of the url_txt field
  25. Set the size and position of the my_playback instance:

    You can either do this manually by dragging and using the Property Inspector, or by means of ActionScript:

    1. Select frame 1 of the Actions layer, and apply this ActionScript in the Actions panel:
        // 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

  26. Set the Automatically Play and Use Preferred Media Size controls:

    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:

    1. Select frame 1 of the Actions layer, and apply this ActionScript in the Actions panel:
      my_playback.autoPlay = true;           // must be set before setMedia()
      my_playback.autoSize = true;           // Use Preferred Media Size
      
  27. Establish the URL of the external FLV:

    We are going to be specifying the FLV dynamically at runtime, so we won't be using the Component Inspector.

    1. Select frame 1 of the Actions layer, and add this ActionScript in the Actions panel:
      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.

  28. Send the filename/URL to a Dynamic Text field:
    1. Select frame 1 of the Actions layer, and add this ActionScript in the Actions panel:
      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

  29. Save and test movie

    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.

  30. Display the current playback time in the Output window
    1. Select the my_playback MediaPlayback instance
    2. With the my_playback instance selected, apply this ActionScript in the Actions panel:
      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).

    3. Save and test movie

      As the FLV is playing, the elapsed time is sent to the Output window.

  31. Display the current playback time in a Dynamic Text field
    1. Select the my_playback MediaPlayback instance
    2. With the my_playback instance selected, add this ActionScript in the Actions panel:
      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.

    3. Comment out the  trace()  statement by putting two forward slashes in front of it
    4. Save and test movie

      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).

     Best Practices  

    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:

  32. Comment out the existing script:
    1. Select the my_playback MediaPlayback instance
    2. With the my_playback instance selected, add a block comment around the existing script:
      /*
      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

    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:

    1) Create a generic Object
    which will be used to "listen" for an event
     
    2) Create the listener callback function (event handler)
    this establishes what to do, what steps to take, when the event is "heard"
     
    3) Associate the broadcaster with the listener
    once the listener is establish, we tell it who (and which event) to listen for

    In the steps below, the remaining ActionScript statements will be applied to frame 1 of the Actions layer

  33. Create a generic Object:
    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

  34. Create the listener callback function:
    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.

  35. Associate the broadcaster with the listener:
    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.

  36. Using the 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.

    1. Save and test movie

      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.

  37. Using the 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.

    1. Save and test movie

      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

  38. Using the 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.

    1. Save and test movie
      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.

  39. Send the 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);
    
    1. Save and test movie

      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:

    of Query Strings and URL Encoding

    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 FLV
    url = "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);
    
  40. Delete the  url = "sept2.flv";  statement (as indicated in the red comment above)
    1. Save and test movie (to export the SWF)

    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???

    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:

    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 ... ;)

  41. (On a Mac): Load the flv_video_length.swf in a browser:
    1. In most browsers, go to the File menu and select Open File (or something similar)

      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

    2. In the location bar, enter a query string:
      1. After the filename, enter a question mark to start the query string: ?
        flv_video_length.swf?
      2. Then enter the name of a variable: url
        flv_video_length.swf?url
      3. Then enter an equals sign: =
        flv_video_length.swf?url=
      4. Then enter the name of an FLV file:  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.

    3. After entering the query string, hit Enter

      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).

  42. On a Windows machine with the Personal Web Server installed and running:
    1. Copy or move the flv_video_length.swf and the step2.flv file into the wwwroot folder
    2. Open your browser, and in the location bar, enter:
      http://localhost/

      - or -

      http://127.0.0.1/

      This will point the browser to the server's home folder, which is the wwwroot folder

    3. Load the flv_video_length.swf in a browser:

      If you placed the SWF file directly in the wwwroot folder, enter the SWF's filename:

      http://localhost/flv_video_length.swf
    4. Enter the query string:  ?url=step2.flv
      http://localhost/flv_video_length.swf?url=step2.flv
    5. Hit: Enter

      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.

  43. Everyone: from a remote server (no special software needed):
    1. Upload the (flv_video_length.swf) SWF and the (step2.flv) FLV to your space on a remote server
    2. In a browser, enter the URL of the SWF in your area on the server
    3. In the location bar of your browser, at the end of the URL to your SWF on the server, add:
      http://somehost.com/flv_video_length.swf?url=step2.flv
    4. Then hit: Enter

    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?)

    Can we do this without the query string hassle?

    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.

    Using an Input Text field to select the FLV

    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.

  44. Modify the url_txt field:
    1. Modify the Text Type of this field from Dynamic to Input Text

      Select the field, and in the Property Inspector, choose Input Text from the Text Type dropdown menu.

    2. In the Property Inspector, set the Show Border around Text control to: selected

    We now have an Input Text field into which a user can enter the URL of an FLV to load

    Establish an initial prompt
  45. Modify the existing ActionScript:
    1. Locate the 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

    2. Just prior to that assignment statement, add a new statement to change the text color:

      url_txt.textColor = 0x808080;            // color text gray

    3. Move the my_playback.setMedia() statement below all exisiting statements
    4. The ActionScript on frame 1 should look like:
        // 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 FLV
      my_playback.setMedia(url, "FLV");   // expected argument as query string
       
      url_txt.text = url + ":";           // display file name
      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){
                                          // 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
      
    5. Save and test movie

      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.

    Respond to Selection
  46. Add ActionScript to remove the prompt when the user clicks inside the url_txt field:
    1. Just above the 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).

    2. Save and test movie

      Test to make sure that when you click on the url_txt field, the contents disappear.

    Respond to Enter key - Load FLV
  47. Add ActionScript to load the URL/FLV when the user hits Enter/Return:
    1. Just above the 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.

    2. Delete the original my_playback.setMedia(url, "FLV"); statement
    3. Save and test movie

      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.

    The final ActionScript

  48. When completed, your ActionScript should look something like this:
      // 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
Home