6

Can you control how AVURLAsset loads the data it requires? I need to add a custom HTTP header (ICY-MetaData=1) and can't seem to figure out how.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Nicholas Young
  • 233
  • 2
  • 10
  • Please take a look at [this question](http://stackoverflow.com/q/15456130) – Nikolay Mamaev Jan 15 '15 at 01:35
  • Yeah, I've seen that question... and since I'm dealing with streaming data, this doesn't really help. (Note the header I specified in the initial question.) – Nicholas Young Jan 16 '15 at 02:40
  • I meant [this answer](http://stackoverflow.com/a/23713028/1310204) for that question. But not sure if it's an option for you... – Nikolay Mamaev Jan 16 '15 at 04:27
  • I looked at that answer, but I'm only interested in public APIs (as most folks who are building apps are). Given that I couldn't find a reference to all of the APIs mentioned there in Apple's docs (and the fact that XCode 6 wouldn't run them), it's pretty useless. – Nicholas Young Jan 17 '15 at 22:36

2 Answers2

14

Apparently, AVPlayer automatically requests metadata from Icecast. The code below works perfectly.

class ViewController: UIViewController {
    var Player: AVPlayer!
    var PlayerItem: AVPlayerItem!

    override func viewDidLoad() {
        super.viewDidLoad()

        PlayerItem = AVPlayerItem(URL: NSURL(string: "http://live.machine.fm/aac"))
        PlayerItem.addObserver(self, forKeyPath: "timedMetadata", options: nil, context: nil)
        Player = AVPlayer(playerItem: PlayerItem)
        Player.play()
    }

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

        if keyPath != "timedMetadata" { return }

        var data: AVPlayerItem = object as AVPlayerItem

        for item in data.timedMetadata as [AVMetadataItem] {
            println(item.value)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
Nicholas Young
  • 233
  • 2
  • 10
  • 1
    god bless u Nicholas, u saved my job, my nerves and my time, your code works like a charm! u r awesome! – animekun May 04 '15 at 00:27
  • @Greag.Deay I'm glad I was able to help! – Nicholas Young May 11 '15 at 07:10
  • 1
    Hello it is not working for me the part of the override func observeValueForKeyPath... The error is: "Method does not override any method from its superclass" – Nick Jan 08 '16 at 22:05
  • @Nick Just remove the "override" string since you aren't overriding anything, and it should work. – Zac Jan 26 '17 at 01:46
5

Nicolas Young's answer is correct it just needs some small changes to work with Swift 3. There were some red exclamation points so now that I understand key value observation a little better I finally figured out how to fix this

import UIKit
import MediaPlayer

//from the original
//https://stackoverflow.com/a/28057734/1839484

class ViewController: UIViewController {
var Player: AVPlayer!
var PlayerItem: AVPlayerItem!

override func viewDidLoad() {
    super.viewDidLoad()
    let playBackURL = URL(string: "http://ca2.rcast.net:8044/")
    PlayerItem = AVPlayerItem(url: playBackURL!)
    PlayerItem.addObserver(self, forKeyPath: "timedMetadata", options: NSKeyValueObservingOptions(), context: nil)
    Player = AVPlayer(playerItem: PlayerItem)
    Player.play()
}


override func observeValue(forKeyPath: String?, of: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if forKeyPath != "timedMetadata" { return }

    let data: AVPlayerItem = of as! AVPlayerItem

    for item in data.timedMetadata! {
        print(item.value!)
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
}
Ohiovr
  • 977
  • 1
  • 12
  • 22