[英]is it possible to read metadata using HTTP live streaming in the iPhone SDK
使用 HTTP Live Streaming 方法播放实时流时,是否可以读取当前元数据(例如标题和艺术家)? 这是一个 iPhone 收音机应用程序。
不确定这个问题对其作者来说是否仍然是实际的,但可能会对某人有所帮助。 经过两天的痛苦,我调查了这很简单。 这是对我有用的代码:
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);
}
}
}
就是这样。 我不知道为什么苹果没有在 AVPlayerItem 的文档中提供这个示例来访问流的“标题”,这是现实世界流音频的关键特性。 在“AV Foundation Framework Reference”中,他们在任何需要的地方都没有提到“timedMetadata”。 并且 Matt 的示例不适用于所有流(但 AVPlayer 可以)。
在 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
}
}
}
}
}
}
迅捷的解决方案。 这是一个简单的流式音频播放器示例。 您可以在委托 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")!)
}
}
是的,但这并不容易。 Matt Gallagher 在他的博客上有一篇关于流式音频的好文章。 在这个问题上引用他的话:
最简单的元数据来源来自 HTTP 标头。 在 handleReadFromStream:eventType: 方法中,使用 CFReadStreamCopyProperty 从 CFReadStreamRef 复制 kCFStreamPropertyHTTPResponseHeader 属性,然后您可以使用 CFHTTPMessageCopyAllHeaderFields 从响应中复制标头字段。 对于许多流音频服务器,流名称是这些字段之一。
更难的元数据来源是 ID3 标签。 ID3v1 始终位于文件末尾(因此在流式传输时无用)。 ID3v2 位于开头,因此可能更易于访问。
我从未读过 ID3 标签,但我怀疑如果您在加载文件时将前几百 KB 缓存在某处,请使用 AudioFileOpenWithCallbacks 打开该缓存,然后使用 AudioFileGetProperty 读取 kAudioFilePropertyID3Tag 您可能能够读取 ID3 数据(如果存在)。 就像我说的:我从来没有真正做过这件事,所以我不确定它会起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.