7

Been using the PlayerItem.timedMetadata (pasted below) for quite a while and has worked very well. However, it seems that Apple has marked this method as 'Deprecated in iOS 13' and might (or will) be removed.

Xcode does inform me that I have to use another method called "AVPlayerItemMetadataOutput" to which I've never tried. So, looking on the internet (google) I found nothing at all apart from the apple docs (https://developer.apple.com/documentation/avfoundation/avplayeritemmetadataoutput).

override open func observeValue(forKeyPath: String?, of: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    guard forKeyPath == "timedMetadata" else { return }
    guard let meta = PlayerItem.timedMetadata else { return }
    for metadata in meta {
        if let songName = metadata.value(forKey: "value") as? String {
            Variables.MediaInfo = (songName)
            self.MediaBox.text = ("Now Playing \n \(songName)")
            setupNowPlaying()
        }
    }
}

UPDATE!

I have banged my head in Apple Docs for a day or so then it hits me like a brick in the face.

class ViewController: UIViewController,AVPlayerItemMetadataOutputPushDelegate {

weak var myDelegate: AVPlayerItemMetadataOutputPushDelegate?
var playerItem: AVPlayerItem?
var player = AVPlayer()

override func viewDidLoad() {
    super.viewDidLoad()
    print("lets go!")
    let url = URL(string: "<URLREMOVED>")!
    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)
    player.play()
    print("END")
    print(playerItem.automaticallyLoadedAssetKeys.description)
}

func metadataOutput(_ output: AVPlayerItemMetadataOutput, didOutputTimedMetadataGroups groups: [AVTimedMetadataGroup], from track: AVPlayerItemTrack?) {

}


}

SO, this reads the stream for timed Metadata changes and then displays this output:

AVMutableMetadataItem: 0x600002064020, identifier=icy/StreamTitle, keySpace=icy, key class = __NSCFConstantString, key=StreamTitle, commonKey=title, extendedLanguageTag=(null), dataType=(null), time={102328704/44100 = 2320.379}, duration={1/44100 = 0.000}, startDate=(null), extras={\n}, value class=__NSCFString, value=Tina Turner - Way Of The World>

Neat right? SO now all I have to to is filter the icy/StreamTitle into a string and I'm golden! :D

Sparks
  • 171
  • 9
  • I spent an embarrasing amount of time trying to figure this out... the key part I missed was `playerItem.add(metadataOutput)` in my own code. Thanks ;) – ianthetechie Aug 18 '21 at 07:09

1 Answers1

10
    func metadataOutput(_ output: AVPlayerItemMetadataOutput, didOutputTimedMetadataGroups groups: [AVTimedMetadataGroup], from track: AVPlayerItemTrack?) {
    if let item = groups.first?.items.first // make this an AVMetadata item
    {
        item.value(forKeyPath: "value") // looking for that key bro
        let Song = (item.value(forKeyPath: "value")!)
        MetaData = "Now Playing: \n \(Song)" // print the results
    } else {
        MetaData = "MetaData Error" // No Metadata or Could not read
    }
Sparks
  • 171
  • 9
  • 1
    Great stuff on this dude. Helped me out a great deal. – highrankin May 29 '20 at 09:02
  • So, this is a long time coming. I have made slight changes to the above code to also deal with error handling as well. – Sparks Jun 02 '20 at 12:48
  • Hey @Sparks, I was trying to send HLS timed metadata through AWS console as base64 string, but not able to receive it through this method. I only get timestamps but no other metadata, Any solution for this? – Deepak Kumar Jul 08 '20 at 14:25
  • @deepakkumar Sadly, I'm not really an expert and sure why it's not working for you :( Sorry. – Sparks Jul 11 '20 at 22:11