iOS视频播放器AVPlayer创建

前言:AVPlayer是用于管理媒体资产的播放和定时控制器对象它提供了控制播放器的有运输行为的接口,如它可以在媒体的时限内播放,暂停,和改变播放的速度,并有定位各个动态点的能力。可以使用AVPlayer来播放本地和远程的视频媒体文件,如QuickTime影片和MP3音频文件,以及视听媒体使用HTTP流媒体直播服务。

一个普通播放器的组成





苹果在视频播放方面提供了多个框架供我们选择使用。分别为:

基于mediaPlayer类库的MPMediaPlayerController(iOS9后遭到废弃,被AVPlayerViewController所替代)

基于AVFounditon类库的AVPlayer

基于AVKit类库的AVPlayerViewController(iOS8后才可使用)

正文

AVPlayer与MPMediaPlayerController比较:

AVplayer有比较灵活,当然,也需要你去自定义构建UI。还有一大优势,例如其扩展的AVQueuePlayer,可以实现视频无缝队列播放、多视频同时播放、视频转换、编解码等功能。

MPMediaPlayerController实际上是基于AVPlayer的简单UI封装,对于一般的播放要求,几行代码就可实现,省心省事。

因为MPMediaPlayerController是对AVPlayer进行的单例封装,所以不能进行多视频播放

播放器Demo(全屏)已实现功能点:

push到播放器页面,横屏显示。

单机隐藏or显示上方标题栏与下方操作栏。

呼出右侧设置栏。

视频播放操作与进度条设置。

在屏幕上左右拖动,进行视频快进与快退。

在屏幕左侧上下拖动,进行亮度调整。

在屏幕右侧上下拖动,进行音量调整。

想到但是暂未实现的功能点:(大多为优化或与业务相关)

屏幕或进度条拖动快进操作时,添加提示框进行快进时间的实时提示。

用户无操作两三秒之后自动隐藏上下View。

视频清晰度调整按钮。(更换视频源)

操作加锁按钮。(加锁后未进行解锁操作之前不可进行操作)

弹幕相关。

用户允许横屏状态下,横屏竖屏自动进行页面切换与动画效果等。

网络视频的缓存、下载等。

软硬解码模式切换等。

笔者Demo选择使用了AVPlayer进行视频播放器的构建。由于UI的代码实现,加上略蛋疼的逻辑代码,播放器页面的代码量达到400多行,之后有时间的话会再进行优化。这里只贴出部分代码,想要查看或借鉴完整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;//系统音量值@property(nonatomic,assign)floatsystemBrightness;//系统亮度@property(nonatomic,assign)CGPointstartPoint;//起始位置坐标@property(nonatomic,assign)BOOLisTouchBeganLeft;//起始位置方向@property(nonatomic,copy)NSString*isSlideDirection;//滑动方向@property(nonatomic,assign)floatstartProgress;//起始进度条

#pragma mark - 播放器

- (void)createAvPlayer{

//设置静音状态也可播放声音

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为显示状态,此时点击上下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显示的状态下,点击屏幕左半空白区域,隐藏右侧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.根据手指按下与离开屏幕后,横向位移的坐标值,对视频播放进度进行刷新。

if(_isSlideOrClick) { 

      _isSlideDirection =@"";  

    _isSlideOrClick =NO;

CGFloatchangeY = point.y - _startPoint.y;

CGFloatchangeX = point.x - _startPoint.x;

//如果位置改变 刷新进度条

if(fabs(changeX) > fabs(changeY)){    

      [selfscrubberIsScrolling];  

    }

return;

    }

//拖动进度条

-(void)scrubberIsScrolling{

//计算出拖动的当前秒数(总长*当前百分比)

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,几行代码既可以实现。

@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,创建一个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];

同样几行代码,即可实现。

音量调整

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.触摸屏幕时,记录手指按下的位置、获取按下时系统的音量(实现touchesBegan方法)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{        _startProgress = _movieProgressSlider.value;

}

4.手指在规定行为下(手指按下位置为视图右半区,且纵向滑动)持续滑动时,动态改变系统音量(实现touchesMoved方法)

//手指持续滑动,此方法会持续调用

- (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.触摸屏幕时,记录手指按下的位置、按下时屏幕的亮度(实现touchesBegan方法)

2.手指在规定行为下(手指按下位置为视图左半区,且纵向滑动)持续滑动时,不断动态处理(实现touchesMoved方法)

3.改变屏幕亮度:[UIScreen mainScreen].brightness = X (0~1);

//手指持续滑动,此方法会持续调用

- (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

3.http://www.jianshu.com/p/e64fe3c7f9ab

4.http://www.th7.cn/Program/IOS/201504/439086.shtml

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容