1. AVPlayer
AVPlayer 是一個(gè)用來播放基于時(shí)間的視聽媒體的控制器對(duì)象(一個(gè)隊(duì)播放和資源時(shí)間相隔信息進(jìn)行管理的對(duì)象,而非一個(gè)視圖或窗口控制器).
AVPlayer支持播放從本地, 分步下載或通過HTTP Live Streaming協(xié)議得到的流媒體, 并在多種播放場(chǎng)景中播放這些視頻資源.
開發(fā)者通過AVPlayer框架提供的應(yīng)用程序接口來開發(fā)控制播放基于時(shí)間的媒體的用戶界面.
AVPlayer只管理一個(gè)單獨(dú)資源的播放, 但是框架還體用了AVPlayer的一個(gè)子類AVQueuePlayer, 通過它可以
管理一個(gè)資源隊(duì)列
AVPlayer是一個(gè)不可見組件,對(duì)于播放MP3, ACC等音頻文件, 沒有可視化界面不會(huì)有什么問題, 但是對(duì)于想MP4等視頻類文件就會(huì)給用戶非常差的體驗(yàn), 而要將視頻資源導(dǎo)出到用戶界面的目標(biāo)位置, 需要使用AVPlayerLayer類.
2. AVPlayerLayer
AVPlayerLayer構(gòu)建于Core Animation之上(AVPlayerLayer擴(kuò)展了Core Animation的CALayer), 是AV Foundation中能找到的位數(shù)不多的可視化組件.
說白了就是AVPlayer沒有顯示界面的能力劲腿,靠AVPlayerLayer來顯示界面编整。
AVPlayerLayer開發(fā)者可以自定義的只有一個(gè)屬性: videoGravity
video gravity 總共有三個(gè)不同的值:
- AVLayerVideoGravityResizeAspect: 會(huì)在承載層的范圍內(nèi)縮放視頻大小來保存視頻的原始寬高比例,最常用
- AVLayerVideoGravityAspectFill: 保留視頻的寬高比,并使其通過縮放填滿層的范圍區(qū)域,通常會(huì)導(dǎo)致視頻圖片被部分裁剪
- AVLayerVideoGravityResize: 會(huì)將視頻內(nèi)容拉伸來匹配承載層的范圍.這是最不常用的模式, 因?yàn)樗ǔ?huì)導(dǎo)致圖片扭曲
3. AVPlayerItem
視頻的播放就是使用AVPlayer來播放AVAsset.
通過AVAsset 可以找到一些用來獲取數(shù)據(jù)的方法和屬性,(如創(chuàng)建日期, 元數(shù)據(jù), 時(shí)長(zhǎng)等信息). 但無法獲取當(dāng)前時(shí)間,也不能夠在媒體中查找特定位置.這是因?yàn)锳VAsset模型只包含媒體資源的靜態(tài)信息, 這些不變的屬性用來描述對(duì)象的靜態(tài)狀態(tài). 這意味著僅使用AVAsset對(duì)象是無法實(shí)現(xiàn)播放功能的.
當(dāng)我們需要對(duì)一個(gè)資源及其相關(guān)曲目進(jìn)行播放時(shí), 首先需要通過AVPlayerItemTrack和 AVPlayerItemTrack類構(gòu)建相應(yīng)的動(dòng)態(tài)內(nèi)容.
- AVPlayerItem會(huì)建立媒體資源動(dòng)態(tài)視角的數(shù)據(jù)模型,并保存AVPlayer在播放資源時(shí)的呈現(xiàn)狀態(tài)
- AVPlayerItem由一個(gè)或多個(gè)媒體曲目組成, 由AVPlayerItemTrack類建立模型
- AVPlayerItemTrack實(shí)例用于表示播放器條目中的類型同一的媒體流,比如音頻或視頻
- AVPlayerItem中的曲目直接與基礎(chǔ)AVAsset中的AVAssetTrack實(shí)例相對(duì)應(yīng)
以下是最簡(jiǎn)單的視頻播放器代碼
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"視頻播放 ";
NSURL *url = [[NSBundle mainBundle]URLForResource:@"hubblecast.m4v" withExtension:nil];
self.set = [AVAsset assetWithURL:url];
self.item = [[AVPlayerItem alloc]initWithAsset:self.set];
self.player = [AVPlayer playerWithPlayerItem:self.item];
self.layer = [AVPlayerLayer playerLayerWithPlayer:self.player];
self.layer.frame = self.view.frame;
[self.view.layer addSublayer:self.layer];
[self.item addObserver:self forKeyPath:@"status" options:0 context:&PlayerItemStatusContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (context == &PlayerItemStatusContext) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.item removeObserver:self forKeyPath:@"status"];
NSLog(@"self.item.status=%ld",(long)self.item.status);
if (self.item.status == AVPlayerItemStatusReadyToPlay) {
[self.player play];
} else {
}
});
}
}