前言:AVPlayer是用于管理媒體資產的播放和定時控制器對象它提供了控制播放器的有運輸行為的接口,如它可以在媒體的時限內播放,暫停,和改變播放的速度,并有定位各個動態(tài)點的能力。可以使用AVPlayer來播放本地和遠程的視頻媒體文件,如QuickTime影片和MP3音頻文件,以及視聽媒體使用HTTP流媒體直播服務。
一個普通播放器的組成
蘋果在視頻播放方面提供了多個框架供我們選擇使用。分別為:
基于mediaPlayer類庫的MPMediaPlayerController(iOS9后遭到廢棄,被AVPlayerViewController所替代)
基于AVFounditon類庫的AVPlayer
基于AVKit類庫的AVPlayerViewController(iOS8后才可使用)
正文
AVPlayer與MPMediaPlayerController比較:
AVplayer有比較靈活,當然,也需要你去自定義構建UI。還有一大優(yōu)勢,例如其擴展的AVQueuePlayer,可以實現(xiàn)視頻無縫隊列播放、多視頻同時播放、視頻轉換、編解碼等功能。
MPMediaPlayerController實際上是基于AVPlayer的簡單UI封裝,對于一般的播放要求,幾行代碼就可實現(xiàn),省心省事。
因為MPMediaPlayerController是對AVPlayer進行的單例封裝,所以不能進行多視頻播放。
播放器Demo(全屏)已實現(xiàn)功能點:
push到播放器頁面,橫屏顯示。
單機隱藏or顯示上方標題欄與下方操作欄。
呼出右側設置欄。
視頻播放操作與進度條設置。
在屏幕上左右拖動,進行視頻快進與快退。
在屏幕左側上下拖動,進行亮度調整。
在屏幕右側上下拖動,進行音量調整。
想到但是暫未實現(xiàn)的功能點:(大多為優(yōu)化或與業(yè)務相關)
屏幕或進度條拖動快進操作時,添加提示框進行快進時間的實時提示。
用戶無操作兩三秒之后自動隱藏上下View。
視頻清晰度調整按鈕。(更換視頻源)
操作加鎖按鈕。(加鎖后未進行解鎖操作之前不可進行操作)
彈幕相關。
用戶允許橫屏狀態(tài)下,橫屏豎屏自動進行頁面切換與動畫效果等。
網(wǎng)絡視頻的緩存、下載等。
軟硬解碼模式切換等。
筆者Demo選擇使用了AVPlayer進行視頻播放器的構建。由于UI的代碼實現(xiàn),加上略蛋疼的邏輯代碼,播放器頁面的代碼量達到400多行,之后有時間的話會再進行優(yōu)化。這里只貼出部分代碼,想要查看或借鑒完整Demo,可以到本人github去下載。
使用AVPlayer構建播放器
1.導入頭文件
#import<AVFoundation/AVFoundation.h>
2.其實沒什么可說的,很簡單,先初始化AVPlayer,然后添加到AVPlayerLayer,最后將其添加到視圖的layer層。
#pragma mark - Demo中此視圖的屬性
#define TopViewHeight 55
#define BottomViewHeight 72
#define mainWidth [UIScreen mainScreen].bounds.size.width
#define mainHeight [UIScreen mainScreen].bounds.size.height
//上層建筑@property(nonatomic,strong)UIView*topView;
@property(nonatomic,strong)UIButton*backBtn;
@property(nonatomic,strong)UILabel*titleLabel;
@property(nonatomic,strong)UIButton*settingsBtn;
@property(nonatomic,strong)UIView*bottomView;
@property(nonatomic,strong)UIButton*playBtn;
@property(nonatomic,strong)UILabel*textLabel;
@property(nonatomic,assign)BOOLisPlay;
@property(nonatomic,strong)UISlider*movieProgressSlider;//進度條@property(nonatomic,assign)CGFloatProgressBeginToMove;
@property(nonatomic,assign)CGFloattotalMovieDuration;//視頻總時間@property(nonatomic,strong)AVPlayer*player;
@property(nonatomic,strong)UIView*settingsView;
@property(nonatomic,strong)UIView*rightView;
@property(nonatomic,strong)UIButton*setTestBtn;
//touch evens
@property(nonatomic,assign)BOOLisShowView;
@property(nonatomic,assign)BOOLisSettingsViewShow;
@property(nonatomic,assign)BOOLisSlideOrClick;
@property(nonatomic,strong)UISlider*volumeViewSlider;
@property(nonatomic,assign)floatsystemVolume;//系統(tǒng)音量值@property(nonatomic,assign)floatsystemBrightness;//系統(tǒng)亮度@property(nonatomic,assign)CGPointstartPoint;//起始位置坐標@property(nonatomic,assign)BOOLisTouchBeganLeft;//起始位置方向@property(nonatomic,copy)NSString*isSlideDirection;//滑動方向@property(nonatomic,assign)floatstartProgress;//起始進度條
#pragma mark - 播放器
- (void)createAvPlayer{
//設置靜音狀態(tài)也可播放聲音
AVAudioSession*audioSession = [AVAudioSessionsharedInstance];?
? [audioSession setCategory:AVAudioSessionCategoryPlaybackerror:nil];
CGRectplayerFrame =CGRectMake(0,0,self.view.layer.bounds.size.height,self.view.layer.bounds.size.width);AVURLAsset? *asset = [AVURLAssetassetWithURL: _url];?
? Float64 duration = CMTimeGetSeconds(asset.duration);
//獲取視頻總時長
_totalMovieDuration = duration;
AVPlayerItem*playerItem = [AVPlayerItemplayer ItemWithAsset: asset];?
_player = [[AVPlayer? alloc]initWithPlayerItem:playerItem];
AVPlayerLayer? *playerLayer = [AVPlayerLayer? playerLayerWithPlayer:_player];? ? playerLayer.frame = playerFrame;??
playerLayer.videoGravity =AVLayerVideoGravityResizeAspect;?
? [self.view.layer addSublayer:playerLayer];
//需要設置自動播放的直接play即可
//[_player play];
}
屏幕單擊手勢與視頻快進
屏幕單擊
1.符合條件的情況下(手指按下后離開屏幕,并且沒有拖動)通過BOOL值判斷,隱藏或顯示上下View
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event{
CGPointpoint = [[touches anyObject] locationInView:self.view];
if(_isShowView) {
//上下View為顯示狀態(tài),此時點擊上下View直接return
if((point.y>CGRectGetMinY(self.topView.frame)&&point.yCGRectGetMinY(self.bottomView.frame))) {
return
}? ?
? ? _isShowView =NO;? ??
? [UIView? animateWithDuration:0.5? animations:^{? ?
? ? ? ? _topView.alpha =0;? ? ? ?
? ? _bottomView.alpha =0;?
? ? ? }];
? }else{? ??
? _isShowView =YES;? ? ?
? [UIView? animateWithDuration:0.5? animations:^{? ??
? ? ? _topView.alpha =1;? ? ? ?
? ? _bottomView.alpha =1;? ?
? ? }];?
? }
}
2.右側View顯示的狀態(tài)下,點擊屏幕左半空白區(qū)域,隱藏右側View
if(_isSettingsViewShow) {
if(point.x>CGRectGetMinX(_rightView.frame)&&point.x< CGRectGetMaxX(_rightView.frame)) {? ?
? ? return;
? }
_settingsView.alpha =0;
_isSettingsViewShow= NO;
}
拖動快進
1.計算后得出拖動方向為橫向拖動。
CGPoint location = [[touches? anyObject] locationInView:self.view];
CGFloatchangeY = location.y - _startPoint.y;
CGFloat? changeX = location.x - _startPoint.x;
if(fabs(changeX) > fabs(changeY)){?
? _isSlideDirection =@"橫向";//設置為橫向
}else if(fabs(changeY)>fabs(changeX)){
? _isSlideDirection =@"縱向";//設置為縱向
}else{?
? _isSlideOrClick =NO;
NSLog(@"不在五行中。");
}
2.根據(jù)手指按下與離開屏幕后,橫向位移的坐標值,對視頻播放進度進行刷新。
if(_isSlideOrClick) {?
? ? ? _isSlideDirection =@"";??
? ? _isSlideOrClick =NO;
CGFloatchangeY = point.y - _startPoint.y;
CGFloatchangeX = point.x - _startPoint.x;
//如果位置改變 刷新進度條
if(fabs(changeX) > fabs(changeY)){? ??
? ? ? [selfscrubberIsScrolling];??
? ? }
return;
? ? }
//拖動進度條
-(void)scrubberIsScrolling{
//計算出拖動的當前秒數(shù)(總長*當前百分比)
NSInteger? dragedSeconds = floorf(_totalMovieDuration * _movieProgressSlider.value);
CMTime? newCMTime =CMTimeMake(dragedSeconds,1);? ?
[_player seekToTime:newCMTime completionHandler:^(BOOLfinished) {??
? ? [_player play];? ?
? ? [_playBtn setTitle:@"暫停"forState:UIControlStateNormal];??
}];
}
MPMediaPlayerController與AVPlayerViewController的使用介紹
MPMediaPlayerController與AVPlayerViewController,兩者都是基于AVPlayer的簡單UI封裝,如果只是需要簡單的視頻播放功能,可以使用這兩個類快速的構建視頻播放器。
MPMediaPlayerController
1.導入頭文件
#import<MediaPlayer/MediaPlayer.h>
2.初始化mp,幾行代碼既可以實現(xiàn)。
@property(nonatomic,strong)MPMoviePlayerController *mp;
NSURL*url1 = [[NSBundle? mainBundle]URLForResource:@"chenyifaer"withExtension:@"mp4"];
_mp = [[MPMoviePlayerController? alloc] initWithContentURL:url1];
_mp.controlStyle =MPMovieControlStyleNone;
_mp.view.frame = CGRectMake(0,0,self.view.layer.bounds.size.height,self.view.layer.bounds.size.width);[self.view addSubview:_mp.view];
[_mp play];
controlStyle屬性有三個值:
MPMovieControlStyleNone,? ? ? //無控制
MPMovieControlStyleEmbedded,? //有全屏按鈕與控制
MPMovieControlStyleFullscreen, // 默認全屏,有退出和控制
當然還有一些其他屬性,有需要可以自行進行設置。
AVPlayerViewController
1.導入框架與頭文件
#import<AVKit/AVKit.h>
2.初始化AVPlayerViewController,創(chuàng)建一個AVPlayer添加上。然后將其添加到視圖上,再將View添加到self.View上,然后play即可
NSURL*url1 = [[NSBundle mainBundle]URLForResource:@"chenyifaer"withExtension:@"mp4"];
AVPlayer* player = [AVPlayer playerWithURL:url1];
AVPlayerViewController *playerController = [[AVPlayerViewControlleralloc]init];
playerController.player = player;
[self addChildViewController:playerController];
[self.view addSubview:playerController.view];
playerController.view.frame =CGRectMake(0,0,self.view.layer.bounds.size.height,self.view.layer.bounds.size.width);[player? play];
同樣幾行代碼,即可實現(xiàn)。
音量調整
1.導入頭文件
#import<MediaPlayer/MediaPlayer.h>
2.借助MPVolumeView類來獲取到其音量進度條,進而進行音量獲取與控制
@property(nonatomic,strong)UISlider*movieProgressSlider;//進度條MPVolumeView*volumeView = [[MPVolumeViewalloc] init];
_volumeViewSlider =nil;
for(UIView*view? in [volumeView subviews]){
if([view.class.description isEqualToString:@"MPVolumeSlider"]){? ? ? ? _volumeViewSlider = (UISlider*)view;
break;
}
3.觸摸屏幕時,記錄手指按下的位置、獲取按下時系統(tǒng)的音量(實現(xiàn)touchesBegan方法)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{? ? ? ? _startProgress = _movieProgressSlider.value;
}
4.手指在規(guī)定行為下(手指按下位置為視圖右半?yún)^(qū),且縱向滑動)持續(xù)滑動時,動態(tài)改變系統(tǒng)音量(實現(xiàn)touchesMoved方法)
//手指持續(xù)滑動,此方法會持續(xù)調用
- (void)touchesMoved:(NSSet *)toucheswithEvent:(UIEvent *)event{??
CGPoint location = [[touches anyObject]locationInView:self.view];
intindex = location.y - _startPoint.y;if(index>0){? ? ? ? [_volumeViewSlidersetValue:_systemVolume - (abs(index)/10*0.05)animated:YES];? ? ? ? [_volumeViewSlidersendActionsForControlEvents:UIControlEventTouchUpInside];? ? }else{??
? [_volumeViewSlidersetValue:_systemVolume + (abs(index)/10*0.05)animated:YES];? ? ? ? [_volumeViewSlidersendActionsForControlEvents:UIControlEventTouchUpInside];? ? }
}
亮度調整
1.觸摸屏幕時,記錄手指按下的位置、按下時屏幕的亮度(實現(xiàn)touchesBegan方法)
2.手指在規(guī)定行為下(手指按下位置為視圖左半?yún)^(qū),且縱向滑動)持續(xù)滑動時,不斷動態(tài)處理(實現(xiàn)touchesMoved方法)
3.改變屏幕亮度:[UIScreen mainScreen].brightness = X (0~1);
//手指持續(xù)滑動,此方法會持續(xù)調用
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{? ? CGPointlocation= [[touches anyObject] locationInView:self.view];
int index= location.y - _startPoint.y;
if(index>0){? ? ?
?[UIScreen mainScreen].brightness = _systemBrightness -abs(index)/10*0.01;?
? }else{? ?
? ? _movieProgressSlider.value = _startProgress -abs(index)/10*0.008;? ?
}
}
屏幕旋轉
1.設置應用支持橫屏(默認支持)。
2.在根視圖中設置默認豎屏(Nav、TabBar、VC基類)
- (BOOL)shouldAutorotate{returnNO;}- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
returnUIInterfaceOrientationMaskPortrait;
}
3.在需要橫屏的VC中重寫下列方法即可
//允許橫屏旋轉
- (BOOL)shouldAutorotate{returnYES;
}
//支持左右旋轉
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscapeRight|UIInterfaceOrientationMaskLandscapeLeft;
}//默認為右旋轉
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
returnUIInterfaceOrientationLandscapeRight;
}
參考:
1.http://www.techotopia.com/index.php/iOS8AVPlayerAndPlayerViewController
2.http://stackoverflow.com/questions/8146942/avplayer-and-mpmovieplayercontroller-differences