最近公司需要一款播放器,想着用用adobe官方的osmf。这个框架支持所有flash允许的视频格式,支持HDS,很少的代码就搞定,方便快捷,开发周期短。下了osm以及strobeMediaPlayBackf研究了一下,很好入手。但是当把播放器放到公司网站上发现,视频任一点快进功能没了(公司部署的是伪流服务,使用start =关键帧方式)。再实验,通过现有框架内容,竟然无法获取关键帧信息。懊恼!这么常见东东居然没有。HDS先进,可要银子。只要自己挖掘了。其实在读取视频的duration, width, height等信息的时候,osmf已经取到了视频的元数据信息。不知道是出于什么原因,osmf将keyframes忽略了。只好自己动手搞定。麻烦啊。好在弄出来了, 随便讲一下吧。首先学了一下osmf如何去视频的duration, 发现时在NetStreamTimeTrait中获取,并将NetStreamTimeTrait加入mediaElement中。照葫芦画瓢,弄了个KeyFramesTraits。
package org.osmf.traits
{
import flash.net.NetStream;
import org.osmf.events.KeyFramesEvent;
import org.osmf.net.NetClient;
import org.osmf.net.NetStreamCodes;
[Event(name="keyFramesChange", type="org.osmf.events.KeyFramesEvent")]
public class KeyFramesTraits extends MediaTraitBase
{
public static const KEY_FRAMES:String = "keyFrames";
private var _keyFrames:Object;
private var netStream:NetStream;
public function KeyFramesTraits(netStream:NetStream)
{
super(KEY_FRAMES);
this.netStream = netStream;
NetClient(netStream.client).addHandler(NetStreamCodes.ON_META_DATA, onMetaData);
}
private function onMetaData(value:Object):void
{
if(!value)
return;
if(value["keyframes"])
{
_keyFrames = value["keyframes"];
}
else if(value["seekpoints"])
{
_keyFrames = value["seekpoints"];
}
else
{
_keyFrames = null;
}
dispatchEvent(new KeyFramesEvent(KeyFramesEvent.KEYFRAMES_CHANGE, false, false, _keyFrames));
}
public function get keyFrames():Object
{
return _keyFrames;
}
}
}
其中,dispatchevent了一个事件,如下:
package org.osmf.events
{
import flash.events.Event;
public class KeyFramesEvent extends Event
{
public static const KEYFRAMES_CHANGE:String = "keyFramesChange";
public var _keyFrames:Object;
public function KeyFramesEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, keyFrames:Object = null)
{
super(type, bubbles, cancelable);
_keyFrames = keyFrames;
}
private function get keyFrame():Object
{
return _keyFrames;
}
override public function clone():Event
{
return new KeyFramesEvent(type, bubbles, cancelable, keyFrame);
}
}
}
有了获取关键帧信息的类了,还要把他加入到mediaElement中去,关键帧只有视频才使用,所以扩展了一下videoElement。创建一个AdvancedVideoElement。
package org.osmf.elements
{
import flash.net.NetStream;
import org.osmf.events.KeyFramesEvent;
import org.osmf.media.MediaResourceBase;
import org.osmf.net.NetClient;
import org.osmf.net.NetLoader;
import org.osmf.net.NetStreamCodes;
import org.osmf.net.NetStreamLoadTrait;
import org.osmf.traits.KeyFramesTraits;
import org.osmf.traits.MediaTraitBase;
import org.osmf.traits.MediaTraitType;
public class AdvancedVideoElement extends VideoElement
{
private var stream:NetStream;
public function AdvancedVideoElement(resource:MediaResourceBase=null, loader:NetLoader=null)
{
super(resource, loader);
}
override protected function processReadyState():void
{
super.processReadyState();
addKeyFramesTraits();
}
private function addKeyFramesTraits():void
{
var loadTrait:NetStreamLoadTrait = getTrait(MediaTraitType.LOAD) as NetStreamLoadTrait;
stream = loadTrait.netStream;
// setup dvr trait
var keyFramesTrait:MediaTraitBase = loadTrait.getTrait(KeyFramesTraits.KEY_FRAMES) as KeyFramesTraits;
if (keyFramesTrait == null)
{
keyFramesTrait = new KeyFramesTraits(stream);
}
keyFramesTrait.addEventListener(KeyFramesEvent.KEYFRAMES_CHANGE, onKeyFramesChange);
function onKeyFramesChange(event:KeyFramesEvent = null):void
{
addTrait(KeyFramesTraits.KEY_FRAMES, keyFramesTrait);
}
}
}
}
我们只要创建AdvancedVideoElement,其实就可以获取到keyframes了。osmf中DefaultMediaFactory可以帮助我们创建各种mediaElement,但是我们的AdvancedVideoElement还是不成的。而且扩展DefaultMediaFactory还不成。只要自己弄个facatory了。
package org.osmf.media
{
import org.osmf.elements.AdvancedVideoElement;
import org.osmf.elements.AudioElement;
import org.osmf.elements.F4MElement;
import org.osmf.elements.F4MLoader;
import org.osmf.elements.ImageElement;
import org.osmf.elements.ImageLoader;
import org.osmf.elements.SWFElement;
import org.osmf.elements.SWFLoader;
import org.osmf.elements.SoundLoader;
import org.osmf.elements.VideoElement;
import org.osmf.net.NetLoader;
import org.osmf.net.dvr.DVRCastNetLoader;
import org.osmf.net.rtmpstreaming.RTMPDynamicStreamingNetLoader;
CONFIG::FLASH_10_1
{
import org.osmf.net.httpstreaming.HTTPStreamingNetLoader;
import org.osmf.net.MulticastNetLoader;
}
public class AdvancedMediaFactory extends MediaFactory
{
public function AdvancedMediaFactory()
{
super();
init();
}
private function init():void
{
f4mLoader = new F4MLoader(this);
addItem
( new MediaFactoryItem
( "org.osmf.elements.f4m"
, f4mLoader.canHandleResource
, function():MediaElement
{
return new F4MElement(null, f4mLoader);
}
)
);
dvrCastLoader = new DVRCastNetLoader();
addItem
( new MediaFactoryItem
( "org.osmf.elements.video.dvr.dvrcast"
, dvrCastLoader.canHandleResource
, function():MediaElement
{
return new VideoElement(null, dvrCastLoader);
}
)
);
CONFIG::FLASH_10_1
{
httpStreamingNetLoader = new HTTPStreamingNetLoader();
addItem
( new MediaFactoryItem
( "org.osmf.elements.video.httpstreaming"
, httpStreamingNetLoader.canHandleResource
, function():MediaElement
{
return new AdvancedVideoElement(null, httpStreamingNetLoader);
}
)
);
multicastLoader = new MulticastNetLoader();
addItem
( new MediaFactoryItem
( "org.osmf.elements.video.rtmfp.multicast"
, multicastLoader.canHandleResource
, function():MediaElement
{
return new AdvancedVideoElement(null, multicastLoader);
}
)
);
}
rtmpStreamingNetLoader = new RTMPDynamicStreamingNetLoader();
addItem
( new MediaFactoryItem
( "org.osmf.elements.video.rtmpdynamicStreaming"
, rtmpStreamingNetLoader.canHandleResource
, function():MediaElement
{
return new AdvancedVideoElement(null, rtmpStreamingNetLoader);
}
)
);
netLoader = new NetLoader();
addItem
( new MediaFactoryItem
( "org.osmf.elements.video"
, netLoader.canHandleResource
, function():MediaElement
{
return new AdvancedVideoElement(null, netLoader);
}
)
);
soundLoader = new SoundLoader();
addItem
( new MediaFactoryItem
( "org.osmf.elements.audio"
, soundLoader.canHandleResource
, function():MediaElement
{
return new AudioElement(null, soundLoader);
}
)
);
addItem
( new MediaFactoryItem
( "org.osmf.elements.audio.streaming"
, netLoader.canHandleResource
, function():MediaElement
{
return new AudioElement(null, netLoader);
}
)
);
imageLoader = new ImageLoader();
addItem
( new MediaFactoryItem
( "org.osmf.elements.image"
, imageLoader.canHandleResource
, function():MediaElement
{
return new ImageElement(null, imageLoader);
}
)
);
swfLoader = new SWFLoader();
addItem
( new MediaFactoryItem
( "org.osmf.elements.swf"
, swfLoader.canHandleResource
, function():MediaElement
{
return new SWFElement(null, swfLoader);
}
)
);
}
private var rtmpStreamingNetLoader:RTMPDynamicStreamingNetLoader;
private var f4mLoader:F4MLoader;
private var dvrCastLoader:DVRCastNetLoader;
private var netLoader:NetLoader;
private var imageLoader:ImageLoader;
private var swfLoader:SWFLoader;
private var soundLoader:SoundLoader;
CONFIG::FLASH_10_1
{
private var httpStreamingNetLoader:HTTPStreamingNetLoader;
private var multicastLoader:MulticastNetLoader;
}
}
}
就可以看效果了。创建一个as程序,然后跑跑试试。
package
{
import flash.display.Sprite;
import flash.events.Event;
import org.osmf.containers.MediaContainer;
import org.osmf.events.MediaElementEvent;
import org.osmf.media.AdvancedMediaFactory;
import org.osmf.media.MediaElement;
import org.osmf.media.MediaPlayer;
import org.osmf.media.URLResource;
import org.osmf.traits.KeyFramesTraits;
[SWF(frameRate="25", backgroundColor="#000000", width="800", height="600")]
public class TestDemo extends Sprite
{
private var media:MediaElement;
private var player:MediaPlayer;
private var mediaContainer:MediaContainer;
private var factory:AdvancedMediaFactory;
private var keyFrames:Object;
private var keyFramesTraits:KeyFramesTraits;
public function TestDemo()
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
mediaContainer = new MediaContainer();
mediaContainer.layoutMetadata.percentWidth = 100;
mediaContainer.layoutMetadata.percentHeight = 100;
factory = new AdvancedMediaFactory();
addChild(mediaContainer);
media = factory.createMediaElement(new URLResource("http://192.168.1.103/Attachments/UserFiles/00000000000000000000000000000000/MyResourseFiles/20121109/758614a5b17742c79ccc2a1460a46850.flv"));
media.addEventListener(MediaElementEvent.TRAIT_ADD, traitAdd);
mediaContainer.addMediaElement(media);
player = new MediaPlayer(media);
player.autoPlay = true;
}
private function traitAdd(event:MediaElementEvent):void
{
if(event.traitType == KeyFramesTraits.KEY_FRAMES)
{
getKeyFrames();
}
}
private function getKeyFrames():void
{
keyFramesTraits = media.getTrait(KeyFramesTraits.KEY_FRAMES) as KeyFramesTraits;
if(keyFramesTraits)
{
var kf:Object = keyFramesTraits.keyFrames;
}
}
}
}