OSMF 0.8 Examples

Posted: 20/01/10

An image of OSMF 0.8 Examples

Here's another revision to my OSMF examples that started life back in August 2009, which brings then up-to-date with some of the API changes that came out of the Sprint 8 release.

If you're new to OSMF, and particularly if you haven't yet set-up your development environment to start writing OSMF apps, might I suggest you read through Getting set up on the my Intro to OSMF post, as this will get you up and running, then refer back here for the code examples.

As well as addressing issues raised by the development community, the changes in OSMF 0.8 involve some significant modifications to the naming of the interfaces, support for live streams, and sub-clip support.

Example code

PLEASE NOTE: The framework has moved on since these examples were written, please refer to the more recent 0.93 examples.

RTMP Streaming

The great news is that this one hasn't changed in 0.8

package

{

import flash.display.Sprite;

import org.osmf.events.MediaPlayerCapabilityChangeEvent;

import org.osmf.media.MediaPlayer;

import org.osmf.media.URLResource;

import org.osmf.net.NetLoader;

import org.osmf.utils.URL;

import org.osmf.video.VideoElement;

public class BasicOSMFStream extends Sprite

{

private const STREAM:String = "rtmp://localhost/vod/mp4:video.mp4";

private var _player:MediaPlayer;

public function BasicOSMFStream()

{

_player = new MediaPlayer();

_player.addEventListener( MediaPlayerCapabilityChangeEvent.VIEWABLE_CHANGE, onViewable );

_player.element = new VideoElement( new NetLoader(), new URLResource( new URL( STREAM ) ) );

}

private function onViewable( e:MediaPlayerCapabilityChangeEvent ) :void

{

if( e.enabled )

{

addChild( _player.view );

}

}

}

}

HTTP/Progressive download

Notes that there have been some big changes here concerning the loading of media. Improvements to the MediaPlayer class now allow the listeners to be registered directly, and the LoadableStateChangeEvent is no more. LoadEvent is the new event to use, which exposes a loadState property that you can interrogate in the handler.

package

{

import flash.display.Sprite;

import org.osmf.events.LoadEvent;

import org.osmf.events.LoaderEvent;

import org.osmf.events.MediaPlayerCapabilityChangeEvent;

import org.osmf.media.MediaPlayer;

import org.osmf.media.URLResource;

import org.osmf.net.NetLoader;

import org.osmf.traits.LoadState;

import org.osmf.utils.URL;

import org.osmf.video.VideoElement;

public class BasicOSMFProgressive extends Sprite

{

private const PROGRESSIVE:String = "http://localhost/video.mp4";

private var _player:MediaPlayer;

public function BasicOSMFProgressive()

{

_player = new MediaPlayer();

_player.addEventListener( MediaPlayerCapabilityChangeEvent.VIEWABLE_CHANGE, onViewableStateChange );

_player.addEventListener( LoaderEvent.LOAD_STATE_CHANGE, onLoadStateChange );

_player.element = new VideoElement( new NetLoader(), new URLResource( new URL( PROGRESSIVE ) ) );

}

private function onLoadStateChange( e:LoadEvent ) :void

{

if( e.loadState == LoadState.READY )

{

trace( 'load completed' );

}

else if( e.loadState == LoadState.LOAD_ERROR )

{

trace( 'load failed' );

}

}

private function onViewableStateChange( e:MediaPlayerCapabilityChangeEvent ) :void

{

if( e.enabled )

{

addChild( _player.view );

}

}

}

}

Serial composition example using an XML playlist

More context about this implementation can be found on my original Intro to OSMF post.

package

