You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVPlayer播放远程MP3时网络断开/URL无效未触发错误通知如何解决

AVPlayer播放远程MP3文件错误捕获方案

你之前订阅的两个通知触发场景和资源类型不匹配:AVPlayerItemFailedToPlayToEndTime仅在已经正常播放、中途加载失败无法续播时才会触发;AVPlayerItemNewErrorLogEntry是HLS流媒体(即m3u8格式)专属的错误日志通知,普通MP3这类渐进式下载资源不会触发该通知。且未触发播放动作时,AVPlayer本身的status默认会停留在readyToPlay,不会主动上报资源加载错误。

你可以通过以下组合方案完成错误捕获:

  • 主动预校验资源可用性:创建AVPlayerItem后不要直接初始化播放器,先调用loadValuesAsynchronously主动加载资源核心属性,无效URL、无网络等场景都会在这个异步回调中返回错误
let playerItem = AVPlayerItem(url: audioUrl)
playerItem.loadValuesAsynchronously(forKeys: ["duration", "playable"]) { [weak self] in
    DispatchQueue.main.async {
        var loadError: NSError?
        let loadStatus = playerItem.statusOfValue(forKey: "duration", error: &loadError)
        switch loadStatus {
        case .failed:
            // 资源加载失败,直接处理错误逻辑
            print("MP3资源不可用:\(loadError?.localizedDescription ?? "未知错误")")
        case .loaded:
            // 资源正常,再初始化播放器、注册监听
            self?.player = AVPlayer(playerItem: playerItem)
            self?.addAllObservers()
        default:
            break
        }
    }
}
  • 用KVO监听AVPlayerItem的status属性:不要仅监听AVPlayer本身的status,播放项的status才会直接返回资源相关的加载错误
  • 监听AVPlayer的timeControlStatus:如果状态为waitingToPlayAtSpecifiedRate,同时reasonForWaitingToPlay为toMinimizeStalls,结合网络状态即可判定为网络加载卡顿错误
  • 补充订阅AVPlayerItemPlaybackStalled通知:处理MP3播放中途网络断开、缓存耗尽导致的卡顿场景

完整的监听注册示例代码:

// 存储KVO监听令牌,销毁时需要主动释放
private var kvoTokens = [NSKeyValueObservation]()

func addAllObservers() {
    guard let player = player, let currentItem = player.currentItem else { return }
    
    // 监听播放项状态
    kvoTokens.append(currentItem.observe(\.status, options: [.new]) { item, _ in
        if item.status == .failed {
            print("播放错误:\(item.error?.localizedDescription ?? "未知错误")")
            // 执行错误处理逻辑
        }
    })
    
    // 监听播放器等待状态
    kvoTokens.append(player.observe(\.timeControlStatus, options: [.new]) { player, _ in
        if player.timeControlStatus == .waitingToPlayAtSpecifiedRate,
           player.reasonForWaitingToPlay == .toMinimizeStalls {
            // 这里配合自己实现的网络状态检测逻辑,无网络时直接判定为加载失败
            if !NetworkMonitor.shared.isConnected {
                print("网络断开,播放加载失败")
            }
        }
    })
    
    // 订阅播放卡顿通知
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handlePlaybackStalled),
        name: .AVPlayerItemPlaybackStalled,
        object: currentItem
    )
    // 保留原有的播放结束失败通知,处理中途播放异常场景
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(playerDidFail),
        name: .AVPlayerItemFailedToPlayToEndTime,
        object: currentItem
    )
}

注意:对象销毁前需要手动移除所有KVO监听和通知订阅,避免野指针崩溃。

内容的提问来源于stack exchange,提问作者Wojciech Kulik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 01:15:07