AVPlayer的使用+簡單的播放器Demo
學習內容
歡迎關注我的iOS學習總結——每天學一點iOS://github.com/practiceqian/one-day-one-iOS-summary
AVPlayer學習
-
幾個播放器相關的類
-
AVPlayer、AVURLAsset、AVPlayerItem、AVPlayerLayer
//控制播放器的播放、暫停、播放速度 @property (nonatomic,strong) AVPlayer * player; //管理資源對象,提供播放數據源 @property (nonatomic,strong) AVPlayerItem* playItem; //負責顯示影片,如果沒有添加該類,只有聲音沒有畫面 @property (nonatomic,strong) AVPlayerLayer* playerLayer;
-
-
構建一個簡單的播放器
-
//一個UIImageView,構建播放器的顯示區域 self.playerView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height/3)]; [self.view addSubview:self.playerView]; //播放資源 NSURL* playUrl = [NSURL URLWithString:@"//clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"]; self.playItem = [AVPlayerItem playerItemWithURL:playUrl]; //播放器實例 self.player = [AVPlayer playerWithPlayerItem:self.playItem]; //顯示區域 self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; self.playerLayer.frame = self.playerView.bounds; //將顯示區域添加到UIImageView上 [self.playerView.layer addSublayer:self.playerLayer]; //開始播放 [self.player play]; -
效果如圖

- 可以在UIImageView的容器中看到畫面,但是此時依然不能控制播放的進度等
-
-
使用AVPlayer控制播放行為
-
//播放 [self.player play]; //暫停 [self.player pause]; //控制播放速度 self.player.rate = 2.0
-
-
使用AVPlayerItem控制播放狀態
-
//三種播放狀態 typedef NS_ENUM(NSInteger, AVPlayerItemStatus) { AVPlayerItemStatusUnknown = 0, //未知 AVPlayerItemStatusReadyToPlay = 1, //準備播放 AVPlayerItemStatusFailed = 2 //播放失敗 }; -
使用KVO進行監聽播放狀態
//對status進行監聽 [self.playItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; //監聽的回調 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{ if ([object isKindOfClass:[AVPlayerItem class]]) { if ([keyPath isEqualToString:@"status"]) { //根據播放的三種狀態進行處理 switch (self.playItem.status) { case AVPlayerItemStatusUnknown: NSLog(@"播放狀態未知"); break; case AVPlayerItemStatusReadyToPlay: NSLog(@"準備播放"); break; case AVPlayerItemStatusFailed: NSLog(@"播放失敗"); break;; default: break; } } } } -
獲取播放時間
-
//CMTime是以分數的形式表示時間,value表示分子,timescale表示分母,flags是位掩碼,表示時間的指定狀態。 typedef struct{ CMTimeValue value; // 幀數 CMTimeScale timescale; // 幀率(影片每秒有幾幀) CMTimeFlags flags; CMTimeEpoch epoch; } CMTime; -
//獲取當前的播放時間 float currentTime = self.playItem.currentTime.value/self.playItem.currentTime.timescale; //獲取影片的總時間(一般在準備播放狀態時獲取) float totalTime = CMTimeGetSeconds(self.playItem.duration);
-
-
監聽播放的進度
-
__weak typeof(self) weakSelf = self; //CMTimeMake(1,1),一秒鐘監聽一次 [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:nil usingBlock:^(CMTime time) { AVPlayerItem* item = weakSelf.playItem; float curTime = item.currentTime.value/item.currentTime.timescale; NSLog(@"當前時間:%.0f",curTime); }];
-
-
監聽緩衝的進度
[self.playItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; --------------------------------------------------------------- if ([keyPath isEqualToString:@"loadedTimeRanges"]){ NSArray *array = self.playItem.loadedTimeRanges; CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次緩衝時間範圍 float startSeconds = CMTimeGetSeconds(timeRange.start); float durationSeconds = CMTimeGetSeconds(timeRange.duration); NSTimeInterval totalBuffer = startSeconds + durationSeconds;//緩衝總長度 NSLog(@"當前已緩衝時間:%f",totalBuffer); } -
監聽已快取時間充足/不足
[self.playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; --------------------------------------------------------------------- [self.playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; -
最後的demo
-



