摘自:http://blog.csdn.net/u011334685/article/details/42675179
说明:用系统自带的AVPlayer类实现一个简单的视频播放器。它既能播放本地视频,也能较流畅地播放网络视频。
首先要引入AVFoundation.framework框架;
播放器类.h文件代码如下:
- #import <UIKit/UIKit.h>
- #import <AVFoundation/AVFoundation.h>
- @interface PlayView : UIView
- -(void)setPlayer:(AVPlayer *)myPlayer;
- -(void)playWith:(NSURL *)url;
- -(void)releasePlayer;
- @end
播放器类.m文件代码如下:
- #import "PlayView.h"
- @interface PlayView()
- {
- UIView *_bgView;
- //播放器
- AVPlayer *_player;
- //用于显示(控制)视频的播放进度
- UISlider *_progressSlider;
- }
- -(void)uiConfigWith:(CGRect)bframe;
- @end
- @implementation PlayView
- - (id)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- [self uiConfigWith:frame];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];
- }
- return self;
- }
- -(void)uiConfigWith:(CGRect)bframe
- {
- self.backgroundColor=[UIColor blackColor];
- _bgView=[[UIView alloc]initWithFrame:CGRectMake(0, bframe.size.height-50, bframe.size.width, 50)];
- _bgView.backgroundColor=[UIColor lightGrayColor];
- [self addSubview:_bgView];
- //播放暂停按钮
- UIButton *playBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- [playBtn setFrame:CGRectMake(0,0,100,50)];
- playBtn.backgroundColor=[UIColor whiteColor];
- playBtn.selected=YES;
- [playBtn setTitle:@"play" forState:UIControlStateNormal];
- [playBtn setTitle:@"pause" forState:UIControlStateSelected];
- [playBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
- [playBtn addTarget:self action:@selector(playBtnClick:) forControlEvents:UIControlEventTouchUpInside];
- [_bgView addSubview:playBtn];
- _progressSlider= [[UISlider alloc] initWithFrame:CGRectMake(100,0,bframe.size.width-100,50)];
- _progressSlider.minimumValue = 0.0;
- _progressSlider.maximumValue = 1.0;
- [_progressSlider addTarget:self action:@selector(progressChange:) forControlEvents:UIControlEventValueChanged];
- [_bgView addSubview:_progressSlider];
- }
- //每个视图都对应一个层,改变视图的形状、动画效果\与播放器的关联等,都可以在层上操作
- //播放器支持的播放格式:mp4、mov(iPhone手机录制视频的默认格式) avi
- -(void)setPlayer:(AVPlayer *)myPlayer
- {
- AVPlayerLayer *playerLayer=(AVPlayerLayer *)self.layer;
- [playerLayer setPlayer:myPlayer];
- }
- //在调用视图的layer时,会自动触发layerClass方法,重写它,保证返回的类型是AVPlayerLayer
- +(Class)layerClass
- {
- return [AVPlayerLayer class];
- }
- -(void)playWith:(NSURL *)url
- {
- //加载视频资源的类
- AVURLAsset *asset = [AVURLAsset assetWithURL:url];
- //AVURLAsset 通过tracks关键字会将资源异步加载在程序的一个临时内存缓冲区中
- [asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler:^{
- //能够得到资源被加载的状态
- AVKeyValueStatus status = [asset statusOfValueForKey:@"tracks" error:nil];
- //如果资源加载完成,开始进行播放
- if (status == AVKeyValueStatusLoaded) {
- //将加载好的资源放入AVPlayerItem 中,item中包含视频资源数据,视频资源时长、当前播放的时间点等信息
- AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
- _player = [[AVPlayer alloc] initWithPlayerItem:item];
- //将播放器与播放视图关联
- [self setPlayer:_player];
- [_player play];
- //需要时时显示播放的进度
- //根据播放的帧数、速率,进行时间的异步(在子线程中完成)获取
- [_player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_global_queue(0, 0) usingBlock:^(CMTime time) {
- //获取时间
- //获取当前播放时间(根据帧数和播放速率,视频资源的总长度得到的CMTime)
- CMTime current = _player.currentItem.currentTime;
- //总时间
- CMTime dur =_player.currentItem.duration;
- //CMTimeGetSeconds 将描述视频时间的结构体转化为float(秒)
- float pro = CMTimeGetSeconds(current)/CMTimeGetSeconds(dur);
- //回到主线程刷新UI
- dispatch_async(dispatch_get_main_queue(), ^{
- //要考虑到代码的健壮性
- /*1、在向对象发送消息前,要判断对象是否为空
- *2、一些值(数组、控制中的属性值)是否越界的判断
- *3、是否对各种异常情况进行了处理(照片、定位 用户允许、不允许)
- *4、数据存储,对nil的判断或处理
- *5、对硬件功能支持情况的判断等
- */
- if (pro >=0 && pro <=1) {
- _progressSlider.value = pro;
- }
- });
- }];
- }
- }];
- }
- #pragma mark -------BtnClick---------
- -(void)playBtnClick:(UIButton *)btn
- {
- if (btn.selected==YES) { //暂停按钮被点击
- if (_player) {
- [_player pause];
- }
- btn.selected=NO;
- return;
- }
- //播放按钮被点击
- if (_player) {
- [_player play];
- }
- btn.selected=YES;
- return;
- }
- -(void)progressChange:(UISlider *)sl
- {
- //通过进度条控制播放进度
- if (!_player) {
- return;
- }
- CMTime dur = _player.currentItem.duration;
- float current = _progressSlider.value;
- //CMTimeMultiplyByFloat64 将总时长,当前进度,转化成为CMTime
- //seekToTime 跳转到指定的时间
- [_player seekToTime:CMTimeMultiplyByFloat64(dur, current)];
- }
- //销毁player
- -(void)releasePlayer
- {
- if (_player) {
- [_player pause];
- _player=nil;
- }
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- for(int i=0;i<[_bgView.subviews count];i++)
- {
- UIView *view=[_bgView.subviews objectAtIndex:i];
- [view removeFromSuperview];
- view=nil;
- i--;
- }
- [_bgView removeFromSuperview];
- _bgView=nil;
- }
- #pragma mark ------Notification-------
- -(void)moviePlayDidEnd:(NSNotification*)notification
- {
- NSLog(@"视频播放完毕!");
- }
- @end
这个简单的视频播放器类就做好了。
在ViewController类中创建一个简单的按钮,点击按钮,调用PlayView类播放视频。
如果是网络视频,
- NSURL *url = [NSURL URLWithString:@"http://123.com/123.mp4"];
- NSString *path=[[NSBundle mainBundle]pathForResource:@"123.mp4" ofType:nil];
- NSURL *url=[NSURL fileURLWithPath:path];
- PlayView *playView=[[PlayView alloc] initWithFrame:CGRectMake(0, 0, 320, 300)];
- [playView playWith:url];
- [self.view addSubview:playView];