【问题标题】:Can't able to get Video Tracks from AVURLAsset for HLS videos(.m3u8 format) for AVPlayer?无法从 AVURLAsset 获取用于 AVPlayer 的 HLS 视频(.m3u8 格式)的视频轨道?
【发布时间】:2019-02-23 20:30:12
【问题描述】:

我正在开发一个自定义视频播放器来从服务器流式传输 HLS 视频。我可以使用 AVPlayerItem 和 AVPlayer 成功播放 HLS 视频。

之后,我想为我的视频播放器添加字幕轨道和音轨。所以我使用 AVMutableComposition 来做到这一点。所以现在的问题是当我为 HLS 视频创建 AVURLAsset 时,我无法从 AVURLAsset 获取视频轨道。它总是给我 0 首曲目。我尝试了 AVURLAsset 的“loadValuesAsynchronously”,并尝试为 AVPlayerItem 的“轨道”添加 KVO。但这些都没有给我带来任何积极的结果。

我正在使用以下代码。

  func playVideo() {
    let videoAsset = AVURLAsset(url: videoURL!)
    let composition = AVMutableComposition()
    // Video
    let videoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
    do {
        let tracks = videoAsset.tracks(withMediaType: .video)
        guard let track = tracks.first else {
            print("Can't get first video track")
            return
        }
        try videoTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: track, at: kCMTimeZero)
    } catch {
        print(error)
        return
    }
    guard let subtitlesUrl = Bundle.main.url(forResource: "en", withExtension: "vtt") else {
        print("Can't load en.vtt from bundle")
        return
    }
    //Subtitles
    let subtitleAsset = AVURLAsset(url: subtitlesUrl)
    let subtitleTrack = composition.addMutableTrack(withMediaType: .text, preferredTrackID: kCMPersistentTrackID_Invalid)
    do {
        let subTracks = subtitleAsset.tracks(withMediaType: AVMediaType.text)
        guard let subTrack = subTracks.first else {
            print("Can't get first subtitles track")
            return
        }
        try subtitleTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: subTrack, at: kCMTimeZero)
    } catch {
        print(error)
        return
    }
    // Prepare item and play it
    let item = AVPlayerItem(asset: composition)
    self.player = AVPlayer(playerItem: item)
    self.playerLayer = AVPlayerLayer.init()
    self.playerLayer.frame = self.bounds
    self.playerLayer.contentsGravity = kCAGravityResizeAspect
    self.playerLayer.player = player
    self.layer.addSublayer(self.playerLayer)
    self.player.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)
    self.player.play()
}

此过程适用于 .mp4 视频,但不适用于 HLS 视频 (.m3u8)。有人对此有一些可行的解决方案吗?

或

我们如何使用 AVURLAsset 从 HLS 视频中获取曲目?如果这是不可能的,那么如何达到类似的结果?

请让我知道您的反馈。

提前多谢。

【问题讨论】:

  • 有人有解决方案吗?请告诉我
  • 这方面有什么更新吗?你是怎么解决这个问题的?
  • @UmaSankarBuddi 你搞定了吗?我被困在同一个地方..任何帮助表示赞赏。
  • @UmaSankarBuddi 有人发现了什么吗?
  • @UmaSankarBuddi 我有同样的问题,你解决了吗?

标签: swift avfoundation avplayer m3u8 avkit


【解决方案1】:

我没有和你完全一样的问题。但是我没有查询 AVURLAsset 上的轨道,而是查询了 AVPlayerItem 上的轨道,从而解决了一个类似的问题(查询 HDR)。

设置项目状态的观察者:

player?.observe(\AVPlayer.currentItem?.status,
                                         options: [.new, .initial], changeHandler: { [weak self] player, _ in
                                            DispatchQueue.main.async {
                                                self?.observedItemStatus(from: player)
                                            }
                                         })

然后查询您选择的 AVMediaType(在您的案例文本中)。

func observedItemStatus(from avPlayer: AVPlayer) {

    guard let currentItem = avPlayer.currentItem else { return }

    // ideally execute code based on currentItem.status...for the brevity of this example I won't.

    let hasLegibleMedia = currentItem.tracks.first(where: {
        $0.assetTrack?.mediaType == AVMediaType.text
    })?.assetTrack.hasMediaCharacteristic(.legible)
}

或者,如果您需要的不仅仅是 Bool,您可以执行一个循环来访问您真正想要的assetTrack。

【讨论】:

    【解决方案2】:

    对于 HLS 视频,tracks(withMediaType: .video) 将返回一个空数组。

    改用这个:player.currentItem.presentationSize.width 和 player.currentItem.presentationSize.height。

    如果有效,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-04
      • 2011-10-07
      • 1970-01-01
      • 1970-01-01
      • 2012-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多