The Uplynk Flash SDK has been deprecated. It is recommended that all customers transition to the Uplynk HTML5 AdaptivePlayer. The documentation for legacy flash-based web browser players is still available for reference.
This guide is provided to assist an integrator with the use of the Uplynk OSMF plugin. By using the plugin with the OSMF, you will be able to create a player with a custom skin and personalized playout experience.
For more details about OSMF, Please visit the Open Source Media Framework website. Adobe also provides the OSMF API online.
Use the Uplynk OSMF plugin to create a custom OSMF player .
http://storage.uplynk.com/client/latest_upLynkOsmfPlugin.swf
If you are using OSMF or an OSMF-based player such as Strobe, you can create a custom player that loads the Uplynk libraries dynamically as follows:
Basic plugin usage:
package { import flash.display.Sprite; import org.osmf.media.MediaPlayerSprite; import org.osmf.media.URLResource; import org.osmf.media.MediaFactory; import org.osmf.media.DefaultMediaFactory; import org.osmf.events.MediaFactoryEvent; import flash.display.StageScaleMode; import flash.display.StageAlign; public class OSMFTestPlayer extends Sprite { private var factory:MediaFactory; private static const MEDIA_URL:String = 'https://content.uplynk.com/content/xxxx.m3u8'; public function OSMFTestPlayer() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; factory = new DefaultMediaFactory(); factory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD, onPluginLoad); var resource:URLResource = new URLResource('http://storage.uplynk.com/client/latest_upLynkOsmfPlugin.swf'); factory.loadPlugin( resource ); } private function onPluginLoad(e:MediaFactoryEvent):void { var sprite:MediaPlayerSprite = new MediaPlayerSprite(null, null, factory); addChild(sprite); sprite.resource = new URLResource(MEDIA_URL); } } }
OSMF uses metadata in order to provide access features inside the OSMF framework. Uplynk provides several metadata hooks that you can use. they are as follows:
Available metadata namespaces:
// Defines namespaces for listening to asset metadata events public static const UPLYNK_ASSET_NAMESPACE:String = "http://www.uplynk.com/streaming/asset/1.0"; public static const UPLYNK_ASSET_NAMESPACE_KEY_ASSET_METADATA:String = "assetMetadata" public static const UPLYNK_ASSET_NAMESPACE_KEY_ID3:String = "ID3" //Defines namespaces for accessing and configuring internal renderer public static const UPLYNK_CAPTION_METADATA_NAMESPACE:String = "http://www.uplynk.com/metadata/caption/1.0"; public static const UPLYNK_CAPTION_KEY_SELECTED_CAPTION:String = "selectedCaption"; public static const UPLYNK_CAPTION_KEY_RENDERER_SETTINGS:String = "rendererSettings"; public static const UPLYNK_CAPTION_KEY_AVAILABLE_VTT_STREAMS:String = "availableVttStreams"; public static const UPLYNK_CAPTION_KEY_AVAILABLE_608_CHANNELS:String = "available608Channels"; //Defines namespaces for accessing internal webvtt subtitling. public static const UPLYNK_WEBVTT_NAMESPACE:String = "http://www.uplynk.com/timeline/webvtt/1.0"; public static const UPLYNK_WEBVTT_KEY_SELECTED_CAPTION:String = "selectedCaption"; public static const UPLYNK_WEBVTT_KEY_WEBVTT:String = "webvtt"; //Defnies namespaces for accessing 608 CC streams public static const UPLYNK_CAPTION_NAMESPACE_v1_1:String = "http://www.uplynk.com/timeline/caption/1.1"; public static const UPLYNK_CAPTION_KEY_CAPTION:String = "caption"; // Defines namespaces for listening to SegmentMap changes public static const UPLYNK_SEGMENTMAP_NAMESPACE:String = "http://www.uplynk.com/stream/segmentmap/1.0"; public static const UPLYNK_SEGMENTMAP_KEY_SEGMENTMAP:String = "segmentMap"
Allows us to listen for CC Data. The data object is as follows {data:Vector.<XML>,mode:String,channel:int,text:String}. data contains a list of xml objects. each line of cc text is in a separate xml object. mode defines it's rendering mode (pop-on,roll-up, etc..). channel indicates it's CC channel. which can be between 0-3. text is a pretty text representation of the data object.
"http://www.uplynk.com/streaming/asset/1.0"
Allows us to listen for asset metadata. Whenever the playhead crosses into a new asset. this event will fire. The Key for the asset metadata is "assetMetadata". the value is an object.
This namespace will also dispatch ID3 data. The key is ID3 and the value is an Object. The object contains two parameters called type and data. Type will indicate the ID3 Frame type and data will indicate the data within that frame.
This metadata object allows us to turn on the default renderer inside the Uplynk plugin. there are three keys used to interface with the Uplynk element when using this metadata as an option. they are: available608Channels, availableVttStreams and selectedCaption. the value of available608Channels will return a vector.<int> of embedded CC channels discovered so far. These CC channels can disappear from a stream without warning. availableVttStreams returns a Vector.<Track>. This is an internal object and will need to be cast to a Vector.<Object> for local storage. Example: var tracks : Vector.<Object> = Vector.<Object>( event.value );. selectedCaption can be an int (0-3) or any of the available tracks.
The SegmentMap metadata provides information about the playout. This can provide helpful information about where server side ads are located in a stream. The value in this metadata object will return a list of vector objects. These are internal objects and will need to be cast to a Vector.<Object> before they can be used. Example: var segments : Vector.<Object> = Vector.<Object>( event.value );. Each object will contain the following properties:
The following is an example of how to setup and listen for different metadata events in a OSMF player. In this example we will setup the internal CC Renderer. select a caption and also listen for assetMetadata.
Internal CC and subtitle support + assetMetadata:
package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; import org.osmf.events.MediaElementEvent; import org.osmf.events.MediaFactoryEvent; import org.osmf.events.MetadataEvent; import org.osmf.events.TimelineMetadataEvent; import org.osmf.media.DefaultMediaFactory; import org.osmf.media.MediaElement; import org.osmf.media.MediaFactory; import org.osmf.media.MediaPlayerSprite; import org.osmf.media.URLResource; import org.osmf.metadata.Metadata; import org.osmf.metadata.TimelineMetadata; [SWF(backgroundColor="#000000")] public class OsmfPlayer extends Sprite { private var factory:MediaFactory; private var mediaPlayer:MediaPlayerSprite; private var mediaElement:MediaElement; private static const MEDIA_URL:String = "https://content.uplynk.com/content/xxxx.m3u8"; private var captionSelected : Boolean = false; public function OsmfPlayer() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; factory = new DefaultMediaFactory(); factory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD, onPluginLoad); factory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD_ERROR, onPluginLoadError); trace('loading plugin'); var resource:URLResource = new URLResource('http://storage.uplynk.com/client/latest_upLynkOsmfPlugin.swf'); factory.loadPlugin(resource); } private function onPluginLoad(e:MediaFactoryEvent):void { var resource : URLResource = new URLResource( MEDIA_URL ); eesource.addMetadataValue( "http://www.uplynk.com/metadata/caption/1.0" , {} ); // Notifies the plugin to use the internal CC renderers mediaPlayer = new MediaPlayerSprite(null, null, factory); addChild(mediaPlayer); mediaElement = factory.createMediaElement(resource); mediaElement.addEventListener(MediaElementEvent.METADATA_ADD, onMetadataAdd); mediaPlayer.media = mediaElement; } private function onPluginLoadError(e:MediaFactoryEvent):void { trace('error loading plugin'); } private function onMetadataAdd(event:MediaElementEvent):void { if( event.namespaceURL == "http://www.uplynk.com/metadata/caption/1.0" ) { var caption:Metadata = mediaElement.getMetadata("http://www.uplynk.com/metadata/caption/1.0") as Metadata; caption.addEventListener(MetadataEvent.VALUE_CHANGE, onCaptionChanged); caption.addEventListener(MetadataEvent.VALUE_ADD, onCaptionChanged); } else if( event.namespaceURL == "http://www.uplynk.com/streaming/asset/1.0" ) { var asset:Metadata = mediaElement.getMetadata("http://www.uplynk.com/streaming/asset/1.0") as Metadata; asset.addEventListener(MetadataEvent.VALUE_CHANGE, onAssetChanged); asset.addEventListener(MetadataEvent.VALUE_ADD, onAssetChanged); } } private function onCaptionChanged(event:MetadataEvent):void { switch(event.key) { case "available608Channels": { //selects the first CC channel. var channels : Vector.<int> = event.value; if(channels.length > 0){ selectCaption(channels[0]); } break; } case "availableVttStreams": { //selects a random track. var tracks : Vector.<Object> = Vector.<Object>( event.value ); if(tracks.length > 0){ var index : int = Math.floor(Math.random()*tracks.length) trace("Selecting Track Index: [" + index + "] Language: " + tracks[index].language); selectCaption(tracks[index]); } break; } } } private function onAssetChanged(event:MetadataEvent):void { switch(event.key) { case "assetMetadata": { // Add your code here to handle new metadata associated with the new asset ID break; } } } private function selectCaption( data : Object) : void { // for this demo we just select the first CC that comes in first. if(!captionSelected){ var caption:Metadata = mediaElement.getMetadata("http://www.uplynk.com/metadata/caption/1.0") as Metadata; caption.addValue("selectedCaption",data); captionSelected = true; } } } }
The following is an example of how to setup and listen for different metadata events in a OSMF player. In this example we will setup our own basic CC renderer and listen for assetMetadata
DIY basic CC support + assetMetadata:
package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; import org.osmf.events.MediaElementEvent; import org.osmf.events.MediaFactoryEvent; import org.osmf.events.MetadataEvent; import org.osmf.events.TimelineMetadataEvent; import org.osmf.media.DefaultMediaFactory; import org.osmf.media.MediaElement; import org.osmf.media.MediaFactory; import org.osmf.media.MediaPlayerSprite; import org.osmf.media.URLResource; import org.osmf.metadata.Metadata; import org.osmf.metadata.TimelineMetadata; [SWF(backgroundColor="#000000")] public class OsmfPlayer extends Sprite { private var _captionsAvailable : Boolean = false; public var captionsEnabled : Boolean = true; private var captionDisplay : TextField; private var factory:MediaFactory; private var mediaPlayer:MediaPlayerSprite; private var mediaElement:MediaElement; private static const MEDIA_URL:String = "https://content.uplynk.com/content/xxxx.m3u8"; public function get captionsAvailable() : Boolean{ return _captionsAvailable } public function OsmfPlayer() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; factory = new DefaultMediaFactory(); factory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD, onPluginLoad); factory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD_ERROR, onPluginLoadError); trace('loading plugin'); var resource:URLResource = new URLResource('http://storage.uplynk.com/client/latest_upLynkOsmfPlugin.swf'); factory.loadPlugin(resource); } private function onPluginLoad(e:MediaFactoryEvent):void { var resource : URLResource = new URLResource( MEDIA_URL ); mediaPlayer = new MediaPlayerSprite(null, null, factory); addChild(mediaPlayer); mediaElement = factory.createMediaElement(resource); mediaElement.addEventListener(MediaElementEvent.METADATA_ADD, onMetadataAdd); initializecaption(); mediaPlayer.media = mediaElement; } private function onPluginLoadError(e:MediaFactoryEvent):void { trace('error loading plugin'); } private function onMetadataAdd(event:MediaElementEvent):void { if (event.namespaceURL == "http://www.uplynk.com/timeline/caption/1.1") { var oldCaptionMetadata:Metadata = mediaElement.getMetadata("http://www.uplynk.com/timeline/caption/1.1") as Metadata; oldCaptionMetadata.addEventListener(MetadataEvent.VALUE_CHANGE, onCaption); oldCaptionMetadata.addEventListener(MetadataEvent.VALUE_ADD, onCaption); } else if( event.namespaceURL == "http://www.uplynk.com/streaming/asset/1.0" ) { var asset:Metadata = mediaElement.getMetadata("http://www.uplynk.com/streaming/asset/1.0") as Metadata; asset.addEventListener(MetadataEvent.VALUE_CHANGE, onAssetChanged); asset.addEventListener(MetadataEvent.VALUE_ADD, onAssetChanged); } } private function initializecaption() : void { captionDisplay = new TextField(); captionDisplay.visible = false; captionDisplay.autoSize = TextFieldAutoSize.LEFT; captionDisplay.multiline = true; captionDisplay.background = true; captionDisplay.backgroundColor = 0x000000; var defaultFormat:TextFormat = new TextFormat(); defaultFormat.color = 0xFFFFFF; defaultFormat.font = "Verdana"; defaultFormat.size = 16; captionDisplay.defaultTextFormat = defaultFormat; addChild( captionDisplay ); } private function onCaption(event:MetadataEvent):void { var captionData : Object = event.value; _captionsAvailable = true; if(captionsEnabled){ captionDisplay.htmlText= captionData.text; captionDisplay.visible = true; captionDisplay.x = (stage.stageWidth - captionDisplay.width) / 2; captionDisplay.y = stage.stageHeight - captionDisplay.height - 50; } } private function onAssetChanged(event:MetadataEvent):void { switch(event.key) { case "assetMetadata": { // Add your code here to handle new metadata associated with the new asset ID break; } } } } }
The following is an example of how to setup and listen for different metadata events in a OSMF player. In this example we will setup listen for ID3 and segment map events
DIY basic CC support + assetMetadata:
package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; import org.osmf.events.MediaElementEvent; import org.osmf.events.MediaFactoryEvent; import org.osmf.events.MetadataEvent; import org.osmf.events.TimelineMetadataEvent; import org.osmf.media.DefaultMediaFactory; import org.osmf.media.MediaElement; import org.osmf.media.MediaFactory; import org.osmf.media.MediaPlayerSprite; import org.osmf.media.URLResource; import org.osmf.metadata.Metadata; import org.osmf.metadata.TimelineMetadata; [SWF(backgroundColor="#000000")] public class OsmfPlayer extends Sprite { private var factory:MediaFactory; private var mediaPlayer:MediaPlayerSprite; private var mediaElement:MediaElement; private static const MEDIA_URL:String = "https://content.uplynk.com/content/xxxx.m3u8"; public function OsmfPlayer() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; factory = new DefaultMediaFactory(); factory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD, onPluginLoad); factory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD_ERROR, onPluginLoadError); trace('loading plugin'); var resource:URLResource = new URLResource('http://storage.uplynk.com/client/latest_upLynkOsmfPlugin.swf'); factory.loadPlugin(resource); } private function onPluginLoad(e:MediaFactoryEvent):void { var resource : URLResource = new URLResource( MEDIA_URL ); mediaPlayer = new MediaPlayerSprite(null, null, factory); addChild(mediaPlayer); mediaElement = factory.createMediaElement(resource); mediaElement.addEventListener(MediaElementEvent.METADATA_ADD, onMetadataAdd); mediaPlayer.media = mediaElement; } private function onPluginLoadError(e:MediaFactoryEvent):void { trace('error loading plugin'); } private function onMetadataAdd(event:MediaElementEvent):void { if( event.namespaceURL == "http://www.uplynk.com/streaming/asset/1.0" ) { var asset:Metadata = mediaElement.getMetadata("http://www.uplynk.com/streaming/asset/1.0") as Metadata; asset.addEventListener(MetadataEvent.VALUE_CHANGE, onAssetChanged); asset.addEventListener(MetadataEvent.VALUE_ADD, onAssetChanged); } else if( event.namespaceURL == "http://www.uplynk.com/stream/segmentmap/1.0" ) { var segment:Metadata = mediaElement.getMetadata("http://www.uplynk.com/stream/segmentmap/1.0") as Metadata; segment.addEventListener(MetadataEvent.VALUE_CHANGE, onSegmentMapChanged); segment.addEventListener(MetadataEvent.VALUE_ADD, onSegmentMapChanged); } } private function onAssetChanged(event:MetadataEvent):void { if(event.key == "ID3") { if(event.value.type == "TXXX") { trace( "TXXX: " + event.value.data); } break; } } private function onSegmentMapChanged(event:MetadataEvent):void { if(event.key == "segmentMap") { var segments : Vector.<Object> = Vector.<Object>( event.value ); for each( var segment : Object in segments){ trace("Asset ID: " + segment.id +"\n" + "Type: " + segment.type +"\n" + "Index: " + segment.index +"\n" + "Position: " + segment.position +"\n" + "Duration: " + segment.duration ); } } } } }
The following is an example of how to setup and listen for different trait events in order to handle events dealing with dynamic streaming and switching audio sources
Plugin with advanced traits:
package { import flash.display.Sprite; import org.osmf.media.MediaPlayerSprite; import org.osmf.media.URLResource; import org.osmf.media.MediaFactory; import org.osmf.media.DefaultMediaFactory; import org.osmf.events.MediaFactoryEvent; import flash.display.StageScaleMode; import flash.display.StageAlign; import org.osmf.events.AlternativeAudioEvent; import org.osmf.events.DynamicStreamEvent; public class OSMFTestPlayer extends Sprite { private var factory:MediaFactory; private static const MEDIA_URL:String = 'https://content.uplynk.com/content/xxxx.m3u8'; public function OSMFTestPlayer() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; factory = new DefaultMediaFactory(); factory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD, onPluginLoad); var resource:URLResource = new URLResource('http://storage.uplynk.com/client/latest_upLynkOsmfPlugin.swf'); factory.loadPlugin( resource ); } private function onPluginLoad(e:MediaFactoryEvent):void { var sprite:MediaPlayerSprite = new MediaPlayerSprite(null, null, factory); mediaPlayerSprite.mediaPlayer.addEventListener(AlternativeAudioEvent.NUM_ALTERNATIVE_AUDIO_STREAMS_CHANGE, onNumAlternativeAudioStreamsChange); mediaPlayerSprite.mediaPlayer.addEventListener(AlternativeAudioEvent.AUDIO_SWITCHING_CHANGE, onAlternateAudioSwitchingChange); mediaPlayerSprite.mediaPlayer.addEventListener(DynamicStreamEvent.AUTO_SWITCH_CHANGE, onAutoSwitchChange); mediaPlayerSprite.mediaPlayer.addEventListener(DynamicStreamEvent.NUM_DYNAMIC_STREAMS_CHANGE, onNumDynamicStreamsChange); mediaPlayerSprite.mediaPlayer.addEventListener(DynamicStreamEvent.SWITCHING_CHANGE, onSwitchingChange); addChild(sprite); sprite.resource = new URLResource(MEDIA_URL); } private function onNumAlternativeAudioStreamsChange(event:AlternativeAudioEvent):void { if (mediaPlayerSprite.mediaPlayer.hasAlternativeAudio) { //Code to handle what to do if the audio streams available change. } } private function onAlternateAudioSwitchingChange(event:AlternativeAudioEvent):void { if (event.switching) { // Code to handle alternative audio stream switch in progress } else { // Code to handle alternate audio stream switch completed } } private function onAutoSwitchChange(event:DynamicStreamEvent):void { // If auto switch logic has been enabled / disabled } private function onNumDynamicStreamsChange(event:DynamicStreamEvent):void { // code to handle when the number of dynamic streams has changed. } private function onSwitchingChange(event:DynamicStreamEvent):void { // Code to indicate if are switching bit-rates } } }
The Kaltura video player is based on OSMF and loads plugins that are compatible with OSMF plugins. To use Uplynk content with your Kaltura-based player, you will have to create your own plugin that loads the Uplynk OSMF plugin. Sample code is available on Kaltura integration instructions page. Once when you have compiled your swf you can place it in your player's plugins folder:
~/KDP3$ ll plugins/ total 1000 -rw-rw-r-- 1 user staff 346843 Oct 21 09:01 upLynkKalturaPlugin.swf -rw-r--r--@ 1 user staff 141327 Oct 12 10:21 kalturaMixPlugin.swf -rw-r--r--@ 1 user staff 8944 Oct 12 10:21 statisticsPlugin.swf
Next, edit your config.xml file and add a <Plugin> element. Typically this is added inside the player VBox element:
<layout id="full" skinPath="assets/skin.swf"> <VBox id="player" width="100%" height="100%" styleName="black"> <Plugin id="upLynkKaltura" width="0%" height="0%" includeInLayout="false" /> <Plugin id="statistics" width="0%" height="0%" includeInLayout="false" /> ...
Finally, to play the content, set the sourceType to url, the streamerType to rtmp, and the entityId to the asset's playback URL. How this is done depends on your specific project; web pages that start Kaltura via Javascript often use the AC_FL_RunContent function, so the above parameters would be specified there:
AC_FL_RunContent( "src", "kdp3", "width", "800", "height", "360", "allowFullScreen", "true", "id", "kdp3", "quality", "high", "bgcolor", "#eeeeee", "name", "kdp3", "allowScriptAccess","always", "type", "application/x-shockwave-flash", "flashvars","sourceType=url"+ "&autoPlay=true"+ //autoplay mode "&streamerType=rtmp"+ // to enable seeking "&entryId=https://content.uplynk.com/37d6fd87f71141dbb1638e1cdf4ea93f.m3u8"+ ...
For additional information, please see the Kaltura plugin integration instructions.