2011-06-07 67 views
2

我已經寫了一個OSMF播放器,通過從亞馬遜Cloudfront RTMP流。有一個已知的問題,mp3的持續時間不正確地從元數據中獲得,因此查找功能不起作用。 我知道有一種解決方法暗示了使用NetConnection的getStreamLength函數,該函數在以前的非OSMF播放器中成功實現,但現在我不知道如何以及何時調用OSMF Events和Traits。 此代碼是不工作:OSMF尋求與亞馬遜Cloudfront

protected function initApp():void 
    { 
    //the pointer to the media 
    var resource:URLResource = new URLResource(STREAMING_PATH); 

    // Create a mediafactory instance 
    mediaFactory = new DefaultMediaFactory(); 

    //creates and sets the MediaElement (generic) with a resource and path 
    element = mediaFactory.createMediaElement(resource); 

    var loadTrait:NetStreamLoadTrait = element.getTrait(MediaTraitType.LOAD) as NetStreamLoadTrait; 
    loadTrait.addEventListener(LoaderEvent.LOAD_STATE_CHANGE, _onLoaded); 
    player = new MediaPlayer(element); 

    //Marker 5: Add MediaPlayer listeners for media size and current time change 
    player.addEventListener(DisplayObjectEvent.MEDIA_SIZE_CHANGE, _onSizeChange); 
    player.addEventListener(TimeEvent.CURRENT_TIME_CHANGE, _onProgress); 

    initControlBar(); 
    } 
    private function onGetStreamLength(result:Object):void { 
    Alert.show("The stream length is " + result + " seconds"); 
    duration = Number(result); 
    } 

    private function _onLoaded(e:LoaderEvent):void 
    { 
    if (e.newState == LoadState.READY) 
    { 
     var loadTrait:NetStreamLoadTrait = player.media.getTrait(MediaTraitType.LOAD) as NetStreamLoadTrait; 

     if (loadTrait && loadTrait.netStream) 

     { 
     var responder:Responder = new Responder(onGetStreamLength); 
     loadTrait.connection.call("getStreamLength", responder, STREAMING_PATH); 
     } 
    } 
    } 
+0

+1一個口齒伶俐的問題。儘管如此,我還沒有最清楚的解決方案。 – JeffryHouser 2011-06-07 12:31:30

回答

2

答案很簡單:

不能充分直播網址STREAMING_PATH傳遞給該方法: loadTrait.connection.call( 「getStreamLength」,響應者,STREAMING_PATH);

您需要使用只是流名稱,該路徑FMS實例的右側

因此,如果該URL(或connection.uri)是: RTMP://示例.com:80/_myfms/MP3:在/流/名/富

你只是想通過流名稱,而不是服務器實例: 「MP3:在/流/名/富」

複雜的答案(擴展NetLoader類):

package{ 
// You can extend the NetLoader class to have it automatically ask for duration 
// and dispatch an event when it is received. 

// This is a super simple, partial example, but the stub should get you going 

// TODO: define imports here (omitted for example's sake) 

class MyNetLoader extends NetLoader 
{ 
    // useful for adding an event listener outside 
    public static const GOT_STREAM_DURATION:String = "gotStreamDuration"; 

    // constructor 
    public function MyNetLoader(factory:NetConnectionFactoryBase = null) 
    { 
    super(factory); 
    } 

    // override the parent method that creates the actual NetStream 
    override protected function createNetStream(connection:NetConnection, resource:URLResource) : NetStream 
    { 
    // usually you pass just the stream name, not the full uri 
    // there is likely a cleaner way to extract the stream name... 
    var streamName:String = resource.url.replace('rtmp://example.com:80/_myfms/', ''); 

    // request duration from FMS 
    connection.call('getStreamLength', new Responder(this.onResult), streamName); 

    return super.createNetStream(connection, resource); 
    } 

    // receives the getStreamLength callback from FMS 
    protected function onResult(info:Object):void 
    { 
    _duration = Number(info) * 1000; // duration, in ms 

    dispatchEvent(new Event(GOT_STREAM_DURATION)); 

    trace('Duration is: ' + _duration); 
    } 
    // read-only getter for duration 
    public function get duration():uint 
    { 
    return _duration as uint; 
    } 
} 
} 

然後,在你的其他代碼:

... 
    // create the resource 
    var resource:URLResource = new URLResource('rtmp://example.com:80/_something/the/stream/name/foo'); 

    // create your custom loader, adding a listener for the duration callback 
    var loader:MyNetLoader = new MyNetLoader(); 

    // listen for the duration event 
    loader.addEventListner(MyNetLoader.GOT_STREAM_DURATION, function(event:Event):void{ 
      trace('Got the duration outside: ' + (event.target as MyNetLoader).duration); 
    }); 

    // I use an AudioElement here, but it could be any of the typed or generic elements 
    // as long as the constructor accepts (resource, loader) 
    // You dont want to use the factory to create the element, because (to my knowledge) 
    // you cant pass a custom loader to the factory (unless you extended it) 
    var myElement:AudioElement = new AudioElement(resource, loader); 

    // pass the element to the player. I dont pass to the constructor in this example because 
    // in most real-world cases, you would already have an instance of MediaPlayer 
    player = new MediaPlayer(); 
    player.media = myElement; 
...