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

标签 swift avplayer http-live-streaming id3 m3u8

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

在 Safari 的 Web 检查器中,我可以在控制台中看到大量数据对象,每个数据对象都有元数据:

enter image description here

在网络检查器的网络选项卡中,我可以读取播放列表文件:

#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 流中的元数据。

最佳答案

这就是我实现它的方法:

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!)")
            }
        }
    }
}

关于swift - 如何从 swift/AVKIT 中的 HLS 流读取 id3 标签/其他元数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58099131/

相关文章:

Swift 自定义 flatMap 实现导致错误 Generic parameter could not be inferred

UiView 中的 IOS swift avplayer 我怎样才能让它工作

ios - 当视频开始播放时暂停歌曲(反之亦然)

ios - 无需编码的 Http 直播

Swift:核心数据 - 解决对象创建的逻辑问题

由于手机号码无效,iOS Swift 调用崩溃

ios - 我正在尝试使用 AVQueuePlayer 创建无缝音频循环,但是,我不知道为什么循环之间会有一个小的无声停顿?

使用 mediaplayer 的 Android http 直播流媒体 URL

video-streaming - 可以在服务器端使用 WebRTC 来获取流帧吗?

ios - 如何使用 Swift 5 从 Firebase 的快照中保存数据?