Commit 7020fea5 cgx

优化白噪音卡顿问题

1 个父辈 7de32c40
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
return; return;
} }
NoisePlayItem *playItem = [[NoisePlayItem alloc] initWithUrl:model.audio_url volume:.5]; NoisePlayItem *playItem = [[NoisePlayItem alloc] initWithUrl:model.audio_url volume:.5];
playItem.isSeamlessLoopPlayback = YES;
cell.playItem = playItem; cell.playItem = playItem;
[[NoisePlayerManager sharedNoisePlayerManager] addNoiseAudioCell:cell]; [[NoisePlayerManager sharedNoisePlayerManager] addNoiseAudioCell:cell];
} else { } else {
......
...@@ -13,10 +13,15 @@ ...@@ -13,10 +13,15 @@
/// 系统播放器 /// 系统播放器
@property (nonatomic, strong) AVPlayer *player; @property (nonatomic, strong) AVPlayer *player;
/// 无缝循环播放辅助播放器 /// 无缝循环播放辅助播放器
@property (nonatomic, strong) AVPlayer *assistPlayer; @property (nonatomic, strong) AVPlayer *loopPlayer;
/// 当前保存的音频播放器
@property (nonatomic, strong) NSMutableArray *allPlayers;
@end @end
@implementation NoisePlayItem @implementation NoisePlayItem {
id _timeObserve;
id _timeLoopObserve;
}
- (instancetype)initWithUrl:(NSString *)url volume:(float)volume { - (instancetype)initWithUrl:(NSString *)url volume:(float)volume {
if (self = [super init]) { if (self = [super init]) {
...@@ -26,33 +31,87 @@ ...@@ -26,33 +31,87 @@
return self; return self;
} }
- (NSArray *)allPlayers {
if (!_allPlayers) {
_allPlayers = [NSMutableArray array];
}
return _allPlayers;
}
- (void)setVolume:(float)volume { - (void)setVolume:(float)volume {
_volume = volume; _volume = volume;
self.player.volume = volume; self.player.volume = volume;
} }
- (void)play { - (void)play {
if (self.isSeamlessLoopPlayback) {
if (self.allPlayers.count == 0) {
if (self.player.timeControlStatus != AVPlayerTimeControlStatusPlaying) {
[self.player play];
}
return;
}
for (AVPlayer *player in self.allPlayers) {
if (player.timeControlStatus != AVPlayerTimeControlStatusPlaying) {
[player play];
}
}
}
if (self.isLoopPlayback) {
if (self.player.timeControlStatus != AVPlayerTimeControlStatusPlaying) { if (self.player.timeControlStatus != AVPlayerTimeControlStatusPlaying) {
[self.player play]; [self.player play];
} }
}
} }
- (void)pause { - (void)pause {
if (self.isSeamlessLoopPlayback) {
for (AVPlayer *player in self.allPlayers) {
if (player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
[player pause];
}
}
}
if (self.isLoopPlayback) {
if (self.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) { if (self.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
[self.player pause]; [self.player pause];
} }
}
} }
- (void)stop { - (void)stop {
if (self.isSeamlessLoopPlayback) {
for (__strong AVPlayer *player in self.allPlayers) {
if (player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
[player pause];
[player seekToTime:CMTimeMake(0, 1)];
if (player == _player) {
[player removeTimeObserver:_timeObserve];
_timeObserve = nil;
_player = nil;
} else if (player == _loopPlayer) {
[_loopPlayer removeTimeObserver:_timeLoopObserve];
_timeLoopObserve = nil;
_loopPlayer = nil;
}
}
}
[self.allPlayers removeAllObjects];
}
if (self.isLoopPlayback) {
if (self.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) { if (self.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
[self.player pause]; [self.player pause];
[self.player seekToTime:CMTimeMake(0, 1)]; [self.player seekToTime:CMTimeMake(0, 1)];
} }
}
} }
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"status"]) { if ([keyPath isEqualToString:@"status"]) {
DSLog(@"changechange:%@", change);
AVPlayerStatus status = [[change objectForKey:@"new"] intValue]; AVPlayerStatus status = [[change objectForKey:@"new"] intValue];
if (status == AVPlayerStatusReadyToPlay) { if (status == AVPlayerStatusReadyToPlay) {
self.isPlaying = YES; self.isPlaying = YES;
...@@ -65,44 +124,119 @@ ...@@ -65,44 +124,119 @@
DSLog(@"AVPlayerStatusUnknown"); DSLog(@"AVPlayerStatusUnknown");
} }
} else if ([keyPath isEqualToString:@"loadedTimeRanges"]) { } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
DSLog(@"change:%@", change); DSLog(@"loadedTimeRanges:%@", change);
} }
} }
- (void)playbackFinished:(NSNotification *)notification { - (void)playbackFinished:(NSNotification *)notification {
DSLog(@"音频播放完成通知:%@", notification.object); DSLog(@"音频播放完成通知%@", notification.object);
AVPlayerItem *playerItem = [notification object]; AVPlayerItem *playerItem = [notification object];
if (self.isSeamlessLoopPlayback) {
if (playerItem == _player.currentItem) {
if ([self.allPlayers containsObject:_player]) {
[self.allPlayers removeObject:_player];
}
[_player removeTimeObserver:_timeObserve];
_timeObserve = nil;
_player = nil;
} else if (playerItem == _loopPlayer.currentItem) {
if ([self.allPlayers containsObject:_loopPlayer]) {
[self.allPlayers removeObject:_loopPlayer];
}
[_loopPlayer removeTimeObserver:_timeLoopObserve];
_timeLoopObserve = nil;
_loopPlayer = nil;
}
}
if (self.isLoopPlayback) {
if (self.isLoopPlayback) {
[playerItem seekToTime:kCMTimeZero completionHandler:nil]; [playerItem seekToTime:kCMTimeZero completionHandler:nil];
[self.player play]; [self.player play];
}
// if ([notification.object isEqualToString:@"major"]) { }
// self.isPlaying = NO;
// AVPlayerItem *playerItem = [notification object];
// [playerItem seekToTime:kCMTimeZero completionHandler:nil];
// if (self.isLoopPlayback) {
// [self.player play];
// }
// if (self.isSeamlessLoopPlayback) {
// [self.assistPlayer play];
// }
// }
} }
- (void)dealloc { - (void)dealloc {
if (_player) {
[_player.currentItem removeObserver:self forKeyPath:@"status" context:nil]; [_player.currentItem removeObserver:self forKeyPath:@"status" context:nil];
[_player.currentItem removeObserver:self forKeyPath:@"loadedTimeRanges" context:nil]; [_player.currentItem removeObserver:self forKeyPath:@"loadedTimeRanges" context:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];
}
if (_loopPlayer) {
[_loopPlayer.currentItem removeObserver:self forKeyPath:@"status" context:nil];
[_loopPlayer.currentItem removeObserver:self forKeyPath:@"loadedTimeRanges" context:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:_loopPlayer.currentItem];
}
} }
#pragma mark - lazy #pragma mark - lazy
- (AVPlayer *)player { - (AVPlayer *)player {
if (!_player) { if (!_player) {
_player = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:self.url]]; _player = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:self.url]];
_player.volume = self.volume;
if (![self.allPlayers containsObject:_player]) {
[self.allPlayers addObject:_player];
}
[_player.currentItem addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew) context:nil]; [_player.currentItem addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew) context:nil];
[_player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:(NSKeyValueObservingOptionNew) context:nil]; [_player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:(NSKeyValueObservingOptionNew) context:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];
WS(weakSelf);
_timeObserve = [_player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 10.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
float current = CMTimeGetSeconds(time);
float total = CMTimeGetSeconds(weakSelf.player.currentItem.duration);
// 即将播放完成后,继续播放该音乐
if (current >= total - .5) {
[weakSelf.loopPlayer play];
}
}];
} }
return _player; return _player;
} }
- (AVPlayer *)loopPlayer {
if (!_loopPlayer) {
_loopPlayer = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:self.url]];
_loopPlayer.volume = self.volume;
if (![self.allPlayers containsObject:_loopPlayer]) {
[self.allPlayers addObject:_loopPlayer];
}
[_loopPlayer.currentItem addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew) context:nil];
[_loopPlayer.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:(NSKeyValueObservingOptionNew) context:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_loopPlayer.currentItem];
WS(weakSelf);
_timeLoopObserve = [_loopPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 10.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
float current = CMTimeGetSeconds(time);
float total = CMTimeGetSeconds(weakSelf.loopPlayer.currentItem.duration);
// 即将播放完成后,继续播放该音乐
if (current >= total - .5) {
[weakSelf.player play];
if (![weakSelf.allPlayers containsObject:weakSelf.player]) {
[weakSelf.allPlayers addObject:weakSelf.player];
}
}
}];
}
return _loopPlayer;
}
#pragma mark - others
- (void)resetMusicPlayer {
if (self.player) {
[self.player removeTimeObserver:_timeObserve];
_timeObserve = nil;
}
self.player = nil;
}
- (void)resetMusicLoopPlayer {
if (self.loopPlayer) {
[self.loopPlayer removeTimeObserver:_timeLoopObserve];
_timeLoopObserve = nil;
}
self.loopPlayer = nil;
}
@end @end
...@@ -16,7 +16,6 @@ SingletonH(NoisePlayerManager) ...@@ -16,7 +16,6 @@ SingletonH(NoisePlayerManager)
/// 播放列表,存放被选中的cell对象 /// 播放列表,存放被选中的cell对象
@property (nonatomic, strong, readonly) NSArray<NoiseAudioCell *> *playCellList; @property (nonatomic, strong, readonly) NSArray<NoiseAudioCell *> *playCellList;
/// 播放状态(所有播放列表中只要有1个在播放则为YES,全部暂停为NO) /// 播放状态(所有播放列表中只要有1个在播放则为YES,全部暂停为NO)
@property (nonatomic, assign) BOOL isPlaying; @property (nonatomic, assign) BOOL isPlaying;
......
...@@ -36,6 +36,7 @@ SingletonM(NoisePlayerManager) ...@@ -36,6 +36,7 @@ SingletonM(NoisePlayerManager)
BOOL isPlaying = NO; BOOL isPlaying = NO;
for (NoiseAudioCell *cell in self.playCellList) { for (NoiseAudioCell *cell in self.playCellList) {
NoisePlayItem *item = cell.playItem; NoisePlayItem *item = cell.playItem;
// 该状态存在不及时
isPlaying = item.isPlaying; isPlaying = item.isPlaying;
[item play]; [item play];
} }
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!