无法从AVURLAsset获取HLS视频(.m3u8格式)的视频轨道用于AVPlayer?

8
我正在开发一个自定义视频播放器,用于从服务器流式传输HLS视频。我可以使用AVPlayerItem和AVPlayer成功播放HLS视频。
接下来,我想为我的视频播放器添加字幕轨道和音频轨道,因此我使用了AVMutableComposition。现在问题是,当我为HLS视频创建AVURLAsset时,无法从AVURLAsset获取视频轨道。它总是给我0个轨道。我尝试过AVURLAsset的“loadValuesAsynchronously”以及为AVPlayerItem的“tracks”添加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视频中获取轨道?如果这不可能,那么如何实现类似的结果?
请告知您的反馈。
非常感谢。
2个回答

1

我没有和你完全相同的问题。但是我通过查询AVPlayerItem上的轨道而不是在AVURLAsset上查询轨道来解决了类似的问题(查询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)
}

或者,如果你需要的不仅仅是一个布尔值,你可以使用循环来访问你真正想要的 assetTrack。


1
对于 HLS 视频 tracks(withMediaType: .video) 将返回一个空数组。
使用以下替代方案:player.currentItem.presentationSize.widthplayer.currentItem.presentationSize.height
请让我知道它是否有效。

成功了!谢谢你! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接