为什么我不能用 AVPlayer 播放某些 .m3u8 项目?

Why can't I play certain .m3u8 items with AVPlayer?

我正在做一个项目,我有一个 AVPlayer 实例,它能够播放我从后端检索的不同音频内容,从播客到音乐和流媒体。每个内容都有两种类型的 url:一种是 mp3,另一种是 m3u8 文件。所有的 mp3 文件都很好用。然而,一些 m3u8 文件可以正常工作,而另一些则不能。特别是,那些不工作的人会导致 AVPlayer 崩溃并出现错误:

Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action"
UserInfo={NSLocalizedRecoverySuggestion=Try again later.,
NSLocalizedDescription=Cannot Complete Action.}

我不明白这是什么问题。根据 这是一个错误的 Manifest 文件,在我的例子中是 - 例如 - 以下内容:

#EXTM3U
#EXT-X-MEDIA:TYPE=AUDIO,URI="_64/index.m3u8",GROUP-ID="2@48000-64000",NAME="AAC  64",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-MEDIA:TYPE=AUDIO,URI="_80/index.m3u8",GROUP-ID="2@48000-80000",NAME="AAC 80",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-MEDIA:TYPE=AUDIO,URI="_96/index.m3u8",GROUP-ID="2@48000-96000",NAME="AAC 96",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-STREAM-INF:BANDWIDTH=133336,CODECS="mp4a.40.2",AUDIO="2@48000-96000"
_96/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=100641,CODECS="mp4a.40.2",AUDIO="2@48000-64000"
_64/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=116989,CODECS="mp4a.40.2",AUDIO="2@48000-80000"
_80/index.m3u8

在 Apple 论坛上,我发现 this answer 说 iOS 14+ 有问题。不幸的是,我无法使用 iOS 13 物理设备进行测试。

你有什么建议吗?

在 Xcode 13.1 上测试 iPhone 7plus 和 iOS 15.0.2.

我在你的 .m3u8 中没有看到版本。尝试将 #EXT-X-VERSION:03 添加到您的播放列表中。 AVPlayer 确实需要将版本包含在播放列表中(Android EXO 播放器不需要它)。以下是可能有效的播放列表示例:

    #EXTM3U
#EXT-X-VERSION:03
#EXT-X-MEDIA:TYPE=AUDIO,URI="_64/index.m3u8",GROUP-ID="2@48000-64000",NAME="AAC  64",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-MEDIA:TYPE=AUDIO,URI="_80/index.m3u8",GROUP-ID="2@48000-80000",NAME="AAC 80",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-MEDIA:TYPE=AUDIO,URI="_96/index.m3u8",GROUP-ID="2@48000-96000",NAME="AAC 96",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-STREAM-INF:BANDWIDTH=133336,CODECS="mp4a.40.2",AUDIO="2@48000-96000"
_96/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=100641,CODECS="mp4a.40.2",AUDIO="2@48000-64000"
_64/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=116989,CODECS="mp4a.40.2",AUDIO="2@48000-80000"
_80/index.m3u8

我终于找到了解决这个问题的方法。对我有用的是 this。我认为问题在于我的清单文件的结构如下:

#EXT-X-MEDIA:TYPE=AUDIO,URI="_64/index.m3u8", GROUP-ID="1@48000-64000",NAME="Audio 64",DEFAULT=NO,AUTOSELECT=NO

特别是他们 DEFAULT=NO,AUTOSELECT=NO。因此,在调用 replaceCurrentItem 之前,我现在执行以下操作:

    let asset = AVAsset(url: url)
    let playerItem = AVPlayerItem(asset: asset)
    
    for characteristic in asset.availableMediaCharacteristicsWithMediaSelectionOptions {
        if let group = asset.mediaSelectionGroup(forMediaCharacteristic: AVMediaCharacteristic.audible) {
            if let option = group.options.first {
                playerItem.select(option, in: group)
            }
        }
    }

这使得我的所有 HLS 音频都可以由 AVPlayer 播放。