2011-06-07 4 views
2

J'ai écrit un petit lecteur OSMF qui diffuse via RTMP depuis Amazon Cloudfront. Il y a un problème connu, la durée du mp3 n'est pas correctement lue à partir des métadonnées et donc la fonction de recherche ne fonctionne pas. Je sais qu'il existe une solution de contournement impliquant l'utilisation de la fonction getStreamLength de NetConnection, implémentée avec succès dans un lecteur non-OSMF précédent, mais maintenant je ne sais pas comment et quand l'appeler, en termes d'événements et de traits OSMF. Ce code ne fonctionne pas:Recherche OSMF avec Amazon 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 pour une question articulée. Cependant, je n'ai pas la moindre idée de la solution. – JeffryHouser

Répondre

2

La réponse simple

Vous ne pouvez pas passer l'URL complète de flux STREAMING_PATH à cette méthode: loadTrait.connection.call ("getStreamLength", répondeur, STREAMING_PATH);

Vous devez utiliser uniquement le nom du cours d'eau, que le chemin vers la droite de l'instance FMS

Donc, si l'URL (ou connection.uri) est: rtmp: //example.com: 80/_myfms/mp3: le/flux/nom/foo

Vous voulez seulement passer le nom du flux, pas l'instance de serveur: 'mp3: le/flux/nom/foo'

la réponse complexe (Extend Classe 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; 
    } 
} 
} 

Puis, dans l'autre code:

... 
    // 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; 
... 
Questions connexes