Accessibility

Table of Contents

Exploring Flash Player support for high-definition H.264 video and AAC audio

Extracting metadata from MPEG-4 files

In the past, when you worked with Flash-based video, you could inject additional data into the video file for use during playback. The onMetaData event was commonly used to retrieve this data during runtime. The data would contain simple pertinent information such as track length and video dimensions. That same type of information is also available with the new supported video formats.

Since MPEG is a container format that can contain many different items of information grouped together into one file, it is useful to access different bits of information inside that container. Using the onMetaData event of the NetStream, you can extract a variety of information such as dimensions, length, codec, seek points, and potentially cover art, subtitles, audio book chapters, and other text and images from both H.264 and M4A files.

It's important to note that if the seek points aren't included in the metadata, you won't be able to seek in the file at all. There are also new onImageData and onTextData events that respond to this data for both audio and video files. The onImageData returns GIF, PNG, or JPEG data as a ByteArray in ActionScript 3.0 only. The onTextData can return text data such as subtitles. Cover art may also be encoded in your audio or video files; they are most often accessed through the onMetaData event. I will explore this in the following walkthrough.

Here are the steps for extracting metadata from video files:

  1. Open the same file that you worked with in the video example (H264_Video_AS3.fla) or open the H264_Video_AS3_MetaData.fla file in the sample files folder.
  2. Create a new layer in the Timeline under the ~AS:Main layer and name it output (see Figure 4).

    Creating a new layer beneath: output

    Figure 4. Creating a new layer beneath: output

  3. While Frame 1 of the output layer is selected, create a dynamic text field on the Stage.
  4. With the text field selected, open the Property inspector (on Windows: Control+F3, on Mac: Command+F3).
  5. Set the x property of the text field to 5.
  6. Set the y property of the text field to 5.
  7. Set the width property of the text field to 175.
  8. Set the height property of the text field to 300.
  9. Give the text field the instance name of output_txt.
  10. On the layer ~AS:Main select Frame 1 and open the Actions panel (on Windows: F9, on Mac: Option+F9).
  11. In ActionScript 3.0, you have to handle the onMetaData event through the client object of the NetStream. So first write the function that handles the metadata and have it receive the event object as its only parameter. Write this code below the netStatusHandler function:

    function onMetaData(p_info:Object):void
    {
    
    }
  12. Inside the onMetaData event handler, create a for loop that will loop through and display the properties of the p_info object to the dynamic text field. The code should look similar to this:

    for(var propName:String in p_info)
    {
        output_txt.appendText(propName + "=" + p_info[propName] + "\n");
    }
  13. Use the metadata to set the size of the video object. After the for loop in the onMetaData event handler, set the width property of the video object to the value of p_info.width, like this:

    video.width = p_info.width;
  14. Set the height property of the video object to the value of p_info.height:

    video.height = p_info.height; 

    Note: The video file in the sample files is 1280 x 720, so you'll want to size your Flash project to accommodate that size. Use 1465 x 720 as the width and height dimensions to size your sample files.

    The completed onMetaData handler should now look like this:

    function onMetaData(p_info:Object):void
    {
        for(var propName:String in p_info)
        {
            output_txt.appendText(propName + " = " + p_info[propName] + "\n");
        }
        video.width = p_info.width;
        video.height = p_info.height;
    }
  15. Test your movie in the browser. You may not see your output text field because the video is getting loaded on top of it. To solve that problem, you'll move the video over. Right before the addChild(video); line, set the x value of the video to 185 and the y value of the video to 5:

    video.x = 185;
    video.y = 5;
  16. Save the file and test your movie in the browser again. The metadata should be displayed in the visible output text field and the Video object should resize to match the size of the source video.

