22 June 2010
Basic knowledge of ActionScript 3 and Adobe Flash Builder or Adobe Flash Professional is recommended for this tutorial.
Intermediate
The RealEyes OSMF Player Sample (REOPS) is a project developed by RealEyes Media to provide the community a sample and an optional starting point for a robust video player utilizing the Open Source Media Framework (OSMF) from Adobe. The REOPS project is meant to be a building block for developers, as well as a visual representation to illustrate the capabilities of the OSMF framework and a "how to" for using it.
This article is a follow-up of our previous article, Part 1: Setup and deployment, where we introduced you to the REOPS project. In this article we show you how to build a very simple OSMF player to get familiar with the building blocks of the OSMF. We then explain each of these OSMF building blocks in simple terms, as well as how the REOPS project integrates each of them.
In this walkthrough you will build a simple player using the OSMF to see these objects in action. For now, don't worry about the details of each item. We will review each of the objects, what they do, and how the REOPS uses them.
We will be referencing the REOPS project throughout this article, so if you haven't downloaded or checked out the REOPS code, you can do so from the Google code page:
We will also be reviewing the OSMF code, so you will want to download that as well. The REOPS project comes with the OSMF.swc file, but you may want to look at the actual OSMF framework code for yourself.
You can get the code in a couple of ways:
Before we dive into the code, we'll review some of the basic OSMF media player building blocks. That way you'll be familiar with them when you build a player, as well as when we review how the REOPS uses the OSMF to create powerful and flexible player platform.
To build a basic player, you need four things:
Note: Completed files for this example can be found in the REOPS Google Code project downloads list. Look for TheSimplestPlayer.zip as a Flex project archive.
[SWF( width="640", height="360" )]
public class TheSimplestPlayer extends Sprite
{
}
"rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short". This will be the media played. The OSMF manages splitting up the connection portion of the string from the content portion for streaming media:
public class TheSimplestPlayer extends Sprite
{
var videoPath:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short";
}
var videoPath:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short";
var resource:URLResource = new URLResource( videoPath );
var resource:URLResource = new URLResource( videoPath );
var element:VideoElement = new VideoElement( resource );
var element:VideoElement = new VideoElement( resource );
var mediaPlayer:MediaPlayer = new MediaPlayer( element );
var mediaPlayer:MediaPlayer = new MediaPlayer( element );
var mediaContainer:MediaContainer = new MediaContainer();
addMediaElement() method on the mediaContainer object and pass it the element variable. This adds the actual media element to a display object:var mediaContainer:MediaContainer = new MediaContainer();
mediaContainer.addMediaElement( element );
addChild() method and pass it the mediaContainer variable. This simply displays the MediaContainer to the display list:mediaContainer.addMediaElement( element );
addChild( mediaContainer );
The completed code should look similar to the following:
[SWF( width="640", height="360" )]
public class TheSimplestPlayer extends Sprite
{
public function TheSimplestPlayer()
{
var videoPath:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short";
var resource:URLResource = new URLResource( videoPath );
var element:VideoElement = new VideoElement( resource );
var mediaPlayer:MediaPlayer = new MediaPlayer( element );
var mediaContainer:MediaContainer = new MediaContainer();
mediaContainer.addMediaElement( element );
addChild( mediaContainer );
}
This is a very simple player: there are no controls and it only plays a single video file—no playlist or other media types. However, this player does illustrate some of the core concepts of working with the OSMF.
The REOPS player uses the MediaPlayerSprite class. The MediaPlayerSprite class provides some out-of-the-box implementations that make developing with the OSMF much easier and quicker. The following sections will describe each of the main objects used to build an OSMF player and point out where the REOPS project integrates each of them. Figure 5 shows the general relationship of the objects used to build the REOPS using the OSMF.
The MediaPlayerSprite (Figure 6) enables a MediaElement with a DisplayObjectTrait to be placed on the display list using the MediaContainer class. The MediaContainer class implements much of the necessary code to accomplish this task. Additionally, the MediaContainer class offers support for the OSMF internal layout API. Currently, the REOPS project doesn't use the MediaPlayerSprite, but rather uses the MediaContainer object directly. The MediaPlayerSprite creates the MediaContainer object for you.
Additionally, the MediaPlayerSprite class can handle the creation of a MediaPlayer controller class (you can also create your own MediaPlayer instance and pass it to the MediaPlayerSprite). MediaElement and MediaPlayer should sound familiar. They were both used in the example player that you just built. DisplayObjectTrait, however, is a new concept. Next, we'll show you where traits fit into the OSMF and the REOPS project.
MediaElements, which we will cover in a moment, express their capabilities through traits. For example, an audio file has a duration or a timeline, but an image does not—so, an audio-based MediaElement object will have a TimeTrait where the image-based MediaElement will not.
Here are a few things to keep in mind when working with traits:
MediaElementEvent.TRAIT_ADD) and traitRemove (MediaElementEvent.TRAIT_REMOVE) events on MediaElement objects to manage the capabilities of your media player to match those of the current MediaElement.It can be quite a bit of work to get a player integrated with all the possible traits and combinations of traits that different MediaElements might have. Luckily, there is a class to help simplify the process of working with traits: the MediaPlayer class.
MediaPlayer is a high-level class that abstracts some of the lower level details of the OSMF. Instead of having to manage traits dynamically for all the different media types, the MediaPlayer class provides simple properties, methods, and events to handle all the normal trait management for you. The MediaPlayer class provides some default capabilities such as looping, auto-play and auto-rewind, as well as handling playback of any media type supported by the OSMF. This makes MediaPlayer a good base for a player.
The REOPS uses the MediaPlayer class directly (see Figure 6). For other use cases, MediaPlayerSprite creates an instance of the MediaPlayer class and applications can access the mediaPlayer instance variable to control the MediaElements.
The MediaElement class and its subclasses represent the media items presented by the media player. MediaElements can represent a single piece of media, such as a video clip or an image, but may also represent a complex composition of media items. In TheSimplestPlayer example, there was only one MediaElement—a video clip, which used the VideoElement directly. This is fine to get the job done, but lacks flexibility. In order to handle multiple types of MediaElement—video, audio, images, compositions, and more—you would need to evaluate the type of media that you want to play, then create the correct MediaElement subclass. The OSMF provides you with the MediaFactory to accomplish this task.
The MediaFactory class is what turns a URL or path into a MediaElement that the OSMF understands. The MediaFactory class maps resources’ paths to specific MediaElements by comparing each resource to a list of known resource types and their MediaElements. When a match is found, a MediaElement is created. The OSMF provides the DefaultMediaFactory, which can create MediaElements for all of the current media types supported by the OSMF.
Note: Reviewing the code in the org.osmf.media.MediaFactory and org.osmf.DefaultMediaFactory classes will give you a good base knowledge of how the MediaFactory works and how you can adjust the media types for your player.
Working with a MediaFactory is relatively straightforward. Once you've instantiated a MediaFactory object, you can call the createMediaElement() method, passing a MediaResource. The MediaFactory creates the appropriate MediaElement for that resource and returns that MediaElement back to the caller, where it can be applied to the player for display. The MediaFactory is meant to be extended and customized, but for most uses, you can use the DefaultMediaFactory class which provides the default media element creation functionality.
MediaElements are created based on the type of resource that needs to be presented. The MediaResourceBase class is the base class for all of these resources. Subclasses of MediaElementBase are specific to the type of media item. Here are some examples:
The following code snippet shows a simple case using the MediaFactory:
var mediaFactory:MediaFactory = new DefaultMediaFactory();
var resource:MediaResourceBase = new URLResource( "http://path/to/media.mp3" );
var audioElement:AudioElement = mediaFactory.createMediaElement( resource );
In this simple walkthrough you will add the MediaFactory class to the code you created in the previous walkthrough to create MediaElements dynamically for you:
DefaultMediaFactory and set it equal to a new instance of DefaultMediaFactory:var resource:URLResource = new URLResource( videoPath );
var mediaFactory:DefaultMediaFactory = new DefaultMediaFactory();
createMediaElement() method. Make sure you pass the resource variable to the createMediaElement() method. Change this:var element:VideoElement = new VideoElement( resource );
to this:
var element:MediaElement = mediaFactory.createMediaElement( resource );
The completed code should look similar to the following:
[SWF( width="640", height="360" )]
public class TheSimplestPlayer extends Sprite
{
public function TheSimplestPlayer()
{
var videoPath:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short";
var resource:URLResource = new URLResource( videoPath );
var mediaFactory:DefaultMediaFactory = new DefaultMediaFactory();
var element:MediaElement = mediaFactory.createMediaElement( resource );
var mediaPlayer:MediaPlayer = new MediaPlayer( element );
var mediaContainer:MediaContainer = new MediaContainer();
mediaContainer.addMediaElement( element );
addChild( mediaContainer );
}
}
There should be no change, but you should now understand that with a few changes the player has become more flexible. You no longer need to know the type of MediaElement ahead of time. All you need to do is pass the MediaFactory a path to a piece of media. Then the MediaFactory figures out what type of MediaElement to create for you.
The REOPS project uses a custom REMediaFactory that extends MediaFactory to enable it to provide some advanced capabilities that will be covered in future articles (see Figure 7). The REOPS also implements connection sharing using a built in feature of the OSMF.
The REOPS project uses the NetConnectionFactory to implement connection sharing in the player (see Figure 8). The REMediaFactory constructor method can receive a NetConnectionFactory object as a parameter. The NetConnectionFactory can be used to generate NetConnection instances and manage connection sharing between MediaElements. It does this by comparing the URLs resource of MediaElements to determine what connections can be shared.
The following code snippet shows how simple it is to use the NetConnection manager to enable connection sharing in a player:
var netConnectionFactory:NetConnectionFactory = new NetConnectionFactory();
var mediaFactory:REMediaFactory = new REMediaFactory( netConnectionFactory );
You should have a good idea of the major components in an OSMF player and how the REOPS player is built using the OSMF. In this section we're going to show you how to set up the REOPS player via XML configuration and then deploy the player with the new configuration.
A Flex project archive file has been provided as a starting point for this walkthrough. It can be found in the REOPS Google Code project downloads list; the archive is called MyREOPS_start.zip. The project includes a few things to make it quick and easy to get a REOPS player up and running:
Follow these steps to use the REOPS configuration XML:
Note: Additional nodes and attributes can be applied to add more functionality. More information will eventually be posted on the Google Code wiki page.
<player> node handles the player sizing and scale mode.<mediaElement> and its child <mediaElement> node handle the initial media that is displayed by the player.<skin> node configures the elements of the skin:Follow these steps to change the size of the player:
<player
width="768" height="600"
scaleMode="stretch"
isLive="false" autoPlay="true"
updateInterval="250"
hasCaptions="false">
Follow these steps to change the scale mode:
<player> node from stretch to letterbox. Note: Valid values for scaleMode are none, stretch, letterbox and zoom. For details on how each is handled, see the org.osmf.display.ScaleMode class.
<player
width="768" height="600"
scaleMode="letterbox"
isLive="false" autoPlay="true"
updateInterval="250"
hasCaptions="false">
Follow these steps to change the default MediaElement:
<mediaElement> node. Update the <media> node's url property to the URL shown:<mediaElement>
<mediaElement>
<media url="http://mediapm.edgesuite.net/strobe/content/test/AFaerysTale_sylviaApostol_640_500_short.flv" />
</mediaElement>
</mediaElement>
Follow these steps to change the player skin:
path attribute of the <skin> node from:<skin path="assets/skins/RE_Skin.swf">
to:
<skin path="assets/skins/Lunar.swf">Note: You can try the Core.swf and Formula.swf skin files as well.
Follow these steps to position and auto-hide the control bar:
<skinElement> node with the id of controlBar.vAdjust attribute value to be –180:<skinElement id="controlBar"
elementClass="com.realeyes.osmfplayer.controls.ControlBar"
initMethod="initControlBarInstance"
scaleMode="none"
hAdjust="0" vAdjust="-180"
hAlign="center"
vAlign="bottom"
autoPosition="true"
draggable="true"
autoHide="false" />
autoHide to be true:<skinElement id="controlBar"
elementClass="com.realeyes.osmfplayer.controls.ControlBar"
initMethod="initControlBarInstance"
scaleMode="none"
hAdjust="0" vAdjust="-180"
hAlign="center"
vAlign="bottom"
autoPosition="true"
draggable="true"
autoHide="true" />
Also, if you move your mouse away from the player the control bar should auto-hide after a short period of time. The control bar should also be visible if you roll over the player again.
Deploying the REOPS player is a simple process of gathering the necessary files and transferring them to your web server. Minimally you will need the following files for a REOPS deployment:
If you use the files from the MyREOPS walkthrough project, you can deploy the REOPS player by uploading the following files from the bin-debug directory to a web server:
The RealEyes OSMF Player Sample leverages some built-in tools provided by the OSMF to make developing media players a less painful and more consistent process. You should have a good idea about how the REOPS uses the OSMF to create a very configurable and flexible media player. Using the external XML configuration file, you should also be able to set up a single player SWF file for multiple uses and deployments quickly and easily.
In this article, we also covered some of the core concepts and components that are needed to build a media player using the OSMF:
This information should help you to build your own media players using the OSMF, even if you don't use the REOPS project as a starting point.
In Part 3 we will explain in detail the control bar and skinning system built into the REOPS project.
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.
Flash User Forum |
More |
| 04/23/2012 | Auto-Save and Auto-Recovery |
|---|---|
| 04/23/2012 | Open hyperlinks in new window/tab/pop-up ? |
| 04/21/2012 | PNG transparencies glitched |
| 04/01/2010 | Workaround for JSFL shape selection bug? |
Flash Cookbooks |
More |
| 02/13/2012 | Randomize an array |
|---|---|
| 02/11/2012 | How to create a Facebook fan page with Flash |
| 02/08/2012 | Digital Clock |
| 01/18/2012 | Recording webcam video & audio in a flv file on local drive |