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

AVPlayer缓冲后停止播放,网络大视频播放卡顿问题求助

解决AVPlayer加载10-40MB网络视频时的卡顿/缓冲异常问题

嘿,我仔细看了你的问题描述和代码片段,这种播放不流畅、要么全加载完才播要么播1秒就停的情况,大概率是你和AVPlayer的默认缓冲机制没配合好,咱们来逐个调整:

1. 别乱关automaticallyWaitsToMinimizeStalling

你把这个属性设为false完全是反操作!这个属性默认是true,它的作用就是让AVPlayer自动管理缓冲,尽可能减少播放卡顿。强制关掉之后,播放器不会主动等缓冲足够就硬播,反而更容易因为缓冲不足直接停掉。赶紧把这行删掉,或者显式设为true。

2. 调整播放触发的时机

你用playImmediately(atRate: 0)是让播放器进入准备状态但不播放,但之后如果直接调用play(),很可能缓冲还没够就开始播了。正确的做法是等playbackLikelyToKeepUp变为true之后再启动播放,这个状态表示缓冲足够支撑后续播放了。

3. 优化观察者逻辑+增加预加载策略

现在你的观察者只处理了加载器的显示隐藏,没针对缓冲空的情况做重试。另外,你可以给AVPlayerItem设置preferredForwardBufferDuration来增加预加载的时长,让播放器提前下载更多内容。

修正后的完整代码示例

// 初始化播放器部分
self.makeLoaderVisible()
let playerItem = AVPlayerItem(url: url)
// 设置预加载缓冲时长,比如设为10秒,根据你的视频码率和网络情况调整
playerItem.preferredForwardBufferDuration = 10.0
// 添加观察者
playerItem.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "playbackBufferFull", options: .new, context: nil)

avPlayer?.replaceCurrentItem(with: playerItem)
// 保留默认的自动缓冲管理,这很重要!
avPlayer?.automaticallyWaitsToMinimizeStalling = true
// 不要着急触发播放,等缓冲足够再说
// 优化后的观察者方法
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    guard let playerItem = object as? AVPlayerItem else { return }
    
    switch keyPath {
    case "playbackBufferEmpty":
        makeLoaderVisible()
        // 缓冲空的时候,主动触发重新加载,让播放器继续缓冲
        playerItem.reloadValues()
        avPlayer?.play() // 尝试恢复播放,驱动播放器继续下载
    case "playbackLikelyToKeepUp":
        hideLoader()
        // 只有确认缓冲足够维持播放时,才开始/恢复播放
        if playerItem.isPlaybackLikelyToKeepUp {
            avPlayer?.play()
        }
    case "playbackBufferFull":
        hideLoader()
    default:
        return
    }
}

4. 额外的排查建议

  • 视频格式检查:如果你的视频是单一文件(不是HLS分段),AVPlayer可能需要下载大量数据才会开始播放。建议把视频转成HLS格式,让播放器可以分段加载,这样启动速度会快很多。
  • 网络环境验证:如果是弱网环境,哪怕代码调优了也可能卡顿,可以再调高preferredForwardBufferDuration的值,或者在播放前先预加载一小段数据。
  • 清理第三方库干扰:你说试了很多第三方库,先暂时关掉这些,用纯系统AVPlayer调试,排除第三方库和系统播放器的冲突问题。

最后别忘了在视图销毁时移除观察者,避免内存泄漏:

deinit {
    guard let currentItem = avPlayer?.currentItem else { return }
    currentItem.removeObserver(self, forKeyPath: "playbackBufferEmpty")
    currentItem.removeObserver(self, forKeyPath: "playbackLikelyToKeepUp")
    currentItem.removeObserver(self, forKeyPath: "playbackBufferFull")
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:11:37