2014-5-7 06:46| 发布者: admin| 查看: 437| 评论: 0

 
摘要:   在iOS开发中,播放视频通常有两种方式,一种是使用MPMoviePlayerController(需要导入MediaPlayer.Framework),还有一种是使用AVPlayer。关于这两个类的区别可以参考http://stackoverflow.com/questions/814694 ...
 
 

  在ios开发中,播放视频通常有两种方式,一种是使用MPMoviePlayerController(需要导入MediaPlayer.Framework),还有一种是使用AVPlayer。关于这两个类的区别可以参考http://stackoverflow.com/questions/8146942/avplayer-and-mpmovieplayercontroller-differences,简而言之就是MPMoviePlayerController使用更简单,功能不如AVPlayer强大,而AVPlayer使用稍微麻烦点,不过功能更加强大。这篇博客主要介绍下AVPlayer的基本使用,由于博主也是刚刚接触,所以有问题大家直接指出~

  在开发中,单纯使用AVPlayer类是无法显示视频的,要将视频层添加至AVPlayerLayer中,这样才能将视频显示出来,所以先在ViewController的@interface中添加以下属性

@property (nonatomic ,strong) AVPlayer *player;@property (nonatomic ,strong) AVPlayerItem *playerItem;
@property (nonatomic ,weak) IBOutletPlayerView *playerView;

其中playerView继承自UIView,不过重写了set和get方法,用于将player添加至playerView的AVPlayerLayer中,这样才能顺利将视频显示出来

在PlayerView.h中声明一个AVPlayer对象,由于默认的layer是CALayer,而AVPlayer只能添加至AVPlayerLayer中,所以我们改变一下layerClass,这样PlayerView的默认layer就变了,之后我们可以把在viewController中初始化的AVPlayer对象赋给AVPlayerLayer的player属性。

 PlayerView.h 

 @property (nonatomic ,strong) AVPlayer *player;

 PlayerView.m

+ (Class)layerClass {    return [AVPlayerLayer class];}- (AVPlayer *)player {    return [(AVPlayerLayer *)[self layer] player];}- (void)setPlayer:(AVPlayer *)player {    [(AVPlayerLayer *)[self layer] setPlayer:player];}

然后在viewDidLoad中执行初始化:

NSURL *videoUrl = [NSURL URLWithString:@"http://www.jxvdy.com/file/upload/201405/05/18-24-58-42-627.mp4"];self.playerItem = [AVPlayerItem playerItemWithURL:videoUrl];[self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];// 监听status属性[self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];// 监听loadedTimeRanges属性self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotificationobject:self.playerItem];

先将在线视频链接存放在videoUrl中,然后初始化playerItem,playerItem是管理资源的对象(A player item manages the presentation state of an asset with which it is associated. A player item contains player item tracks—instances of AVPlayerItemTrack—that correspond to the tracks in the asset.)

然后监听playerItem的status和loadedTimeRange属性,status有三种状态:

AVPlayerStatusUnknown,

AVPlayerStatusReadyToPlay,

AVPlayerStatusFailed

当status等于AVPlayerStatusReadyToPlay时代表视频已经可以播放了,我们就可以调用play方法播放了。

loadedTimeRange属性代表已经缓冲的进度,监听此属性可以在UI中更新缓冲进度,也是很有用的一个属性。

