AVPlayer的功能很强大,既可以播放视频, 也可以播放音频, 既可以播放本地的, 也可以播放网络的;
下面是我封装的一个AVPlayer的Demo,在ViewController中实现
工程中的所有东西如下:
创建一个PlayView类,PlayView.h中的代码如下
#import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @class PlayView; @protocol PlayViewDelegate <NSObject> @optional //向左转全屏播放 - (void)fullScreen:(PlayView *)playerView; //左全屏转回小窗口播放 - (void)normalScreen:(PlayView *)playerView; //向右转全屏播放 - (void)turnRight:(PlayView *)playerView; //右全屏转窗口播放 - (void)rtghtTurnBack:(PlayView *)playerView; //播放失败 - (void)AVPlayerStatusFailed:(PlayView *)playerView; @end @interface PlayView : UIView @property (nonatomic, strong) NSURL *url; @property (nonatomic, strong) AVPlayer *player; @property (nonatomic, strong) UIView *container; @property (nonatomic, strong) AVPlayerItem *playerItem; @property (nonatomic, strong) UIButton *playButton; @property (nonatomic, strong) UIButton *fullButton; @property (nonatomic, strong) UILabel *startTime; @property (nonatomic, strong) UILabel *endTime; @property (nonatomic, strong) UILabel *gang; @property (nonatomic, strong) UISlider *progress; @property (nonatomic, strong) UISlider *playableProgress; @property (nonatomic, strong) UISlider *volume; @property (nonatomic, strong) UIView *backView; @property (nonatomic, strong) UIActivityIndicatorView *actiity; @property (nonatomic, assign) BOOL isSliding; @property (nonatomic, assign) BOOL istouched; @property (nonatomic, strong) NSTimer *timer; @property (nonatomic, strong)UIImageView *imageView; @property (nonatomic, assign)BOOL _isSmall; @property (nonatomic, strong) NSString *urlStr; @property (nonatomic, strong)AVPlayerLayer *playerLayer; @property (nonatomic, assign)id<PlayViewDelegate> delegate; @end
PlayView.m中的代码如下
#import "PlayView.h" #define KScreenWidth [[UIScreen mainScreen]bounds].size.width #define KScreenHeight [[UIScreen mainScreen]bounds].size.height #define WIDTH [UIScreen mainScreen].bounds.size.width #define HEIGHT [UIScreen mainScreen].bounds.size.height @implementation PlayView /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { //设置活跃, 声音才有 AVAudioSession *session = [AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayback error:nil]; [session setActive:YES error:nil]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:self.urlStr]]; self.player = [AVPlayer playerWithPlayerItem:playerItem]; // _playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; // _playerLayer.frame = self.frame; // [self.layer addSublayer:_playerLayer]; // [self addSubview:self.backView]; // UITapGestureRecognizer *singRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideTap)]; // [self addGestureRecognizer:singRecognizer]; // _imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"play_1"]]; // _imageView.frame = CGRectMake(KScreenWidth / 2 - 30, 340, 30, 30); // [self addSubview:self.imageView]; // [self tap]; } return self; } - (void)layoutSubviews { [super layoutSubviews]; self.playerLayer.frame = self.bounds; [self.backView removeFromSuperview]; //长条视图 _backView = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height - WIDTH /10, self.bounds.size.width, WIDTH /10)]; _backView.backgroundColor = [UIColor brownColor]; // _backView.hidden = YES; [self addSubview:self.backView]; //播放暂停按钮 self.playButton = [UIButton buttonWithType:UIButtonTypeCustom]; _playButton.frame = CGRectMake(WIDTH / 37.5, WIDTH / 70, WIDTH / 16.5, WIDTH / 16.5); _playButton.layer.cornerRadius = WIDTH / 16.5 / 2; _playButton.clipsToBounds = YES; [_playButton addTarget:self action:@selector(playClick) forControlEvents:UIControlEventTouchUpInside]; [_playButton setImage:[UIImage imageNamed:@"pause"] forState:UIControlStateNormal]; [_playButton setImage:[UIImage imageNamed:@"play"] forState:UIControlStateSelected]; [self.backView addSubview:self.playButton]; //进度条 _playableProgress = [[UISlider alloc] initWithFrame:CGRectMake(40, 10, KScreenWidth - 100, 15)]; _playableProgress.minimumTrackTintColor = [UIColor whiteColor]; _playableProgress.maximumTrackTintColor = [UIColor clearColor]; [_playableProgress setThumbImage:[[UIImage alloc] init] forState:UIControlStateNormal]; [_playableProgress setThumbImage:[[UIImage alloc] init] forState:UIControlStateSelected]; [self.backView addSubview:self.playableProgress]; //状态条 self.progress = [[UISlider alloc] initWithFrame:CGRectMake(40, 10, KScreenWidth - 100, 15)]; _progress.minimumTrackTintColor = [UIColor whiteColor]; _progress.maximumTrackTintColor = [UIColor clearColor]; UIImage *image = [UIImage imageNamed:@"ThumBut"]; [_progress setThumbImage:image forState:UIControlStateNormal]; [_progress setThumbImage:image forState:UIControlStateSelected]; [self.progress addTarget:self action:@selector(valueChange:other:) forControlEvents:UIControlEventValueChanged]; [self.backView addSubview:self.progress]; //起始时间 Label self.startTime = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(self.progress.frame) - WIDTH / 6.25, 25, WIDTH / 6.25, WIDTH / 37.5)]; _startTime.text = @"00:00"; _startTime.font = [UIFont systemFontOfSize:12]; _startTime.textColor = [UIColor redColor]; [self.backView addSubview:self.startTime]; //结束时间 Label self.endTime = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(self.progress.frame) - WIDTH / 16.25, 25, WIDTH / 6.25, WIDTH / 37.5)]; _endTime.text = @"00:00"; _endTime.font = [UIFont systemFontOfSize:12]; _endTime.textColor = [UIColor redColor]; [self.backView addSubview:self.endTime]; //中间 / Label self.gang = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(self.progress.frame) - WIDTH / 13.25, 25, WIDTH / 6.25, WIDTH / 37.5)]; _gang.text = @"/"; _gang.font = [UIFont systemFontOfSize:12]; _gang.textColor = [UIColor redColor]; [self.backView addSubview:self.gang]; //全屏按钮 self.fullButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_fullButton setImage:[UIImage imageNamed:@"quanping"] forState:UIControlStateNormal]; _fullButton.frame = CGRectMake(self.bounds.size.width - WIDTH / 10, 10, WIDTH / 16.5, WIDTH / 16.5); [_fullButton addTarget:self action:@selector(bigOrSmall) forControlEvents:(UIControlEventTouchUpInside)]; [self.backView addSubview:self.fullButton]; //隐藏长条的手势 UITapGestureRecognizer *singRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideTap)]; [self addGestureRecognizer:singRecognizer]; } - (void)setUrlStr:(NSString *)urlStr { // [self.playerLayer removeFromSuperlayer]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:urlStr]]; [self addObserverToPlayerItem:_playerItem]; [self.player replaceCurrentItemWithPlayerItem:playerItem]; self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];//设置播放层 self.playerLayer.frame = self.layer.bounds; self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; [self.layer addSublayer:self.playerLayer]; //开始播放 [self.player play]; self.backView.hidden = YES; [self addProgressObserver]; [self addNotification]; [self.player addObserver:self forKeyPath:@"currentItem.status" options:NSKeyValueObservingOptionNew context:nil]; [self.player addObserver:self forKeyPath:@"currentItem.loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; } //定时器隐藏状态条 - (void)hideTap{ [UIView animateWithDuration:0.5 animations:^{ if (self.backView.hidden == NO) { self.backView.hidden = YES; } else { self.backView.hidden = NO; [self useTimerToHiddenBackView];//定时器隐藏状态条 } } completion:^(BOOL finish){ }]; } //定时器隐藏状态条的时间 - (void)useTimerToHiddenBackView { [self.timer invalidate]; if (!self.backView.hidden) { self.timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(hiddenBackView) userInfo:nil repeats:YES]; } } //隐藏状态条 - (void)hiddenBackView { self.backView.hidden = YES; } //获取播放时间 - (void)addProgressObserver{ AVPlayerItem *playerItem = self.player.currentItem; __weak typeof(self) weakSelf = self; [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { float current = CMTimeGetSeconds(time); float total =CMTimeGetSeconds([playerItem duration]); if (current) { if (!weakSelf.isSliding) { weakSelf.progress.value = current/total; } weakSelf.startTime.text = [weakSelf currentTimeToString:current]; } }]; } - (void)addObserverToPlayerItem:(AVPlayerItem *)playerItem{ [playerItem addObserver:self forKeyPath:@"currentItem.status" options:NSKeyValueObservingOptionNew context:nil]; [playerItem addObserver:self forKeyPath:@"currentItem.loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{ AVPlayer *avPlayer = (AVPlayer *)object; if ([keyPath isEqualToString:@"currentItem.status"]) { // AVPlayerStatus status = [[change objectForKey:@"new"] intValue]; NSInteger minit; NSInteger sceond; if (avPlayer.currentItem.status ==AVPlayerStatusReadyToPlay) { [self playClick]; minit = CMTimeGetSeconds(avPlayer.currentItem.duration)/60; sceond = CMTimeGetSeconds(avPlayer.currentItem.duration)- 60 * minit; self.endTime.text = [NSString stringWithFormat:@"%02ld:%02ld",(long)minit,sceond]; } }else if ([keyPath isEqualToString:@"currentItem.loadedTimeRanges"]){ NSArray *array = avPlayer.currentItem.loadedTimeRanges; CMTimeRange timeRange = [array.firstObject CMTimeRangeValue]; float startSeconds = CMTimeGetSeconds(timeRange.start); float durationSeconds = CMTimeGetSeconds(timeRange.duration); NSTimeInterval totalBuffer = startSeconds + durationSeconds; self.playableProgress.value = totalBuffer/100; if (!_istouched) { if (self.player.rate==0) { [_actiity startAnimating]; } else{ [_actiity stopAnimating]; } } } } - (void)removeObserverFromPlayerItem:(AVPlayerItem *)playerItem{ [playerItem removeObserver:self forKeyPath:@"currentItem.status"]; [playerItem removeObserver:self forKeyPath:@"currentItem.loadedTimeRanges"]; } - (void)playClick{ if (self.player.rate==1) { self.istouched = YES; [self.player pause]; self.playButton.selected = YES; }else{ [self.backView isHidden]; self.istouched = NO; self.playButton.selected = NO; [self.player play]; } } - (void)fullScreen:(PlayView *)playerView { _playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; // playerLayer.transform = CATransform3DMakeRotation(M_PI_2, 0 , 0, 1); // playerLayer.frame = self.view.bounds; self.transform = CGAffineTransformRotate(self.transform, M_PI_2); self.backView.frame = CGRectMake(0, 0, 667, 414); self.backView.transform = CGAffineTransformRotate(self.backView.transform, M_PI_2); // [[UIApplication sharedApplication].windows.firstObject.layer addSublayer:_playerLayer]; // [[UIApplication sharedApplication].windows.firstObject addSubview:self.backView]; __isSmall = NO; } - (void)normalScreen:(PlayView *)playerView { _playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; // playerLayer.transform = CATransform3DMakeRotation(-M_PI_2, 0 , 0, -1); // playerLayer.frame = self.view.bounds; // self.backView.frame = CGRectMake(0, 450, KScreenWidth, 40); self.backView.transform = CGAffineTransformRotate(self.backView.transform, -M_PI_2); self.transform = CGAffineTransformRotate(self.transform, -M_PI_2); // [[UIApplication sharedApplication].windows.firstObject.layer addSublayer:playerLayer]; // [[UIApplication sharedApplication].windows.firstObject addSubview:self.backView]; __isSmall = YES; } - (void)bigOrSmall{ if (__isSmall) { if ([self.delegate respondsToSelector:@selector(fullScreen:)]) { [self.delegate fullScreen:self]; } } else { if ([self.delegate respondsToSelector:@selector(normalScreen:)]) { [self.delegate normalScreen:self]; } } __isSmall = !__isSmall; } - (void)valueChange:(UISlider *)progress other:(UIEvent *)event{ NSTimeInterval currenttime; UITouch *touch = [[event allTouches] anyObject]; switch (touch.phase) { case UITouchPhaseBegan: NSLog(@"start"); self.isSliding = YES; break; case UITouchPhaseMoved: [_player pause]; currenttime = self.progress.value *CMTimeGetSeconds([self.player.currentItem duration]); self.startTime.text = [self currentTimeToString:currenttime]; NSLog(@"%@", self.startTime.text); break; case UITouchPhaseEnded: self.isSliding = NO; [self play]; NSLog(@"qewrwr"); break; default: break; } } - (void)play{ CMTime dragedCmTime = CMTimeMake(self.progress.value*CMTimeGetSeconds([self.player.currentItem duration]), 1); [self.player seekToTime:dragedCmTime completionHandler:^(BOOL finished) { [self playClick]; }]; } - (NSString *)currentTimeToString:(NSTimeInterval)currentTime{ NSInteger static minit; NSInteger static second; minit = currentTime / 60; second = currentTime - 60 * minit; return [NSString stringWithFormat:@"%02ld:%02ld", (long)minit, (long)second]; } - (void)addNotification{ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem]; } - (void) playEnd:(NSTimeInterval)currentTime{ NSLog(@"播放完成"); } - (void) tap { UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickPhoto)]; self.imageView.userInteractionEnabled = YES; [self.imageView addGestureRecognizer:gesture]; } - (void)clickPhoto{ NSLog(@"43435"); // if (self.player.rate==1) { // self.istouched = YES; // [self.player pause]; // }else{ // self.imageView.hidden = YES; // self.istouched = NO; // [self.player play]; // } // _player = [[AVPlayer alloc] initWithPlayerItem:self.playerItem]; // _playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://baobab.cdn.wandoujia.com/14463059939521445330477778425364388_x264.mp4"]]; // [self addObserverToPlayerItem:_playerItem]; } @end
ViewController.m中的代码
#define KScreenWidth [[UIScreen mainScreen]bounds].size.width #define KScreenHeight [[UIScreen mainScreen]bounds].size.height #define WIDTH [UIScreen mainScreen].bounds.size.width #define HEIGHT [UIScreen mainScreen].bounds.size.height #import "ViewController.h" #import <AVFoundation/AVFoundation.h> #import "PlayView.h" @interface ViewController ()<PlayViewDelegate> @property (nonatomic,strong) NSURL *url; @property (nonatomic,strong) AVPlayer *player; @property (nonatomic,strong) UIView *container; @property (nonatomic,strong) AVPlayerItem *playerItem; @property (nonatomic,strong) UIButton *playButton; @property (nonatomic,strong) UIButton *fullButton; @property (nonatomic,strong) UILabel *startTime; @property (nonatomic,strong) UILabel *endTime; @property (nonatomic,strong) UISlider *progress; @property (nonatomic,strong) UISlider *playableProgress; @property (nonatomic,strong) UISlider *volume; @property (nonatomic,strong) UIView *backView; @property (nonatomic,strong) UIActivityIndicatorView *actiity; @property (nonatomic,assign) BOOL isSliding; @property (nonatomic,assign) BOOL istouched; @property (nonatomic,strong) NSTimer *timer; @property (nonatomic,strong)UIImageView *imageView; @property (nonatomic, assign) CGRect nowFrame;//现在的 @property (nonatomic, assign) CGRect currentFrame2;//滚出的 @property (nonatomic,strong)PlayView *playView; @end @implementation ViewController{ AVPlayerLayer *playerLayer; BOOL _isSmall; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor yellowColor]; self.actiity = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; _actiity.frame = CGRectMake(0, 0, 30, 30); _actiity.center = CGPointMake(KScreenWidth / 2, KScreenHeight / 2); [self.playView addSubview:_actiity]; self.playView = [[PlayView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, HEIGHT / 2.2)]; self.playView.backgroundColor = [UIColor blackColor]; self.playView.urlStr = @"http://baobab.cdn.wandoujia.com/14463059939521445330477778425364388_x264.mp4"; self.playView.delegate = self; [self.view addSubview:self.playView]; } - (void)normalScreen:(PlayView *)playerView { playerView.transform = CGAffineTransformRotate(playerView.transform, M_PI_2); playerView.frame = [UIScreen mainScreen].bounds; NSLog(@"%f",self.backView.frame.size.width); playerView.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; } - (void)fullScreen:(PlayView *)playerView { playerView.transform = CGAffineTransformRotate(playerView.transform, -M_PI_2); playerView.frame = CGRectMake(0, 0, WIDTH, HEIGHT / 2.2); playerView.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end