如何从swift / AVKIT的HLS流中读取id3标签/其他元数据

时间:2019-09-25 13:05:04

标签: swift avplayer http-live-streaming id3 m3u8

我正在尝试收集有关如何从iOS应用程序中的HLS流读取元数据的一些知识。 以下HLS流具有一些我想阅读的ID3标签: HLS test stream

在Safari的Web检查器中,我能够在控制台中看到很多数据对象,每个对象都有元数据:

enter image description here

在Web检查器的“网络”标签中,我可以阅读播放列表文件:

#EXTM3U
#EXT-X-VERSION:5
#EXT-X-MEDIA-SEQUENCE:89147
#EXT-X-TARGETDURATION:20
#EXT-X-PROGRAM-DATE-TIME:2019-09-25T11:35:23.401Z
#EXTINF:19.970,
05-20190925T113523Z.aac
#EXTINF:19.970,
05-20190925T113543Z.aac
#EXTINF:19.970,
05-20190925T113603Z.aac
#EXTINF:19.970,
05-20190925T113623Z.aac
#EXTINF:19.970,
05-20190925T113643Z.aac
#EXTINF:19.970,
05-20190925T113703Z.aac

到目前为止,我已经实现了一个使用AVPlayer实例播放此流的类。它工作正常。

我打印了从AVPlayerAVPlayerItem到Xcode控制台的各种属性。 但是,我只能解释的属性是AVPlayerItem.currentTime,该属性为我提供了播放列表文件中的EXT-X-PROGRAM-DATE-TIME的值。 其他所有属性似乎与我在播放列表和id3标签中看到的信息无关。

有什么办法可以读取每个id3标签中包含的元数据? 如何从播放列表中读取EXT-X-TARGETDURATION

我了解了AVPlayerItemMetadataCollector,但是我不知道应该怎么做,以及这是否有助于我阅读HLS流中的元数据。

1 个答案:

答案 0 :(得分:0)

这是我实现的方式:

import UIKit
import AVKit
import AVFoundation
import MediaPlayer

class ViewController: UIViewController{

    let player = AVPlayer()
    var playerItem: AVPlayerItem!
    let asset = AVAsset(url: URL(string: "https://db2.indexcom.com/bucket/ram/00/05/05.m3u8")!)

    override func viewDidLoad() {
        prepareToPlay()
        player.play()
    }

    func prepareToPlay() {
        playerItem = AVPlayerItem(asset: asset)
        playerItem.addObserver(self, forKeyPath: "timedMetadata", options: [], context: nil)
        player.replaceCurrentItem(with: playerItem)
        printTimeStamp()
    }

    func printTimeStamp() {
        print("▼⎺▼⎺▼⎺▼⎺▼⎺▼⎺▼⎺▼")
        print("PROGRAM-DATE-TIME: ")
        print(playerItem.currentDate() ?? "No timeStamp")
        print("▲_▲_▲_▲_▲_▲_▲_▲\n\n")
    }

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

        printTimeStamp()

        let data: AVPlayerItem = of as! AVPlayerItem

        guard let timedMetadata = data.timedMetadata else { return }

        for item in timedMetadata {
            switch item.commonKey {

            case .commonKeyAlbumName?:
                print("AlbumName: \(item.value!)")
            case .commonKeyArtist?:
                print("Artist: \(item.value!)")
            case .commonKeyArtwork?:
                print("Artwork: \(item.value!)")
            case .commonKeyAuthor?:
                print("Author: \(item.value!)")
            case .commonKeyContributor?:
                print("Contributor: \(item.value!)")
            case .commonKeyCopyrights?:
                print("Copyrights: \(item.value!)")
            case .commonKeyCreationDate?:
                print("CreationDate: \(item.value!)")
            case .commonKeyCreator?:
                print("creator: \(item.value!)")
            case .commonKeyDescription?:
                print("Description: \(item.value!)")
            case .commonKeyFormat?:
                print("Format: \(item.value!)")
            case .commonKeyIdentifier?:
                print("Identifier: \(item.value!)")
            case .commonKeyLanguage?:
                print("Language: \(item.value!)")
            case .commonKeyMake?:
                print("Make: \(item.value!)")
            case .commonKeyModel?:
                print("Model: \(item.value!)")
            case .commonKeyPublisher?:
                print("Publisher: \(item.value!)")
            case .commonKeyRelation?:
                print("Relation: \(item.value!)")
            case .commonKeySoftware?:
                print("Software: \(item.value!)")
            case .commonKeySubject?:
                print("Subject: \(item.value!)")
            case .commonKeyTitle?:
                print("Title: \(item.value!)")
            case .commonKeyType?:
                print("Type: \(item.value!)")

            case .id3MetadataKeyAlbumTitle?:
                print("id3MetadataKeyAlbumTitle: \(item.value!)")

            default:
                print("other data: \(item.value!)")
            }
        }
    }
}