AVKit
从iOS8开始被引入iOS平台。针对iOS平台的AVKit
是一个简单的标准框架-只包含一个AVPlayerViewController
类。它是UIViewController
的子类,用于展示并控制AVPlayer
实例的播放。
AVPlayerViewController
具有一个很小的界面,提供以下几个属性:
-
player
:用来播放媒体内容的AVPlayer实例 -
showsPlaybackControls
:用来表示播放控件是否显示或隐藏。 -
videoGravity
:视频的显示区域设置 -
readForDisplay
:通过观察这个布尔值类型的值来确定视频内容是否已经准备好进行展示。
注意
Do not subclass AVPlayerViewController. Overriding this class’s methods is unsupported and results in undefined behavior.
不要子类化AVPlayerViewController,重写类的方法是不被支持的,而且可能导致未知行为
实战
效果

代码实现
import UIKit
import AVKit
class AVKitPlayerController: UIViewController {
var playerItem: AVPlayerItem?
var playerController: AVPlayerViewController!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
setupAVPlayerViewController()
addObserver()
}
}
创建AVPlayerViewController
func setupAVPlayerViewController() {
guard let url = Bundle.main.url(forResource: "trailer", withExtension: ".mp4") else {
return
}
playerController = AVPlayerViewController()
playerItem = AVPlayerItem(url: url)
playerController.player = AVPlayer(playerItem: playerItem)
playerController.videoGravity = .resizeAspectFill
playerController.view.frame = CGRect(x: 0, y: 100, width: view.frame.width, height: 300)
view.addSubview(playerController.view)
}
为playerItem添加监听,等到资源准备完毕开始播放视频
func addObserver() {
// 监听loadedTimeRanges属性来监听缓冲进度更新
playerItem?.addObserver(self,
forKeyPath: "loadedTimeRanges",
options: .new,
context: nil)
// 监听status属性进行播放
playerItem?.addObserver(self,
forKeyPath: "status",
options: .new,
context: nil)
}
func removeObserver() {
playerItem?.removeObserver(self, forKeyPath: "status")
playerItem?.removeObserver(self, forKeyPath: "loadedTimeRanges")
}
deinit {
removeObserver()
}
实现监听的回调函数
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
guard let object = object as? AVPlayerItem else { return }
guard let keyPath = keyPath else { return }
if keyPath == "status" {
if object.status == .readyToPlay { //当资源准备好播放,那么开始播放视频
playerController?.player?.play()
print("正在播放...,视频总长度:\(formatPlayTime(seconds: CMTimeGetSeconds(object.duration)))")
} else if object.status == .failed || object.status == .unknown {
print("播放出错")
}
} else if keyPath == "loadedTimeRanges" {
let loadedTime = availableDurationWithplayerItem()
print("当前加载进度\(loadedTime)")
}
}
// 将秒转成时间字符串的方法,因为我们将得到秒。
func formatPlayTime(seconds: Float64) -> String {
let min = Int(seconds / 60)
let sec = Int(seconds.truncatingRemainder(dividingBy: 60))
return String(format: "%02d:%02d", min, sec)
}
// 计算当前的缓冲进度
func availableDurationWithplayerItem() -> TimeInterval {
guard let loadedTimeRanges = playerController.player?.currentItem?.loadedTimeRanges,
let first = loadedTimeRanges.first else {
fatalError()
}
let timeRange = first.timeRangeValue
let startSeconds = CMTimeGetSeconds(timeRange.start) // 本次缓冲起始时间
let durationSecound = CMTimeGetSeconds(timeRange.duration)// 缓冲时间
let result = startSeconds + durationSecound// 缓冲总长度
return result
}
可以看到AVPlayerViewController在没有编写过多代码的前提下实现了许多功能。创建了一个带有与iOS视频播放器同样用户界面和体验的功能齐全的播放器,由于这个类是UIViewController的子类,所以很容易将它作为子视图控制器嵌入到其他视图中,或向其他视图控制器一样呈现
网友评论