{

import flash.display.Sprite;

import flash.events.Event;

import flash.events.IOErrorEvent;

import flash.net.URLLoader;

import flash.net.URLRequest;

import org.osmf.audio.AudioElement;

import org.osmf.audio.SoundLoader;

import org.osmf.composition.SerialElement;

import org.osmf.events.LoadEvent;

import org.osmf.events.LoaderEvent;

import org.osmf.events.MediaPlayerCapabilityChangeEvent;

import org.osmf.image.ImageElement;

import org.osmf.image.ImageLoader;

import org.osmf.media.LoadableMediaElement;

import org.osmf.media.MediaPlayer;

import org.osmf.media.URLResource;

import org.osmf.net.NetLoader;

import org.osmf.proxies.TemporalProxyElement;

import org.osmf.traits.LoadState;

import org.osmf.traits.MediaTraitType;

import org.osmf.utils.URL;

import org.osmf.video.VideoElement;

public class PlaylistOSMFPlayer extends Sprite

{

private const PLAYLIST_LOCATION:String = "http://localhost/osmfplaylist.xml";

private var _composition:SerialElement;

private var _loader:URLLoader;

private var _player:MediaPlayer;

private var _playlist:XML;

public function PlaylistOSMFPlayer()

{

loadPlaylist();

}

private function loadPlaylist() :void

{

_loader = new URLLoader();

_loader.addEventListener( Event.COMPLETE, onPlaylistLoaded );

_loader.addEventListener( IOErrorEvent.IO_ERROR, onPlaylistFail );

_loader.load( new URLRequest( PLAYLIST_LOCATION ) );

}

private function onPlaylistLoaded( e:Event ) :void

{

_playlist = XML( e.target.data );

parsePlaylist();

playPlaylist();

}

private function parsePlaylist() :void

{

_composition = new SerialElement();

var currentHour:int = new Date().getHours();

for each( var media:XML in _playlist.media )

{

if( currentHour <= int( String( media.@startTime ).split(":")[0] ) )

{

switch( media.@type.toString() )

{

case "video":

_composition.addChild( new VideoElement( new NetLoader(), new URLResource( new URL( media.@source ) ) ) );

break;

case "advert":

_composition.addChild( new VideoElement( new NetLoader(), new URLResource( new URL( media.@source ) ) ) );

break;

case "image":

_composition.addChild( new TemporalProxyElement( 5, new ImageElement( new ImageLoader(), new URLResource( new URL( media.@source ) ) ) ) );

break;

case "audio":

_composition.addChild( new AudioElement( new SoundLoader(), new URLResource( new URL( media.@source ) ) ) );

break;

}

}

}

}

private function playPlaylist() :void

{

if( _composition.numChildren )

{

_player = new MediaPlayer();

_player.addEventListener( MediaPlayerCapabilityChangeEvent.VIEWABLE_CHANGE, onViewable );

_player.addEventListener( MediaPlayerCapabilityChangeEvent.SPATIAL_CHANGE, onSpatial );

_player.addEventListener( LoaderEvent.LOAD_STATE_CHANGE, onLoadStateChange );

_player.element = _composition;

}

}

private function onLoadStateChange( e:LoadEvent ) :void

{

if( e.loadState == LoadState.READY )

{

trace( 'load completed' );

}

else if( e.loadState == LoadState.LOAD_ERROR )

{

trace( 'load failed' );

}

}

private function onPlaylistFail( e:IOErrorEvent ) :void

{

// When the playlist XML fails to loa

}

private function onSpatial( e:MediaPlayerCapabilityChangeEvent ) :void

{

// Hook up spatial components here

}

private function onViewable( e:MediaPlayerCapabilityChangeEvent ) :void

{

if( e.enabled )

{

addChild( _player.view );

}

}

}

}

Notice again that the lines assigning a listener to the ILoadable trait...

var loadable:ILoadable = _player.element.getTrait( MediaTraitType.LOADABLE ) as ILoadable;

loadable.addEventListener( LoadableStateChangeEvent.LOADABLE_STATE_CHANGE, onLoaded );

...which appeared in my earlier example implementations have been replaced with a far simpler listener assignment to the MediaPlayer instance.

_player.addEventListener( LoaderEvent.LOAD_STATE_CHANGE, onLoadStateChange );

Here's the playlist XML document (osmfplaylist.xml) that the code above attempts to load:

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

<playlist>

<media startTime="00:00" type="video" source="http://localhost/a2.mp4" title="video1"/>

<media startTime="01:00" type="advert" source="http://localhost/pcworld.flv" title="advert1"/>

<media startTime="02:00" type="video" source="http://localhost/b2.mp4" title="video2"/>

<media startTime="03:00" type="audio" source="http://localhost/2009_25a.mp3" title="audio1"/>

<media startTime="04:00" type="video" source="http://localhost/a2.mp4" title="video1"/>

<media startTime="05:00" type="advert" source="http://localhost/pcworld.flv" title="advert1"/>

<media startTime="06:00" type="video" source="http://localhost/b2.mp4" title="video2"/>

<media startTime="07:00" type="audio" source="http://localhost/2009_25a.mp3" title="audio1"/>

<media startTime="08:00" type="video" source="http://localhost/a2.mp4" title="video1"/>

<media startTime="09:00" type="advert" source="http://localhost/pcworld.flv" title="advert1"/>

<media startTime="11:00" type="video" source="http://localhost/b2.mp4" title="video2"/>

<media startTime="12:00" type="audio" source="http://localhost/2009_25a.mp3" title="audio1"/>

<media startTime="13:00" type="video" source="http://localhost/a2.mp4" title="video1"/>

<media startTime="14:00" type="advert" source="http://localhost/pcworld.flv" title="advert1"/>

<media startTime="15:00" type="image" source="http://localhost/welcome.png" title="image1"/>

<media startTime="16:00" type="video" source="http://localhost/a2.mp4" title="video1"/>

<media startTime="17:00" type="audio" source="http://localhost/2009_25a.mp3" title="audio1"/>

<media startTime="18:00" type="advert" source="http://localhost/pcworld.flv" title="advert1"/>

<media startTime="19:00" type="image" source="http://localhost/welcome.png" title="image1"/>

<media startTime="20:00" type="audio" source="http://localhost/2009_25a.mp3" title="audio1"/>

<media startTime="21:00" type="video" source="http://localhost/a2.mp4" title="video1"/>

<media startTime="22:00" type="advert" source="http://localhost/pcworld.flv" title="advert1"/>

<media startTime="23:00" type="video" source="http://localhost/b2.mp4" title="video2"/>

</playlist>

Don't forget that there's now a thriving OSMF community that you can participate in at http://adobe.com/go/osmf_usergroup.

You can also follow @OSMF on Twitter.

Download the latest version of OSMF

Keywords for this post: osmf, open source, adobe, media, framework, video, stream, progressive, audio, image, actionscript 3