最后添加一个通知,用于监听视频是否已经播放完毕,然后实现KVO的方法:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {    AVPlayerItem *playerItem = (AVPlayerItem *)object;    if ([keyPath isEqualToString:@"status"]) {        if ([playerItem status] == AVPlayerStatusReadyToPlay) {            NSLog(@"AVPlayerStatusReadyToPlay");            self.stateButton.enabled = YES;            CMTime duration = self.playerItem.duration;// 获取视频总长度            CGFloat totalSecond = playerItem.duration.value / playerItem.duration.timescale;// 转换成秒            _totalTime = [self convertTime:totalSecond];// 转换成播放时间            [self customVideoSlider:duration];// 自定义UISlider外观            NSLog(@"movie total duration:%f",CMTimeGetSeconds(duration));            [self monitoringPlayback:self.playerItem];// 监听播放状态        } else if ([playerItem status] == AVPlayerStatusFailed) {            NSLog(@"AVPlayerStatusFailed");        }    } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {        NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度        NSLog(@"Time Interval:%f",timeInterval);        CMTime duration = self.playerItem.duration;        CGFloat totalDuration = CMTimeGetSeconds(duration);        [self.videoProgress setProgress:timeInterval / totalDuration animated:YES];    }}- (NSTimeInterval)availableDuration {    NSArray *loadedTimeRanges = [[self.playerView.player currentItem] loadedTimeRanges];    CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域    float startSeconds = CMTimeGetSeconds(timeRange.start);    float durationSeconds = CMTimeGetSeconds(timeRange.duration);    NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度    return result;}- (NSString *)convertTime:(CGFloat)second{    NSDate *d = [NSDate dateWithTimeIntervalSince1970:second];    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];    if (second/3600 >= 1) {        [formatter setDateFormat:@"HH:mm:ss"];    } else {        [formatter setDateFormat:@"mm:ss"];    }    NSString *showtimeNew = [formatter stringFromDate:d];    return showtimeNew;}

此方法主要对status和loadedTimeRanges属性做出响应,status状态变为AVPlayerStatusReadyToPlay时,说明视频已经可以播放了,这时我们可以获取一些视频的信息,包含视频长度等,把播放按钮设备enabled,点击就可以调用play方法播放视频了。在AVPlayerStatusReadyToPlay的底部还有个monitoringPlayback方法:

- (void)monitoringPlayback:(AVPlayerItem *)playerItem {    self.playbackTimeObserver = [self.playerView.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time) {        CGFloat currentSecond = playerItem.currentTime.value/playerItem.currentTime.timescale;// 计算当前在第几秒        [self updateVideoSlider:currentSecond];        NSString *timeString = [self convertTime:currentSecond];        self.timeLabel.text = [NSString stringWithFormat:@"%@/%@",timeString,_totalTime];    }];}

monitoringPlayback用于监听每秒的状态,- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;此方法就是关键,interval参数为响应的间隔时间,这里设为每秒都响应,queue是队列,传NULL代表在主线程执行。可以更新一个UI,比如进度条的当前时间等。

  作为播放器,除了播放,暂停等功能外。还有一个必不可少的功能,那就是显示当前播放进度,还有缓冲的区域,我的思路是这样,用UIProgressView显示缓冲的可播放区域,用UISlider显示当前正在播放的进度,当然这里要对UISlider做一些自定义,代码如下:

- (void)customVideoSlider:(CMTime)duration {    self.videoSlider.maximumValue = CMTimeGetSeconds(duration);    UIGraphicsBeginImageContextWithOptions((CGSize){ 1, 1 }, NO, 0.0f);    UIImage *transparentImage = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();        [self.videoSlider setMinimumTrackImage:transparentImage forState:UIControlStateNormal];    [self.videoSlider setMaximumTrackImage:transparentImage forState:UIControlStateNormal];}

这样UISlider就只有中间的ThumbImage了,而ThumbImage左右的颜色都变成透明的了,仅仅是用于显示当前的播放时间。UIProgressView则用于显示当前缓冲的区域,不做任何自定义的修改,在StoryBoard看起来是这样的:

把UISlider添加至UIProgressView上面,运行起来的效果就变成了这样:

这样基本的缓冲功能就做好了,当然还有一些功能没做,比如音量大小,滑动屏幕快进快退等,大家有时间可以自己做着玩儿下~ 最后的效果如下:

AVPlayer的基本使用的更多相关文章

  1. AVPlayer

    AVPlayer     AVPlayerLayer是CALayer的一个子类,由于AVPlayer这个播放器只能安置在AVPlayerLayer 这个图层之上,所以我们需要实例化一个UIView,并 ...

  2. 基于 AVPlayer 自定义播放器

    如果我只是简单的播放一个视频,而不需要考虑播放器的界面.iOS9.0 之前使用 MPMoviePlayerController, 或者内部自带一个 view 的 MPMoviePlayerViewCo ...

  3. iOS播放器 - AVPlayer

    之前有说到在播放器中一点点小技巧,现在正式记录一下AVPlayer. 这里主要是说明用AVPlayer做音乐播放器的功能实现,所以不介绍AVPlayer中那个图层类. 首先我们要声明一下播放器,这里有 ...

  4. An AVPlayerItem cannot be associated with more than one instance of AVPlayer错误

    An AVPlayerItem cannot be associated with more than one instance of AVPlayer An AVPlayerItem cannot ...

  5. iOS:基于AVPlayer实现的视频播放器

    最近在学习AVFoundation框架的相关知识,写了一个基于AVPlayer的视频播放器,相关功能如下图: 代码github:https://github.com/wzpziyi1/VideoPla ...

  6. iOS开发 - AVPlayer实现流音频边播边存

    边播边下有三套左右实现思路,本文使用AVPlayer + AVURLAsset实现. 概述 1. AVPlayer简介 AVPlayer存在于AVFoundation中,可以播放视频和音频,可以理解为 ...

  7. AVPlayer的使用本地视频

    1引入AVFoundation.framework框架 2引入头文件<AVFoundation/AVFoundation.h>,并拖入需要播放的视频文件 代码如下: 自定义播放的View, ...

  8. iOS - AVPlayer 音视频播放

    前言 NS_CLASS_AVAILABLE(10_7, 4_0) @interface AVPlayer : NSObject @available(iOS 4.0, *) public class ...

  9. iOS在线音乐播放SZKAVPlayer(基于AVPlayer的封装)

    由于最近闲着没事,想找有关在线音乐播放的demo学习一下,在gitHub跟code4APP上面查找了很多帖子,结果很多在线音乐都是基于AudioStream实现的,我感觉用起来不太方便.后来突然发现, ...

随机推荐

  1. Unity之坐标转换

    1.世界坐标→屏幕坐标:camera.WorldToScreenPoint(transform.position);这样可以将世界坐标转换为屏幕坐标.其中camera为场景中的camera对象. 2. ...

  2. activity传递数据

    这些都是老生常谈了,到处都搜的到,但是因为经常忘记,放着好调用: 传递数据: Intent intent = new Intent(); Bundle bundle = new Bundle(); b ...

  3. 北大ACM(POJ1013-Counterfeit Dollar)

    Question:http://poj.org/problem?id=1013 问题点:排除+验证. Memory: 244K Time: 16MS Language: C++ Result: Acc ...

  4. vs怎么创建MVC及理解其含义

    怎么创建MVC项目 一·1.点击 文件à新建à项目à模板àVisua C#(选择 .NET Framework 4.0或以上版本) à选择 MVC 3 Web应用程序 或者MVC 4 Web应用程序à ...

  5. jquery的clone方法 于textarea和select的bug修复

    在使用jquery的clone方法时,textarea和select的值clone的时候会丢掉,这可能是这个方法的一个BUG.解决办法就是在clone的时候将val再重新赋值一下. 引入到你要用的cl ...

  6. VxWorks 6.9 内核编程指导之读书笔记 -- 多任务

    概述 VxWork系统任务 任务调度 任务创建和管理 任务的错误状态 任务异常处理 共享代码和重入 概述 现代实时操作系统是基于多任务和任务间通信的概念的.多任务环境运行一个实时进程RTP可以被作为一 ...

  7. 单机版简单弹幕墙demo (jqery+bootstrap)

    最近在看fcc  ,上面有一个弹幕墙设计的题目,要求从后端获取数据,显示出来.百度,谷歌都没找到相关好的例子作为借鉴,索性按照自己的思路写了一个简单的demo  .在做demo的过程中遇到最大的问题就 ...

  8. Excel中 设置使得每行的颜色不一样

        在编写测试案例的时候,众多的excel行看的眼睛花花的,这里给出一个小技巧,设置Excel的每行显示的颜色不一样,最终的效果如下:    具体操作:     1. Ctrl+A全选所有表格区域 ...

  9. (栈)栈 给定push序列,判断给定序列是否是pop序列

    题目: 输入两个整数序列.其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序.为了简单起见,我们假设push序列的任意两个整数都是不相等的. 比如输入的push序列是1.2. ...

  10. 第二章 开始学习C++

    第二章  开始学习C++ 2.1  main函数 简单代码如下: #include <iostream> int main() { //This is my first program u ...