是否可以使用iPhone SDK中的HTTP实时流媒体读取元数据

时间:2011-01-14 13:12:16

标签: iphone objective-c metadata audio-streaming

使用HTTP Live Streaming方法播放实时流时,是否可以读取当前元数据(例如标题和艺术家)?这适用于iPhone收音机应用程序。

4 个答案:

答案 0 :(得分:21)

不确定这个问题对于作者来说是否仍然存在,但可能对某些人有帮助。经过两天的痛苦,我调查了它很简单。以下是适用于我的代码:

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];

然后:

- (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);
      }
   }
}

就是这样。我不知道为什么Apple没有在AVPlayerItem的文档中提供这个样本来访问流的“标题”,这是现实世界流音频的关键特性。在“AV基础框架参考”中,他们告诉“timedMetadata”无处需要。 Matt的样本不适用于所有流(但AVPlayer会这样做)。

答案 1 :(得分:4)

在swift 2.0中获取元数据信息音乐流:

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

添加此方法:

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
                    }
                }
            }
        }
    }


}

答案 2 :(得分:1)

快速解决方案。这是简单的流音频播放器的示例。您可以使用委托AVPlayerItemMetadataOutputPushDelegate的方法读取元数据。

import UIKit
import AVFoundation

class PlayerViewController: UIViewController {
    var player = AVPlayer()

    override func viewDidLoad() {
        super.viewDidLoad()
        configurePlayer()
        player.play()
    }

    private func configurePlayer() {
        guard let url = URL(string: "Your stream URL") else { return }
        let asset = AVAsset(url: url)
        let playerItem = AVPlayerItem(asset: asset)
        let metadataOutput = AVPlayerItemMetadataOutput(identifiers: nil)
        metadataOutput.setDelegate(self, queue: DispatchQueue.main)
        playerItem.add(metadataOutput)
        player = AVPlayer(playerItem: playerItem)
    }
}

extension PlayerViewController: AVPlayerItemMetadataOutputPushDelegate {
    func metadataOutput(_ output: AVPlayerItemMetadataOutput, didOutputTimedMetadataGroups groups: [AVTimedMetadataGroup], from track: AVPlayerItemTrack?) {
        let item = groups.first?.items.first
        item?.value(forKeyPath: "value")
        print(item!.value(forKeyPath: "value")!)
    }
}

答案 3 :(得分:0)

确实如此,但这并不容易。 Matt Gallagher有关于流音频的nice post on his blog。引用他的话题:

  

最简单的元数据来源   来自HTTP标头。在 - 的里面   handleReadFromStream:事件类型:   方法,使用CFReadStreamCopyProperty   复制   kCFStreamPropertyHTTPResponseHeader   来自CFReadStreamRef的属性,   然后你可以使用   CFHTTPMessageCopyAllHeaderFields到   将标题字段复制出来   响应。对于许多流媒体音频   服务器,流名称是其中之一   这些领域。

     

相当难的来源   元数据是ID3标签。 ID3v1是   总是在文件的末尾(所以   流媒体时无用)。 ID3v2是   位于开头可能更多   访问。

     

我从来没有读过ID3标签,但是我   怀疑如果你缓存第一个   几百千字节的文件   在加载的某个地方,打开缓存   使用AudioFileOpenWithCallbacks和   然后读取kAudioFilePropertyID3Tag   您可以使用AudioFileGetProperty   能够读取ID3数据(如果它   存在)。就像我说的那样:我   从来没有真正这样做,所以我不这样做   确定它会起作用。