AVPlayer自定义视频播放器

我的avplayer播放器,能横屏,竖屏,适应屏幕,上代码

1.我把我的那个最主要的类的.m的主要的代码附上

@implementation LDZMoviePlayerController


- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blackColor];
    self.topProgressSlider.value = 0.0;
    [self addGestureRecognizer];
    //  添加观察者
    [self addNotificationCenters];
    [self addAVPlayer];
}

- (void)addAVPlayer{
    playItem = [AVPlayerItem playerItemWithURL: self.movieURL];
    self.playerHelper = [[LDZAVPlayerHelper alloc] init];
    [_playerHelper initAVPlayerWithAVPlayerItem:playItem];
    //  创建显示层
    self.playerLayer = [AVPlayerLayer playerLayerWithPlayer: _playerHelper.getAVPlayer];
    _playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
    //  竖屏的时候frame
    [self setVerticalFrame];
    //  这是视频的填充模式, 默认为AVLayerVideoGravityResizeAspect
    _playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    //  插入到view层上面, 没有用addSubLayer
    [self.view.layer insertSublayer:_playerLayer atIndex:0];
    //  添加进度观察
    [self addProgressObserver];
    [self addObserverToPlayerItem: playItem];
}
//  播放页面添加轻拍手势
- (void)addGestureRecognizer {
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissAllSubViews:)];
    tap.delegate = self;
    [self.view addGestureRecognizer:tap];
}
#pragma mark - 观察者 观察播放完毕 观察屏幕旋转
- (void)addNotificationCenters {
    //  注册观察者用来观察,是否播放完毕
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
    //  注册观察者来观察屏幕的旋转
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}
#pragma mark - 横屏 竖屏的时候frame的设置
- (void)statusBarOrientationChange:(NSNotification *)notification {
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (orientation == UIInterfaceOrientationLandscapeRight) {
        [self setPlayerLayerFrame];
        self.isFirstRotatorTap = YES;
        [self setTopRightBottomFrame];
    }
    if (orientation == UIInterfaceOrientationLandscapeLeft) {
        [self setPlayerLayerFrame];
        self.isFirstRotatorTap = YES;
        [self setTopRightBottomFrame];
    }
    if (orientation == UIInterfaceOrientationPortrait) {
        //  竖屏的时候
        [self setVerticalFrame];
        self.isFirstRotatorTap = YES;
        [self setTopRightBottomFrame];
    }
}
//  横屏的时候frame
- (void)setPlayerLayerFrame {
    CGRect frame = self.view.bounds;
    frame.origin.x = 20;
    frame.origin.y = (SCREEN_HEIGHT - SCREEN_HEIGHT * (SCREEN_WIDTH - 40) / SCREEN_WIDTH) / 2;
    frame.size.width = SCREEN_WIDTH - 40;
    frame.size.height = SCREEN_HEIGHT * (SCREEN_WIDTH - 40) / SCREEN_WIDTH;
    _playerLayer.frame = frame;
}
//  竖屏的时候frame
- (void)setVerticalFrame {
    CGRect frame = self.view.bounds;
    frame.origin.x = ZERO;
    frame.origin.y = (SCREEN_HEIGHT - SCREEN_WIDTH * (SCREEN_WIDTH / SCREEN_HEIGHT)) / 2;
    frame.size.width = SCREEN_WIDTH;
    frame.size.height = SCREEN_WIDTH * (SCREEN_WIDTH / SCREEN_HEIGHT);
    _playerLayer.frame = frame;
}

