iOS實現視頻播放,原生代碼播放視頻更多的使用AVPlayer和AVPlayerViewController進行播放。
其中,
- AVPlayer不能單獨進行播放,僅使用AVPLayer的話,還需要將其添加到AVPlayerLayer上進行播放,不含播放控制控件,需要自定義添加;
- AVPlayerViewController也是在AVPlayer的基礎上集成的播放控件。包含完整的播放,暫停,進度拖動等控制控件。
所需庫
- 使用AVPlayer和AVPlayerViewController需要添加庫文件:AVKit.framework
- 獲取時間(CMTimeGetSeconds)等等需要添加庫文件:CoreMedia.framework
引用頭文件
#import <AVKit/AVKit.h>
#import <AVFoundation/AVFoundation.h>
實現播放(代碼)
1. AVPlayer
僅使用AVPlayer和AVPlayerLayer創建播放
//生成播放url
本地
NSString* localFilePath=[[NSBundle mainBundle]pathForResource:@"aaa" ofType:@"mp4"];
NSURL *videoUrl = [NSURL fileURLWithPath:localFilePath];
//網絡
NSString *webVideoPath = @"http://122.144.137.20:81/2018/12/video/d63797a1912a4f529d8cffab862d8747.mp4";
NSURL *videoUrl = [NSURL URLWithString:webVideoPath];
//創建播放單元
AVPlayerItem* item = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:videoUrl]]; //通過url生成
//創建播放器
AVPlayer* player = [AVPlayer playerWithPlayerItem:item]; //使用播放單元生成相應的播放器
或者
AVPlayer* player = [AVPlayer playerWithURL:videoUrl]; //直接使用播放URL生成
//切換播放內容時
[player replaceCurrentItemWithPlayerItem:item];
//創建播放層,將playerLayer添加到view上即可播放
AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.myPlayer];
2. AVPlayerViewController
AVPlayerViewController 在生成播放器player的基礎上,進行下一步調用:
AVPlayerViewController* playerVC = [[AVPlayerViewController alloc] init];
//設置播放器
playerVC.player = player;
//設置播放範圍
playerVC.view.frame = CGRectMake(0, 0, 700, 300);
/** 設置所播放視頻的適配顯示範圍
* AVLayerVideoGravityResizeAspectFill : 顯示尺寸適配,保證適配內容不變形的情況下鋪滿顯示區域,畫面可能會有截斷
* AVLayerVideoGravityResizeAspect : 保證視頻不變形,畫面全部顯示,可能不能鋪滿顯示區域
* AVLayerVideoGravityResize : 保證視頻鋪滿顯示區域,畫面全部顯示,但視頻內容可能會有變形
*/
playerVC.videoGravity = AVLayerVideoGravityResizeAspectFill;
//顯示播放開始,播放進度條等控件
playerVC.showsPlaybackControls = YES;
通過[self presentViewController:playerVC animated:YES completion:nil];進行調用
播放相關監聽
- status屬性
播放單元playerItem可以通過添加status屬性的監聽來獲取視頻加載的狀態。
/** 觀察status屬性, 一共有三種屬性
* AVPlayerStatusReadyToPlay : 可以播放
* AVPlayerItemStatusFailed : 加載失敗
* AVPlayerItemStatusUnknown : 未知錯誤
*/
[self.playerItem addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew) context:nil];
- loadedTimeRanges屬性
播放單元playerItem還可以添加loadedTimeRanges屬性。
[self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
以上兩種屬性均在如下代碼中返回監聽結果:(這裏的代碼直接引用了簡書作者的代碼)
作者:梧雨北辰
鏈接:https://www.jianshu.com/p/b304694af77a
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
AVPlayerItem *playerItem = (AVPlayerItem *)object;
if ([keyPath isEqualToString:@"status"]) {
//獲取playerItem的status屬性最新的狀態
AVPlayerStatus status = [[change objectForKey:@"new"] intValue];
switch (status) {
case AVPlayerStatusReadyToPlay:{
//獲取視頻長度
CMTime duration = playerItem.duration;
//更新顯示:視頻總時長(自定義方法顯示時間的格式)
self.totalNeedPlayTimeLabel.text = [self formatTimeWithTimeInterVal:CMTimeGetSeconds(duration)];
//開啓滑塊的滑動功能
self.sliderView.enabled = YES;
//關閉加載Loading提示
[self showaAtivityInDicatorView:NO];
//開始播放視頻
[self.player play];
break;
}
case AVPlayerStatusFailed:{//視頻加載失敗,點擊重新加載
[self showaAtivityInDicatorView:NO];//關閉Loading視圖
self.playerInfoButton.hidden = NO; //顯示錯誤提示按鈕,點擊後重新加載視頻
[self.playerInfoButton setTitle:@"資源加載失敗,點擊繼續嘗試加載" forState: UIControlStateNormal];
break;
}
case AVPlayerStatusUnknown:{
NSLog(@"加載遇到未知問題:AVPlayerStatusUnknown");
break;
}
default:
break;
}
} else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
//獲取視頻緩衝進度數組,這些緩衝的數組可能不是連續的
NSArray *loadedTimeRanges = playerItem.loadedTimeRanges;
//獲取最新的緩衝區間
CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];
//緩衝區間的開始的時間
NSTimeInterval loadStartSeconds = CMTimeGetSeconds(timeRange.start);
//緩衝區間的時長
NSTimeInterval loadDurationSeconds = CMTimeGetSeconds(timeRange.duration);
//當前視頻緩衝時間總長度
NSTimeInterval currentLoadTotalTime = loadStartSeconds + loadDurationSeconds;
//NSLog(@"開始緩衝:%f,緩衝時長:%f,總時間:%f", loadStartSeconds, loadDurationSeconds, currentLoadTotalTime);
//更新顯示:當前緩衝總時長
_currentLoadTimeLabel.text = [self formatTimeWithTimeInterVal:currentLoadTotalTime];
//更新顯示:視頻的總時長
_totalNeedLoadTimeLabel.text = [self formatTimeWithTimeInterVal:CMTimeGetSeconds(self.player.currentItem.duration)];
//更新顯示:緩衝進度條的值
_progressView.progress = currentLoadTotalTime/CMTimeGetSeconds(self.player.currentItem.duration);
}
}
- 監聽播放進度
播放器player可以添加時間觀察來管理播放進度
__weak __typeof(self) weakSelf = self;
[self.playerVC.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
//當前播放的時間
NSTimeInterval currentTime = CMTimeGetSeconds(time);
//視頻的總時間
NSTimeInterval totalTime = CMTimeGetSeconds(weakSelf.playerVC.player.currentItem.duration);
if (currentTime == totalTime) {
//[weakSelf dismissViewControllerAnimated:YES completion:nil]; //播放完成退出播放界面
}
}];
以上爲目前使用iOS視頻播放功能的整理。