AVPlayer中的问题

AVPlayer的播放功能封装

在.h中写方法的声明

- (void)playWithString:(NSString *)musicUrlStr durationBlock:(void(^)(CMTime duration))durationBlock currentBlock:(void(^)(CMTime cuttentTime))currentBlock;

注:

durationBlock:回调播放器播放总时长

currentBlock:回调播放器当前播放时长

 

在.m中写方法的实现

@property(nonatomic, strong)AVPlayer *player;

//Block属性, 能在.m中全局使用

@property(nonatomic, copy)void(^durationBlock)(CMTime duration);

 

- (void)playWithString:(NSString *)musicUrlStr durationBlock:(void(^)(CMTime duration))durationBlock currentBlock:(void(^)(CMTime cuttentTime))currentBlock{

    //如果不存在player, 第一次时会创建

    if (!_player) {

        //AVPlayer 既可以播放远程的, 也可以播放本地的

        //既可以播放视频, 也可以播放音频

        //如果播放视频, 需要创建显示层 AVPlayerLayer

        self.player = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:musicUrlStr]];

        //播放

        [_player play];

        //总时长, CMTime 是结构体类型

        //属性接收局部变量, 能在全局使用

        self.durationBlock = durationBlock;

        //KVO 检测播放器播放总时长

        [self.player addObserver:self forKeyPath:@"currentItem.duration" options:NSKeyValueObservingOptionNew context:nil];

        //当前时长 self.player.currentTime 不能用KVO检测  

       //Not key-value observable; use -addPeriodicTimeObserverForInterval:queue:usingBlock: instead.

        CMTime time = CMTimeMake(1, 1);//每1秒, 显示一次

        [self.player addPeriodicTimeObserverForInterval:time queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) usingBlock:^(CMTime time) {

            //回调当前时长

            //在主线程内完成回调

            dispatch_async(dispatch_get_main_queue(), ^{

                currentBlock(time);

            });

        }];

        //监听播放结束

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];

    }else{

        //已经存在player, 替换播放 Item

        AVPlayerItem *item = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:musicUrlStr]];

        [self.player replaceCurrentItemWithPlayerItem:item];

        [self.player play];

        self.durationBlock = durationBlock;

    }

}

 

 

//KVO 触发方法

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{

//self.player.currentItem.duration 返回的是nan, 表示无穷大, 是因为timescale为0

//如果是nan, 不回调

    if (self.player.currentItem.duration.timescale != 0) {

        self.durationBlock(self.player.currentItem.duration);

    }

}

 

注:CMTimeGetSeconds(self.player.currentItem.duration) 能直接得到总时间的秒数, 等价于

self.player.currentItem.duration.value / self.player.currentItem.duration.timescale

 

让播放器在某个时间点开始播放的方法:

声明:

- (void)seekToTime:(float)percent;//在指定的时间点播放, 用于slide滑动

 

实现:

- (void)seekToTime:(float)percent{

    CMTime time = CMTimeMake(percent * CMTimeGetSeconds(self.player.currentItem.duration), 1);

    [self pause];

    [self.player seekToTime:time completionHandler:^(BOOL finished) {

        [self.player play];

    }];

}

posted @ 2016-01-18 21:53  星空梦之蓝  阅读(936)  评论(0编辑  收藏  举报