VideoHelperViewController.m 7.47 KB
Newer Older
1 2 3 4 5 6 7 8 9
//
//  VideoHelperViewController.m
//  Lighting
//
//  Created by 曹云霄 on 2016/11/25.
//  Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//

#import "VideoHelperViewController.h"
10
#import "VIMediaCache.h"
11 12 13 14 15 16 17


@interface VideoHelperViewController ()

@property (nonatomic,strong) AVPlayer *customPlayer;
@property (nonatomic,strong) AVPlayerItem *playerItem;
@property (nonatomic,strong) id avplayerServer;
18
@property (nonatomic,strong) VIResourceLoaderManager *resourceLoaderManager;
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

/**
 导航栏、工具类是否隐藏
 */
@property (nonatomic,assign) BOOL toolNaviViewIsHide;

@end

@implementation VideoHelperViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self uiConfigAction];
    [self setUpAVPlayer];
    [self addAVPlayerKVO];
    [self addProgressObserver];
}

#pragma mark - UI
- (void)uiConfigAction
{
    self.videoNavigationView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
    self.videoToolView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
    [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideOrShowNavigationBarAndToolBar)]];
}

#pragma mark - SetUp AVPlayer
- (void)setUpAVPlayer
{
49 50 51 52 53 54 55 56 57 58 59 60
    VIResourceLoaderManager *resourceLoaderManager = [VIResourceLoaderManager new];
    self.resourceLoaderManager = resourceLoaderManager;
    self.playerItem = [resourceLoaderManager playerItemWithURL:[NSURL URLWithString:self.videoUrl]];
    VICacheConfiguration *configuration = [VICacheManager cacheConfigurationForURL:[NSURL URLWithString:self.videoUrl]];
    if (configuration.progress >= 1.0) {
        NSLog(@"缓存完成");
    }
    self.customPlayer = [[AVPlayer alloc] initWithPlayerItem:_playerItem];
    self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:_customPlayer];
    self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    self.playerLayer.frame = CGRectMake(0, 0, ScreenWidth*2/3, ScreenHeight/2);
    [self.view.layer insertSublayer:self.playerLayer atIndex:0];
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    [self CreateMBProgressHUDLoding];
    //设置静音模式播放声音
    AVAudioSession * session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    [session setActive:YES error:nil];
}

#pragma mark - AVPlayer KVO
- (void)addAVPlayerKVO
{
    //播放状态属性
    [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    //监控网络加载情况属性
    [self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
    //给AVPlayerItem添加播放完成通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinish) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
}

#pragma mark -KVO回调
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if ([keyPath isEqualToString:@"status"]) {//播放状态
        NSInteger status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        switch (status) {
            case AVPlayerStatusFailed:
                [self ErrorMBProgressView:@"播放失败"];
                break;
            case AVPlayerStatusReadyToPlay://正在播放
                [self RemoveMBProgressHUDLoding];
                self.playItemTotalTimeLabel.text = [NSString stringWithFormat:@"/ %@",[self convertTime:CMTimeGetSeconds(self.playerItem.duration)]];
                break;
            default:
                break;
        }
    }else if ([keyPath isEqualToString:@"loadedTimeRanges"]){//缓冲
        NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度
        if (timeInterval > self.getCurrentPlayingTime+5){ // 缓存 大于 播放 当前时长+5
            [self.customPlayer play];
        }
    }
}

#pragma mark - 返回当前视频播放时长
- (double)getCurrentPlayingTime{
    return self.customPlayer.currentTime.value/self.customPlayer.currentTime.timescale;
}

#pragma mark - 返回当前视频缓存时长
- (NSTimeInterval)availableDuration{
    NSArray *loadedTimeRanges = [[self.customPlayer currentItem] loadedTimeRanges];
    CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域
    float startSeconds = CMTimeGetSeconds(timeRange.start);
    float durationSeconds = CMTimeGetSeconds(timeRange.duration);
    NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度
    return result;
}

#pragma mark -播放进度条更新
-(void)addProgressObserver {
    
    WS(weakSelf);
    AVPlayerItem *playerItem = self.customPlayer.currentItem;
    self.avplayerServer = [self.customPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time){
        float current = CMTimeGetSeconds(time);
        float total = CMTimeGetSeconds(playerItem.duration);
        //更新进度条
        float progress = current/total;
        weakSelf.bufferProgressView.progress = progress;
        //更新播放时间
        CMTime ctime = weakSelf.customPlayer.currentTime;
        weakSelf.playingTimeLabel.text = [weakSelf convertTime:ctime.value/ctime.timescale];
    }];
}

#pragma mark - 隐藏(显示)状态栏、工具栏
- (void)hideOrShowNavigationBarAndToolBar
{
    WS(weakSelf);
    [UIView animateWithDuration:0.4 animations:^{
        weakSelf.videoNavigationView.alpha = weakSelf.toolNaviViewIsHide?1:0;
        weakSelf.videoToolView.alpha = weakSelf.toolNaviViewIsHide?1:0;
        
    }completion:^(BOOL finished) {
        weakSelf.toolNaviViewIsHide = !weakSelf.toolNaviViewIsHide;
    }];
}

#pragma mark -计算时间
- (NSString *)convertTime:(CGFloat)second
{
    NSDate *date = [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:date];
    return showtimeNew;
}

#pragma mark - 播放完成
- (void)playFinish
{
    [self.customPlayer seekToTime:kCMTimeZero];
    self.playButton.selected = YES;
}

#pragma mark - 播放、暂停
- (IBAction)playOrPauseButtonClickAction:(UIButton *)sender {
    
    sender.selected = !sender.selected;
    if (sender.selected) {
        [self.customPlayer pause];
    }else {
        [self.customPlayer play];
    }
}

#pragma mark - 退出播放
- (IBAction)exitPlayControllerButtonClick:(UIButton *)sender {
    [self.customPlayer pause];
    [self.navigationController popViewControllerAnimated:YES];
}

#pragma mark - 后退5秒
- (IBAction)backFiveSecondButtnClick:(UIButton *)sender {
    
    [self.customPlayer seekToTime:CMTimeMake(5, 1)];
}

#pragma mark - 放大缩小按钮
- (IBAction)zoomButtonClick:(UIButton *)sender {
    
    sender.selected = !sender.selected;
    if (self.zoomButtonClickBlock) {
        self.zoomButtonClickBlock(sender.selected);
    }
}

200 201 202 203 204 205 206 207
#pragma mark - 页面消失后释放播放器
- (void)viewDidDisappear:(BOOL)animated
{
    [self.customPlayer pause];
    [self.customPlayer.currentItem cancelPendingSeeks];
    [self.customPlayer.currentItem.asset cancelLoading];
}

208 209 210 211 212 213 214 215 216 217
#pragma mark - 释放KVO
- (void)dealloc
{
    [self.playerItem removeObserver:self forKeyPath:@"status"];
    [self.playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
    [self.customPlayer removeTimeObserver:self.avplayerServer];
}


@end