简体   繁体   English

使用 HLS 视频时,仅在带有 AVPlayerViewController 和 AVPlayer 的 iOS 13 上出现视频播放问题

[英]Video playback issues only on iOS 13 with AVPlayerViewController and AVPlayer when using HLS video

I have an app that plays back videos.我有一个播放视频的应用程序。 It's compatible with iOS 11, 12 and iOS 13. On iOS 11 and 12, video playback works properly as expected using either AVPlayerViewController or even just AVPlayerLayer .它与 iOS 11、12 和 iOS 13 兼容。在 iOS 11 和 12 上,使用AVPlayerViewController甚至AVPlayerLayer甚至可以正常播放视频

However, on iOS 13 I started getting reports that suddenly video wasn't loading (or would only load audio, or only the first frame) for quite a few users when they updated iOS.然而,在 iOS 13 上,当他们更新 iOS 时,我开始收到不少用户突然无法加载视频(或仅加载音频,或仅加载第一帧)的报告。 I had a really hard time replicating it, but some mentioned it occurred mostly with poor network connections, and sure enough with Network Link Conditioner I was able to reproduce it.我很难复制它,但有些人提到它主要发生在网络连接不佳的情况下,果然使用 Network Link Conditioner 我能够复制它。

It specifically affects HLS video (the fancy livestream compatible one that Reddit uses, for instance).它特别影响 HLS 视频(例如,Reddit 使用的花哨的直播兼容视频)。 It continues to work fine with MP4.它继续与 MP4 一起正常工作。 Here's an example URL that fails: https://v.redd.it/gl3chx2kd4v31/HLSPlaylist.m3u8这是一个失败的示例 URL: https://v.redd.it/gl3chx2kd4v31/HLSPlaylist.m3u8

Here's a Network Link Conditioner profile that triggers it: https://i.imgur.com/XWsKUeM.jpg这是触发它的网络链接调节器配置文件: https://i.imgur.com/XWsKUeM.jpg

Here's a sample project that triggers it, showing both AVPlayerViewController and AVPlayer (hit Download, Google is being weird): https://drive.google.com/file/d/1RS5DvUypdOLFCYJe1Pt2Ig0fQljZDLs2/view这是一个触发它的示例项目,显示了 AVPlayerViewController 和 AVPlayer(点击下载,谷歌很奇怪): https://drive.google.com/file/d/1RS5DvUypdOLFCYJe1Pt2Ig0fQljZDLs2/view

Here's sample code showing it off with AVPlayerViewController:这是使用 AVPlayerViewController 展示它的示例代码:

let assetURL = URL(string: "https://v.redd.it/gl3chx2kd4v31/HLSPlaylist.m3u8")!

// The following MP4 URL *does* work, for instance
// let assetURL = URL(string: "https://giant.gfycat.com/DependentFreshKissingbug.mp4")!

let player = AVPlayer(url: assetURL)
let playerViewController = AVPlayerViewController()
playerViewController.player = player

self.present(playerViewController, animated: true) {
    playerViewController.player!.play()
}

If I try that exact same code on an iOS 12 device instead it works perfectly.如果我在 iOS 12 设备上尝试完全相同的代码,则它可以完美运行。

Does anyone have any suggestions on how to fix it?有人对如何修复它有任何建议吗? If you scrub back to the beginning sometimes you can get the video to play back properly, but not reliably enough so to seemingly build a solution off that.如果您重新开始,有时您可以让视频正确播放,但不够可靠,因此似乎无法建立解决方案。 Video stuff definitely isn't my forte in iOS development so I'm starting to scratch my head a little, any help would be super appreciated.视频内容绝对不是我在 iOS 开发中的强项,所以我开始有点摸不着头脑,任何帮助将不胜感激。

Note: I'm quite aware this is (likely) an iOS bug and I will file a Radar, but I still have to deal with it now.注意:我很清楚这(很可能)是一个 iOS 错误,我将提交 Radar,但我现在仍然必须处理它。

You need to kvo on the playerItems status in order to know when it is ready to play.您需要了解 playerItems 状态才能知道它何时可以播放。 Then in the playerItem status change to ready to play call your player.play.然后在 playerItem 状态更改为准备播放调用你的 player.play。

playerItem.addObserver(self,
                           forKeyPath: #keyPath(AVPlayerItem.status),
                           options: [.old, .new],
                           context: &playerItemContext)


override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?,
                           change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?) {

    // Only handle observations for the playerItemContext
    guard context == &playerItemContext else {
        super.observeValue(forKeyPath: keyPath,
                           of: object,
                           change: change,
                           context: context)
        return
    }

    if keyPath == #keyPath(AVPlayerItem.status) {
        let status: AVPlayerItemStatus
        if let statusNumber = change?[.newKey] as? NSNumber {
            status = AVPlayerItemStatus(rawValue: statusNumber.intValue)!
        } else {
            status = .unknown
        }

        // Switch over status value
        switch status {
        case .readyToPlay:
            // Player item is ready to play.
        case .failed:
            // Player item failed. See error.
        case .unknown:
            // Player item is not yet ready.
        }
    }
}


Try re-arraigning the entiries in the HLSPlaylist.m3u8.尝试重新安排 HLSPlaylist.m3u8 中的条目。 It is observed that safari and AVPlayer prefers the first items in the list.观察到 safari 和 AVPlayer 更喜欢列表中的第一项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 iOS 13 上,AVPlayer 为该 HLS 视频选择仅音频 stream。 我可以控制这种行为,而是让它加载视频+音频吗? - On iOS 13, AVPlayer chooses an audio only stream for this HLS video. Can I control this behavior, and instead have it load the video + audio? 使用AVPlayer和AVPlayerViewController,但不存在音频和视频 - Using AVPlayer and AVPlayerViewController, but audio and video not present 如何在 iOS 13 的 AVPlayer 中播放不安全的视频? - How to play unsecure video in AVPlayer in iOS 13? AVPlayer延伸了HLS视频的结尾 - AVPlayer stretches the end of a HLS video 带有 avplayerviewcontroller 播放控件的 AVPlayer - AVPlayer with playback controls of avplayerviewcontroller 在 iOS SDK 中手动选择视频质量的 HLS Streaming - AVPlayer? - HLS Streaming with manual video quality selection in iOS SDK - AVPlayer? 让iOS 5 AVPlayer在播放完成时显示视频的最后一帧而不是黑屏 - Getting iOS 5 AVPlayer to display the last frame of the video when playback completes instead of a black screen AVPlayer在播放HLS / AES加密视频之前发出无关的http请求 - AVPlayer making extraneous http request prior to playback of HLS / AES-encrypted video 当使用AVPLayer播放视频时,它会停止背景音乐ios - When Video plays using AVPLayer, it stops background music ios iOS AVPlayer:屏幕锁定时暂停视频 - iOS AVPlayer: pause video when screen locks
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM