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
//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];
}];
}