2011-01-14 8 views

Antwort

0

Es ist, aber es ist nicht einfach. Matt Gallagher hat eine nice post on his blog über Streaming-Audio. Um ihn zu diesem Thema zu zitieren:

Die einfachste Quelle für Metadaten kommt aus den HTTP-Headern. Im Innern der handleReadFromStream: eventtype: Methode verwenden CFReadStreamCopyProperty die kCFStreamPropertyHTTPResponseHeader Eigenschaft aus der CFReadStreamRef zu kopieren, dann können Sie CFHTTPMessageCopyAllHeaderFields verwenden, um die Header-Felder aus der Antwort kopieren. Für viele Streaming-Audio Server ist der Stream-Name einer der diese Felder.

Die wesentlich schwierigere Quelle von Metadaten sind die ID3-Tags. ID3v1 ist immer am Ende der Datei (so ist nutzlos beim Streaming). ID3v2 ist befindet sich am Anfang, so kann mehr zugänglich sein.

Ich habe nie die ID3-Tags lesen, aber ich dass vermute, wenn man die ersten paar hundert Kilobyte der Datei-Cache irgendwo wie es lädt, dass Cache öffnen mit AudioFileOpenWithCallbacks und dann die kAudioFilePropertyID3Tag mit AudioFileGetProperty lesen Sie können in der Lage sein, die ID3-Daten zu lesen (wenn es existiert). Wie ich schon sagte: Ich habe nie wirklich getan, damit ich nicht sicher weiß, dass es funktionieren würde.

+0

Wenn Sie diese Arbeit tun bekommen, lassen Sie mich wissen. – Moshe

+0

Ja, in iTunes, wenn eine .m3u-Datei streamt, werden die Informationen zu Titel und Interpret automatisch aktualisiert. vielleicht wird die ID3v2 durchweg gestreamt-- am Anfang jedes Tracks, wie du gesagt hast. Vielleicht ist es nur eine Frage eines Ereignis-Listeners, der auf Metadaten wartet - ich werde weiter suchen. – miketucker

+0

@mike yep.Werfen Sie einen Blick auf Matts Code, die neueste Version ist auf GitHub. Es sollte nette Hinweise geben. – Moshe

20

Nicht sicher, dass diese Frage für seinen Autor noch aktuell ist, aber möglicherweise wird es jemandem helfen. Nach zwei Tagen mit Schmerzen habe ich untersucht, dass es ganz einfach ist. Hier ist der Code, der für mich funktioniert:

AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:<here your http stream url>]]; 

[playerItem addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionNew context:nil]; 

AVPlayer* player = [[AVPlayer playerWithPlayerItem:playerItem] retain]; 
[player play]; 

und dann:

- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object 
         change:(NSDictionary*)change context:(void*)context { 

    if ([keyPath isEqualToString:@"timedMetadata"]) 
    { 
     AVPlayerItem* playerItem = object; 

     for (AVMetadataItem* metadata in playerItem.timedMetadata) 
     { 
     NSLog(@"\nkey: %@\nkeySpace: %@\ncommonKey: %@\nvalue: %@", [metadata.key description], metadata.keySpace, metadata.commonKey, metadata.stringValue); 
     } 
    } 
} 

Das ist es. Ich weiß nicht, warum Apple in den Dokumenten für AVPlayerItem dieses Beispiel für den Zugriff "Titel" des Streams nicht zur Verfügung gestellt hat, der das Schlüsselfeature für das reale Audio-Streaming ist. In "AV Foundation Framework Reference" erzählen sie nirgends von "timedMetadata", wo sie gebraucht werden. Und Matts Sample funktioniert nicht mit allen Streams (aber AVPlayer tut es).

+0

Nicht sicher, warum dies nie als die richtige Antwort markiert wurde, aber es sollte wirklich markiert werden. In einem kontinuierlichen Stream, für Radio-App, was kann getan werden, damit es die Metadaten bekommen, sobald die aktuelle Audiodatei abgespielt hat, und die neue beginnt zu spielen? – user717452

+0

Der obige Code wird immer dann aufgerufen, wenn der Wert 'timedMetadata' geändert wird. Bei der Wiedergabe eines Webstreams (wie Internet Radio) wird daher bei der Änderung der Parameter 'observeValueForKeyPath: ofObject: change: context:' ausgelöst. – rckoenes

+0

Oben sollte als die richtige Antwort gewählt werden, weiß nicht warum, aber es hilft mir sehr. Vielen Dank. –

3

in swift 2.0 bekommen Metadaten info Musik-Streaming:

PlayerItem.addObserver(self, forKeyPath: "timedMetadata", options: NSKeyValueObservingOptions.New, context: nil) 

diese Methode hinzufügen:

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { 

    //Atualiza Nome Musica 
    if keyPath == "timedMetadata" { 
     if let meta = PlayerItem.timedMetadata { 
      print("Novo Metadata \(meta)") 
      for metadata in meta { 
       if let nomemusica = metadata.valueForKey("value") as? String{ 
        LB_NomeMusica.text = nomemusica 
        if NSClassFromString("MPNowPlayingInfoCenter") != nil { 
         let image:UIImage = UIImage(named: "logo.gif")! 
         let albumArt = MPMediaItemArtwork(image: image) 
         var songInfo: [String:AnyObject] = [ 
          MPMediaItemPropertyTitle: nomemusica, 
          MPMediaItemPropertyArtist: "Ao Vivo", 
          MPMediaItemPropertyArtwork: albumArt 
         ] 
         MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo = songInfo 
        } 
       } 
      } 
     } 
    } 


} 
Verwandte Themen