AVPlayer 无间隔循环播放

使用AVPlayer进行音频播放时,为达到无间隔的单曲循环效果,通过在歌曲即将结束时预加载下一首并调整音量,确保无缝衔接。监听播放状态并在播放结束后销毁并重建播放器,以消除播放间隙。同时,要注意销毁播放器时移除观察者以避免问题。
摘要由CSDN通过智能技术生成

AVPlayer 可以实现音频或者视频文件的在线播放和本地播放。最近做了一个单曲循环播放的功能。一开始选择了下面这个方法:

- (void)replaceCurrentItemWithPlayerItem:(nullable AVPlayerItem *)item;

但尝试后发现两首音乐无法完美衔接,中间会有一个短暂的停留,这个不太符合我们的需求。尝试在播放完后,重新创建播放器,继续播放这首音乐。但还是会有停留。

随后采用了一个折中的方案,在音乐播放即将完成的时候,重新创建一个新的播放器,开始播放。第一个播放器播放完成后就销毁掉。当第二个播放器即将播放完成的时候,在初始化第一个播放器,记录开始播放,以此循环。这样,用一段重合的音乐代替了一段暂停。

我们需要监听音乐播放:

id _timeObserve;
id _timeLoopObserve;

监听第一个播放器的播放情况:

@weakify(self)
        _timeObserve = [self.musicPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
            @strongify(self)
            float current = CMTimeGetSeconds(time);
            float total = CMTimeGetSeconds(self.currentPlayerItem.duration);
            //即将播放完成后,继续播放该音乐
            if (current >= total-5 && current < total && !self.musicPlayerSwitch) {
                self.musicPlayer.volume = 0.8;
                [self resetMusicLoopPlayer];
                [self initMusicLoopPlayer];
                self.musicLoopPlayer.volume = 0.8;
                [self.musicLoopPlayer play];
                self.musicPlayerSwitch = YES;
              }
            }else{
                if (current > 6 && current < total-6) {
                    self.musicPlayerSwitch = NO;
                    [self resetMusicPlayer];
                    self.musicLoopPlayer.volume = 1;
                }
            }
        }];

监听第二个播放器的播放情况:

@weakify(self)
        _timeLoopObserve = [self.musicLoopPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
            @strongify(self)
            float current = CMTimeGetSeconds(time);
            float total = CMTimeGetSeconds(self.currentPlayerItem.duration);
            //即将播放完成后,继续播放该音乐
            if (current >= total-5 && current < total && !self.musicPlayerSwitch) {
                self.musicPlayer.volume = 0.8;
                [self resetMusicPlayer];
                [self initMusicPlayer];
                self.musicPlayer.volume = 0.8;
                [self.musicPlayer play];
                self.musicPlayerSwitch = YES;
              }
            }else{
                if (current > 6 && current < total-6) {
                    self.musicPlayerSwitch = NO;
                    [self resetMusicLoopPlayer];
                    self.musicPlayer.volume = 1;
                }
            }
        }];

如上代码,在两段音乐重叠的时候,为了防止声音突然变大,通过设置 volume 降低声音。在其中一个播放器销毁的时候再恢复原声。

另外,销毁播放器的时候注意要把观察者移除:

- (void)resetMusicPlayer{
    if (self.musicPlayer) {
        [self.musicPlayer removeTimeObserver:_timeObserve];
        _timeObserve = nil;
    }
    self.musicPlayer  = nil;
}
- (void)resetMusicLoopPlayer{
    if (self.musicLoopPlayer) {
        [self.musicLoopPlayer removeTimeObserver:_timeLoopObserve];
        _timeLoopObserve = nil;
    }
    self.musicLoopPlayer  = nil;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值