Building Flex video applications with OSMF

Posted: 28/01/11

An image of Building Flex video applications with OSMF

It was a real pleasure to be invited to speak at the first Flex London User Group meeting of 2011, which took place at Academy Class HQ in Waterloo on 26th Jan. This is the presentation I had planned to deliver a Flex and the City last year, and covers getting OSMF working in a manner that respects the layouts defined by Flex containers.

As promised I've uploaded my slide deck.

Examples

* Please compile these against the Flex 4.5 (Hero) SDK or better.

Displaying an OSMF-derived video player in Flex using the <s:VideoPlayer/> component:

<?xml version="1.0" encoding="utf-8"?>

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:s="library://ns.adobe.com/flex/spark"

xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">

<fx:Declarations>

<!-- Place non-visual elements (e.g., services, value objects) here -->

</fx:Declarations>

<fx:Script>

<![CDATA[

private const RTMP:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short";

private const HTTP:String = "http://mediapm.edgesuite.net/osmf/content/test/manifest-files/dynamic_Streaming.f4m";

]]>

</fx:Script>

<s:VideoPlayer width="100%" height="100%" source="{HTTP}"/>

</s:Application>

The HTTP URL streams a F4M chunked video using HTTP protocol, whereas the RTMP URL streams video from an FMS server using the RTMP protocol.

A custom OSMF implementation - using the MediaPlayer, MediaContainer and MediaElement classes from the framework.

The MediaContainer is added as child of a UIComponent instance, as being part of a pure AS3.0 framework MediaContainer extends Sprite. To allow its use in the context of a Flex container, we need to wrap it inside a UIComponent:

<?xml version="1.0" encoding="utf-8"?>

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:s="library://ns.adobe.com/flex/spark"

xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" creationComplete="init()">

<fx:Declarations>

<!-- Place non-visual elements (e.g., services, value objects) here -->

</fx:Declarations>

<fx:Script>

<![CDATA[

import org.osmf.containers.MediaContainer;

import org.osmf.elements.VideoElement;

import org.osmf.media.MediaPlayer;

import org.osmf.net.NetLoader;

import org.osmf.net.StreamingURLResource;

private const RTMP:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short";

private const HTTP:String = "http://mediapm.edgesuite.net/osmf/content/test/manifest-files/dynamic_Streaming.f4m";

private var _mediaPlayer:MediaPlayer;

private var _container:MediaContainer;

private var _media:VideoElement;

private function init() :void

{

_media = new VideoElement( new StreamingURLResource( RTMP ), new NetLoader() );

_mediaPlayer = new MediaPlayer();

_mediaPlayer.media = _media;

_container = new MediaContainer();

_container.addMediaElement( _media );

playerContainer.addChild( _container );

}

]]>

</fx:Script>

<s:Panel>

<mx:UIComponent id="playerContainer"/>

</s:Panel>

</s:Application>

Creating a custom Flex OSMF video display component

In this example, the OSMF code is encapsulated inside a UIComponent to enable sizing to occur in line with parent container constraints and changes. At the moment the component only exposes a source property to allow setting the media to play, though this could be expanded to allow access to many of the MediaPlayer's properties.

First the Application that implements the component:

<?xml version="1.0" encoding="utf-8"?>

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:s="library://ns.adobe.com/flex/spark"

xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:flexosmf="com.jodieorourke.flexosmf.*">

<fx:Declarations>

<!-- Place non-visual elements (e.g., services, value objects) here -->

</fx:Declarations>

<fx:Script>

<![CDATA[

import mx.containers.BoxDirection;

private const RTMP:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short";

private const HTTP:String = "http://mediapm.edgesuite.net/osmf/content/test/manifest-files/dynamic_Streaming.f4m";

]]>

</fx:Script>

<mx:DividedBox direction="{BoxDirection.HORIZONTAL}">

<s:Panel title="My OSMF Player Component 1">

<flexosmf:FlexOSMFVideoDisplay source="{HTTP}"/>

</s:Panel>

<s:Panel title="My OSMF Player Component 2">

<flexosmf:FlexOSMFVideoDisplay source="{RTMP}"/>

</s:Panel>

</mx:DividedBox>

</s:Application>

Then the component code:

package com.jodieorourke.flexosmf

{

import mx.core.UIComponent;

import org.osmf.containers.MediaContainer;

import org.osmf.elements.VideoElement;

import org.osmf.events.DisplayObjectEvent;

import org.osmf.media.DefaultMediaFactory;

import org.osmf.media.MediaElement;

import org.osmf.media.MediaFactory;

import org.osmf.media.MediaPlayer;

import org.osmf.media.URLResource;

public class FlexOSMFVideoDisplay extends UIComponent

{

private var _mediaPlayer:MediaPlayer;

private var _container:MediaContainer;

private var _source:String;

private var _element:MediaElement;

private var _mediaFactory:DefaultMediaFactory;

public function FlexOSMFVideoDisplay()

{

super();

percentWidth = percentHeight = 100;

minWidth = minHeight = 5;

}

override protected function createChildren() :void

{

super.createChildren();

_mediaFactory = new DefaultMediaFactory();

_mediaPlayer = new MediaPlayer();

_mediaPlayer.addEventListener( DisplayObjectEvent.MEDIA_SIZE_CHANGE, onMediaSizeChange );

_container = new MediaContainer();

addChild( _container );

if( _source )

{

playMedia();

}

}

override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ) :void

{

super.updateDisplayList( unscaledWidth, unscaledHeight );

if( _container )

{

_container.width = unscaledWidth;

_container.height = unscaledHeight;

}

}

override protected function measure() :void

{

super.measure();

measuredWidth = _mediaPlayer.mediaWidth;

measuredHeight = _mediaPlayer.mediaHeight;

measuredMinWidth = measuredMinHeight = 5;

}

protected function playMedia() :void

{

if( _mediaPlayer )

{

if( _element )

{

if( _container.containsMediaElement( _element ) )

{

_container.removeMediaElement( _element );

}

}

_element = _mediaFactory.createMediaElement( new URLResource( _source ) );

_mediaPlayer.media = _element;

_container.addMediaElement( _element );

}

}

protected function onMediaSizeChange( e:DisplayObjectEvent ) :void

{

e.stopPropagation();

invalidateSize();

invalidateDisplayList();

}

public function set source( value:String ) :void

{

_source = value;

playMedia();

}

}

}

More about getting started with OSMF

Keywords for this post: osmf, flex, actionscript 3, video, london, user group