AVPlayer 的时间线进度条

ios

1个回答

写回答

daixiayu

2025-07-09 15:24

+ 关注

IOS
IOS

在IOS应用开发中,我们经常会遇到需要使用进度条来展示音视频播放的进度。而在使用 AVPlayer 播放音视频时,我们可以通过监听其时间线来实现进度条的更新。本文将介绍如何利用 AVPlayer 的时间线来实现进度条,并提供相应的案例代码。

AVPlayer简介

AVPlayer 是苹果提供的一个强大的媒体播放框架,可以用来播放音频和视频。它提供了丰富的功能和灵活的接口,可以满足开发者对媒体播放的各种需求。

监听时间线

要实现进度条的更新,我们需要监听 AVPlayer 的时间线。AVPlayer 提供了一个 KVO(Key-Value Observing)机制,可以监听它的属性变化。我们可以监听 AVPlayer 的 "currentItem" 属性,以获取当前播放的音视频项。然后,我们再监听当前音视频项的 "status" 属性和 "loadedTimeRanges" 属性,以获取当前音视频的加载状态和已加载的时间范围。

当我们监听到 "status" 属性为 AVPlayerItemStatusReadyToPlay 时,表示音视频已经准备好可以播放了。而 "loadedTimeRanges" 属性是一个数组,包含了已加载的时间范围。我们可以通过遍历数组,获取已加载的最大时间范围,以计算出当前的加载进度。

案例代码

下面是一个简单的案例代码,演示了如何使用 AVPlayer 的时间线来更新进度条:

Swift

import UIKit

import AVFoundation

class ViewController: UIViewController {

@IBOutlet weak var progressBar: UIProgressView!

var player: AVPlayer?

var playerItem: AVPlayerItem?

var timeObserverToken: Any?

override func viewDidLoad() {

super.viewDidLoad()

// 创建 AVPlayerItem

let vIDEOURL = URL(string: "https://example.com/vIDEO.mp4")

playerItem = AVPlayerItem(url: vIDEOURL!)

// 创建 AVPlayer

player = AVPlayer(playerItem: playerItem)

// 监听 AVPlayerItem 的状态和已加载时间范围

playerItem?.addObserver(self, forKeyPath: "status", options: .new, context: nil)

playerItem?.addObserver(self, forKeyPath: "loadedTimeRanges", options: .new, context: nil)

// 添加时间线观察者

let interval = CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC))

timeObserverToken = player?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.mAIn) { [weak self] time in

self?.updateProgressBar()

}

}

func updateProgressBar() {

guard let playerItem = playerItem else { return }

if playerItem.status == .readyToPlay {

let duration = CMTimeGetSeconds(playerItem.duration)

let currentTime = CMTimeGetSeconds(playerItem.currentTime())

let progress = Float(currentTime / duration)

progressBar.progress = progress

}

}

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

if keyPath == "status" {

if playerItem?.status == .readyToPlay {

// 音视频已准备好可以播放

player?.play()

}

} else if keyPath == "loadedTimeRanges" {

// 计算加载进度

let loadedTimeRanges = playerItem?.loadedTimeRanges

let timeRange = loadedTimeRanges?.first?.timeRangeValue

let startSeconds = CMTimeGetSeconds(timeRange?.start ?? CMTime.zero)

let durationSeconds = CMTimeGetSeconds(timeRange?.duration ?? CMTime.zero)

let loadedTime = startSeconds + durationSeconds

// 更新进度条

let TotalTime = CMTimeGetSeconds(playerItem?.duration ?? CMTime.zero)

let progress = Float(loadedTime / TotalTime)

progressBar.progress = progress

}

}

deinit {

// 移除观察者和时间线观察者

playerItem?.removeObserver(self, forKeyPath: "status")

playerItem?.removeObserver(self, forKeyPath: "loadedTimeRanges")

if let timeObserverToken = timeObserverToken {

player?.removeTimeObserver(timeObserverToken)

}

}

}

在上面的代码中,我们首先创建了一个 AVPlayerItem,其初始化使用了一个远程视频的 URL。然后,我们创建了一个 AVPlayer,并将 AVPlayerItem 设置为其当前项。接下来,我们监听了 AVPlayerItem 的 "status" 和 "loadedTimeRanges" 属性,以及 AVPlayer 的时间线。

在 "updateProgressBar" 方法中,我们首先判断 AVPlayerItem 的状态是否为 .readyToPlay,如果是,则计算播放进度,并更新进度条的值。在 "observeValue" 方法中,我们分别处理了 "status" 和 "loadedTimeRanges" 属性的变化,计算已加载的时间范围,并更新进度条的值。

最后,在视图控制器销毁时,我们移除了监听和时间线观察者,以释放相关资源。

通过监听 AVPlayer 的时间线,我们可以实时更新进度条,展示音视频的播放进度。AVPlayer 提供了丰富的功能和灵活的接口,可以满足开发者对媒体播放的各种需求。希望本文对你在实现进度条时有所帮助。

如果你对 AVPlayer 还不够熟悉,可以参考苹果的官方文档,了解更多关于 AVPlayer 的知识和用法。

举报有用(4)分享收藏

Copyright © 2025 IZhiDa.com All Rights Reserved.

知答 版权所有 粤ICP备2023042255号