//  动画(出现或隐藏top - right - bottom)
- (void)dismissAllSubViews:(UITapGestureRecognizer *)tap {
    [self setTopRightBottomFrame];
}
//  设置TopRightBottomFrame
- (void)setTopRightBottomFrame {
    __weak typeof (self) myself = self;
    if (!self.isFirstRotatorTap) {
        [UIView animateWithDuration:.2f animations:^{
            myself.topView.frame = CGRectMake(myself.topView.frame.origin.x, -TOPVIEW_HEIGHT, myself.topView.frame.size.width, myself.topView.frame.size.height);
            myself.rightView.frame = CGRectMake(SCREEN_WIDTH, myself.rightView.frame.origin.y, myself.rightView.frame.size.width, myself.rightView.frame.size.height);
            myself.verticalBottomView.frame = CGRectMake(myself.verticalBottomView.frame.origin.x, SCREEN_HEIGHT, myself.verticalBottomView.frame.size.width, myself.verticalBottomView.frame.size.height);
            myself.ratotarBottomView.frame = CGRectMake(myself.ratotarBottomView.frame.origin.x, SCREEN_HEIGHT, myself.ratotarBottomView.frame.size.width, myself.ratotarBottomView.frame.size.height);
        }];
        self.isFirstRotatorTap = YES;
    } else {
        [UIView animateWithDuration:.2f animations:^{
            myself.topView.frame = CGRectMake(myself.topView.frame.origin.x, ZERO, myself.topView.frame.size.width, myself.topView.frame.size.height);
            myself.rightView.frame = CGRectMake(SCREEN_WIDTH - RIGHT_WIDTH, myself.rightView.frame.origin.y, myself.rightView.frame.size.width, myself.rightView.frame.size.height);
            myself.verticalBottomView.frame = CGRectMake(myself.verticalBottomView.frame.origin.x, SCREEN_HEIGHT - VERTICAL_BOTTOM_HEIGHT, myself.verticalBottomView.frame.size.width, myself.verticalBottomView.frame.size.height);
            myself.ratotarBottomView.frame = CGRectMake(myself.ratotarBottomView.frame.origin.x, SCREEN_HEIGHT - ROTATOR_BOTTOM_HEIGHT, myself.ratotarBottomView.frame.size.width, myself.ratotarBottomView.frame.size.height);
        }];
        self.isFirstRotatorTap = NO;
    }
}
//  显示top,right,bottom的View
- (void)setTopRightBottomViewHiddenToShow {
    _topView.hidden = NO;
    _rightView.hidden = NO;
    _ratotarBottomView.hidden = NO;
    _verticalBottomView.hidden = NO;
    _isFirstRotatorTap = NO;
}
//  隐藏top,right,bottom的View
- (void)setTopRightBottomViewShowToHidden {
    _topView.hidden = YES;
    _rightView.hidden = YES;
    _ratotarBottomView.hidden = YES;
    _verticalBottomView.hidden = YES;
    _isFirstRotatorTap = YES;
}
#pragma mark - 暂停
- (void)setMovieParse {
    [_playerHelper.getAVPlayer pause];
    isPlay = NO;
    //  因为用的是xib,不设置的话图片会重合
    _verticalPlayButton.imageView.image = nil;
    _rotatorPlayButton.imageView.image = nil;
    [_verticalPlayButton setImage:[UIImage imageNamed:@"播放器_播放"] forState: UIControlStateNormal];
    [_rotatorPlayButton setImage:[UIImage imageNamed:@"播放器_播放"] forState:UIControlStateNormal];
}
#pragma mark - 播放
- (void)setMoviePlay {
    [_playerHelper.getAVPlayer play];
    isPlay = YES;
    //  因为用的是xib,不设置的话图片会重合
    _verticalPlayButton.imageView.image = nil;
    _rotatorPlayButton.imageView.image = nil;
    [_verticalPlayButton setImage:[UIImage imageNamed:@"播放器_暂停"] forState: UIControlStateNormal];
    [_rotatorPlayButton setImage:[UIImage imageNamed:@"播放器_暂停"] forState:UIControlStateNormal];
}

#pragma mark -  添加进度观察 - addProgressObserver
- (void)addProgressObserver {
    //  设置每秒执行一次
    [_playerHelper.getAVPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue: NULL usingBlock:^(CMTime time) {
NSLog(@"进度观察 + %f", _topProgressSlider.value);
        //  获取当前时间
        CMTime currentTime = _playerHelper.getAVPlayer.currentItem.currentTime;
        //  转化成秒数
        CGFloat currentPlayTime = (CGFloat)currentTime.value / currentTime.timescale;
        //  总时间
        CMTime totalTime = playItem.duration;
        //  转化成秒
        _totalMovieDuration = (CGFloat)totalTime.value / totalTime.timescale;
        //  相减后
        _topProgressSlider.value = CMTimeGetSeconds(currentTime) / _totalMovieDuration;
        progressSlider = CMTimeGetSeconds(currentTime) / _totalMovieDuration;
NSLog(@"%f", _topProgressSlider.value);
        NSDate *pastDate = [NSDate dateWithTimeIntervalSince1970: currentPlayTime];
         _topPastTimeLabel.text = [self getTimeByDate:pastDate byProgress: currentPlayTime];
        CGFloat remainderTime = _totalMovieDuration - currentPlayTime;
        NSDate *remainderDate = [NSDate dateWithTimeIntervalSince1970: remainderTime];
        _topRemainderLabel.text = [self getTimeByDate:remainderDate byProgress: remainderTime];
        if (_isFirstRotatorTap) {
            [self setTopRightBottomViewShowToHidden];
        } else {
            [self setTopRightBottomViewHiddenToShow];
        }
    }];
    //  设置topProgressSlider图片
    UIImage *thumbImage = [UIImage imageNamed:@"slider-metal-handle.png"];
    [self.topProgressSlider setThumbImage:thumbImage forState:UIControlStateHighlighted];
    [self.topProgressSlider setThumbImage:thumbImage forState:UIControlStateNormal];
}

- (NSString *)getTimeByDate:(NSDate *)date byProgress:(float)current {
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    if (current / 3600 >= 1) {
        [formatter setDateFormat:@"HH:mm:ss"];
    } else {
        [formatter setDateFormat:@"mm:ss"];
    }
    return [formatter stringFromDate:date];
}

