【问题标题】:Why can't I play certain .m3u8 items with AVPlayer?为什么我不能用 AVPlayer 播放某些 .m3u8 项目?
【发布时间】:2021-12-22 02:46:54
【问题描述】:

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

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

我不明白问题出在哪里。根据this answer,这是一个错误的 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 时会出现一些问题。你在真机上也有同样的错误吗?
  • @Mr.SwiftOak 我用真机测试过。我提到的 iPhone 7plus 是一款真正的设备。

标签: ios swift xcode audio avplayer


【解决方案1】:

我没有在您的 .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

【讨论】:

  • 我该怎么做?我是否必须操作文件,或者我可以在收到文件时从 Swift 中进行操作吗?
  • 首先尝试验证这是否是您的情况,那些包含某些版本的#EXT-X-VERSION(例如#EXT-X-VERSION:03)的播放列表可以工作,而那些没有版本的则不能.您说某些 .m3u8 播放列表运行良好,对吗?您是从 URL 任务中获取播放列表,还是将它们存储在设备上?首先尝试通过向其添加版本来在文本编辑中手动操作播放列表。
  • 对。基本上我从后端得到一些网址。通过在浏览器中打开网址,我可以检查它们并查看清单(如果我做得对,我不是真正的多媒体专家)。我看到那些可玩的实际上确实包含了版本。一个不可播放的 url 出现了一种奇怪的情况:我得到一个文件 my_resource.m3u8 没有版本,两个 index.m3u8 包含许多 segment1.aac 并且其中有版本。
  • 如果您正在构建一些 VOD 服务,请尝试告诉后端的某个人只需将版本添加到播放列表中,您就应该准备好了。在后端更改播放列表比在设备上更容易。
  • 我会试试的,谢谢。如果其他人可以做出其他贡献,我将保持问题开放,我会将其标记为已接受的答案。
【解决方案2】:

最后我找到了解决这个问题的方法。对我有用的是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)
            }
        }
    }

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    相关资源
    最近更新 更多