Here are the steps for extracting metadata from audio files:

  1. Open the same audio file you've been working with (AAC_Audio_AS3.fla) or open the AAC_Audio_AS3_MetaData.fla file from the sample files folder.
  2. Create a new layer in the Timeline under the existing ~AS:Main layer and name it output (see Figure 5).

    Creating a new layer: output

    Figure 5. Creating a new layer: output

  3. While Frame 1 of the output layer is selected, create two dynamic text fields on the Stage and give them the instance names length_txt and copy_txt.
  4. Select the text field with the instance name length_txt and set its x position to 10 and its y position to 5. Set the width of the text field to 240 and its height to 21. Also click the Show Border Around Text button in the Property inspector to add a border around the text field. Your Property inspector should look similar to Figure 6.

    Updating the text field settings

    Figure 6. Updating the text field settings

  5. Select the text field with the instance name copy_txt TextField and set its x position to 10 and its y position to 31. Also set its width to 240 and its height to 21 and click the Show Border Around Text button in the Property inspector. After making these changes, the Stage should now roughly appear like the example in Figure 7.

    Updating the settings of the two text fields

    Figure 7. Updating the settings of the two text fields

  6. Select Frame 1 of the ~AS:Main layer in the Timeline and open the Actions panel (on Windows: F9, on Mac: Option+F9).
  7. After declaring the NetStream object, set the client property of the NetStream object equal to the reference value this, so that the root Timeline will handle events from the NetStream. In ActionScript 3.0, you have to handle the onMetaData event through the client object of the NetStream:

    var stream_ns:NetStream = new NetStream(connect_nc);
        stream_ns.client = this;
  8. Create an event handler for the onMetaData event. The function should receive one parameter named p_info that is typed as an Object:

    function onMetaData(p_info:Object):void
    {
    }
  9. Inside the onMetaData event handler, set the text property of the length_txt text field to display the length of the audio source file. The length of the audio is stored as seconds in the duration property of the event object, so you can multiply that number by 1000 to get the duration of the media in milliseconds:

    length_txt.text = "Length: " + (p_info.duration*1000) + " ms";
  10. Set the text of the copy_txt TextField to display the codec used to encode the audio source file. This codec information is stored in the audiocodecid property of the p_info object received by the onMetaData event handler:

    copy_txt.text = "Codec: " + p_info.audiocodecid;

    The completed code should look like this:

    var mySound:SoundTransform;
    var connect_nc:NetConnection = new NetConnection();
    connect_nc.connect(null);
    var stream_ns:NetStream = new NetStream(connect_nc);
    stream_ns.client = this;
    function onMetaData(p_info:Object):void
    {
        length_txt.text = "Length: " + (p_info.duration*1000) + " ms";
        copy_txt.text = "Codec: " + p_info.audiocodecid;
    }
    stream_ns.play("RE-Sample.m4a");
    mySound = stream_ns.soundTransform;
    mySound.volume = .5;
    stream_ns.soundTransform = mySound;
              
  11. Test the movie in the browser and you should see some basic information extracted from the file's metadata. That's cool, but you can make things more interesting.
  12. Close the browser window and return to Flash. Open the Action panel.
  13. Write a function that will display a cover image. The cover image data is received in the onMetaData event handler as an array of ByteArrays. Under the onMetaData event handler, create a function named handleCoverImage and have it accept an Array named p_data as its only parameter:

    function handleCoverImage(p_data:Array):void
    {
    }

    Note: The cover data you'll be bringing in is 320 x 240, so you should resize your Flash movie to match those dimensions.

  14. Inside the handleCoverImage() function, create a new Loader variable and set it equal to a new Loader:

    var loader:Loader = new Loader();
  15. After creating the new Loader, call its loadBytes method to load in the data at the first index of the array, casting that value as a ByteArray. You can also retrieve this information for video, as well as audio, if it has the cover art metadata attached:

    loader.loadBytes(p_data[0] as ByteArray);
  16. In the last line of the function, you'll need to add the Loader to the display list at index 0 so that the image you load will be visible. Do this by calling the addChildAt() method and passing it loader as the first parameter and 0 as the second parameter:

    addChildAt(loader, 0);

    The completed handleCoverImage() function should look like this:

    function handleCoverImage(p_data:Array):void
    {
        var loader:Loader = new Loader();
        loader.loadBytes(p_data[0] as ByteArray);
        addChildAt(loader, 0);
    }
  17. Above the existing code in the onMetaData event handler, create an if conditional statement. The if condition should check if the cover data, stored as covr, in the tags object exists:

    if(p_info.tags.covr)
    {
    
    }
    length_txt.text = "Length: " + (p_info.duration*1000) + "ms";
    copy_txt.text = "Codec: " + p_info.audiocodecid;
              
  18. Move the code where you set the text property for the length_txt TextField above the if condition, like this:

    length_txt.text = "Length: " + (p_info.duration*1000) + " ms";
    
    if(p_info.tags.covr)
    {
    
    }
  19. Wrap the code where you set the text properties for copy_txt in an else statement:

    if(p_info.tags.covr)
    {
    }
    else {
         copy_txt.text = "Codec: " +
         p_info.audiocodecid;
    }
  20. Inside the if condition, set the htmlText property of the length_txt TextField to display the copyright information for the audio as a hyperlink to the URL associated with the media. This information is stored as the ©cpy and ©url attributes of your sample media files:

    if(p_info.tags.covr)
    {
          copy_txt.htmlText = "© <a href='"+ p_info.tags["©url"] + "'>"
             + p_info.tags["©cpy"] + "</a>";
    
    }
  21. Declare a covr variable and set it equal to the covr metadata and cast this value as an Array. Theoretically, you can have multiple images associated with the media as cover data, so the covr property should be treated as an Array:

    var covr = p_info.tags.covr as Array;
  22. Pass the covr variable as a parameter to the handleCoverImage function you wrote earlier:

    handleCoverImage(covr);

    The completed onMetaData handler should look like this:

    function onMetaData(p_info:Object):void
    {
        length_txt.text = "Length: " + (p_info.duration*1000) + "ms";
        if(p_info.tags.covr)
        {
             copy_txt.htmlText = "© <a href='"+ p_info.tags["©url"] + "'>" + p_info.tags["©cpy"] + "</a>";
             var covr = p_info.tags.covr as Array;
             handleCoverImage(covr);
        }
        else
        {
           copy_txt.text = "Codec " + p_info.audiocodecid;
        }
    }
  23. Test the movie in the browser. You should now see the cover art included with the audio duration and the copyright information about the media (see Figure 8).

    Audio source file metadata displayed when the movie is tested in a browser

    Figure 8. Audio source file metadata displayed when the movie is tested in a browser