- (void)addObserverToPlayerItem:(AVPlayerItem *)playerItem {
    [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)removeObserverFromPlayerItem:(AVPlayerItem *)playerItem {
    [playerItem removeObserver:self forKeyPath:@"status"];
    [playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
}

//  观察者的方法, 会在加载好后触发, 可以在这个方法中, 保存总文件的大小, 用于后面的进度的实现
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    AVPlayerItem *playerItem = (AVPlayerItem *)object;
    if ([keyPath isEqualToString:@"status"]) {
        AVPlayerStatus status = [[change objectForKey:@"new"] intValue];
        if (status == AVPlayerStatusReadyToPlay) {
            NSLog(@"正在播放...,视频总长度: %.2f",CMTimeGetSeconds(playerItem.duration));
            CMTime totalTime = playerItem.duration;
            self.totalMovieDuration = (CGFloat)totalTime.value / totalTime.timescale;
        }
    }
    if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
        NSArray *array = playerItem.loadedTimeRanges;
        //  本次缓冲时间范围
        CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];
        float startSeconds = CMTimeGetSeconds(timeRange.start);
        float durationSeconds = CMTimeGetSeconds(timeRange.duration);
        //  缓冲总长度
        NSTimeInterval totalBuffer = startSeconds + durationSeconds;
//        NSLog(@"共缓冲%.2f", totalBuffer);
        NSLog(@"进度 + %f", progressSlider);
        self.topProgressSlider.value = progressSlider;
    }
}

#pragma mark - UIGestureRecognizerDelegate Method 方法
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    //  不让子视图响应点击事件
    if( CGRectContainsPoint(self.topView.frame, [gestureRecognizer locationInView:self.view]) || CGRectContainsPoint(self.rightView.frame, [gestureRecognizer locationInView:self.view]) || CGRectContainsPoint(self.ratotarBottomView.frame, [gestureRecognizer locationInView:self.view]) || CGRectContainsPoint(self.verticalBottomView.frame, [gestureRecognizer locationInView:self.view])) {
        return NO;
    } else{
        return YES;
    };
}

#pragma mark - 播放进度
- (IBAction)topSliderValueChangedAction:(id)sender {
    UISlider *test = (UISlider *)sender;
    NSLog(@"进度条进度 + %f", test.value);
    UISlider *senderSlider = sender;
    double currentTime = floor(_totalMovieDuration * senderSlider.value);
    //转换成CMTime才能给player来控制播放进度
    CMTime dragedCMTime = CMTimeMake(currentTime, 1);
    [_playerHelper.getAVPlayer seekToTime:dragedCMTime completionHandler:^(BOOL finished) {
        if (_isPlayOrParse) {
            [_playerHelper.getAVPlayer play];
        }
    }];
}

- (IBAction)topSliderTouchDownAction:(id)sender {
}

- (IBAction)topSliderTouchUpInsideAction:(id)sender {
}

#pragma mark - 播放上一个
- (IBAction)rotatorUpAction:(id)sender {
    NSLog(@"上一个~~~");
}

#pragma mark - 播放...
- (IBAction)rotatorPlayAction:(UIButton *)sender {
    if (isPlay) {
        [self setMovieParse];
    } else {
        [self setMoviePlay];
    }
}

#pragma mark - 播放下一个...
- (IBAction)rotatorNextAction:(UIButton *)sender {
    NSLog(@"下一个~~~");
}

#pragma mark - 返回按钮...
- (IBAction)finishAction:(UIButton *)sender {
    NSLog(@"完成~~~");
}

#pragma mark 播放结束后的代理回调
- (void)moviePlayDidEnd:(NSNotification *)notify
{
    //  LettopRightBottomViewShow
    [self setTopRightBottomViewHiddenToShow];
    [self setMovieParse];
    //  让这个视频循环播放...
}

#pragma mark - 音量slider
- (IBAction)bottomSoundSliderAction:(UISlider *)sender {
    //  0 - 1
    [_playerHelper setAVPlayerVolume:sender.value];
    
    self.rotatorBottomSlider.value = sender.value;
    self.verticalBottomSlider.value = sender.value;
    if (sender.value == 0) {
        self.rotatorSoundImageView.image = [UIImage imageNamed:@"播放器_静音"];
        self.verticalSoundImageView.image = [UIImage imageNamed:@"播放器_静音"];
    } else {
        self.rotatorSoundImageView.image = [UIImage imageNamed:@"播放器_音量"];
        self.verticalSoundImageView.image = [UIImage imageNamed:@"播放器_音量"];
    }
}

#pragma mark -  分享 - 收藏 - 缓存
- (IBAction)rightShareButton:(UIButton *)sender {
    NSLog(@"分享~~~");
}

- (IBAction)rightCollectButton:(UIButton *)sender {
    NSLog(@"收藏~~~");
}

- (IBAction)rightCacheButton:(UIButton *)sender {
    NSLog(@"缓存~~~");
}

- (void)dealloc {
    //  移除观察者,使用观察者模式的时候,记得在不使用的时候,进行移除
    [self removeObserverFromPlayerItem: _playerHelper.getAVPlayer.currentItem];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
    //  返回前一个页面的时候释放内存
    [self.playerHelper.getAVPlayer replaceCurrentItemWithPlayerItem:nil];
}

2.到此说完啦,为了写这个玩意,我写了一周啊.

3.实现了横屏,竖屏,快进,快退,暂停等功能

源码地址:http://download.csdn.net/detail/fengchenlangzi_/9354939


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值