ios 音频流媒体播放
项目中用到播放网络音频,最开始想到的就是AVPlayer,但是播放很慢,需要等到加载完成才会播放。
于是,领导让改成流媒体模式,那什么是流式播放呢?即:边缓存边播放
直接上代码
一、导入 pod 'FreeStreamer'
二、引入头文件
#import <AVFoundation/AVFoundation.h>
#import <FSAudioStream.h>
#import <MediaPlayer/MPNowPlayingInfoCenter.h>
#import <MediaPlayer/MPMediaItem.h>
#import <MediaPlayer/MPRemoteCommandCenter.h>
#import <MediaPlayer/MPRemoteCommand.h>
#import <MediaPlayer/MPRemoteCommandEvent.h>
三、创建播放器
// 网络文件
if(!_audioStream) {
// 创建FSAudioStream对象
_audioStream= [[FSAudioStreamalloc]initWithUrl:url];
_audioStream.onFailure= ^(FSAudioStreamErrorerror,NSString*description){
NSLog(@"播放过程中发生错误,错误信息:%@",description);
// [weakSelf showAlertMsg:description];
};
_audioStream.onCompletion=^(){
[weakSelfautoPlayNext];
};
[_audioStream preload];
[_audioStreamplay];
}
else
{
if(!self.audioStream.isPlaying) {
[_timersetFireDate:[NSDatedistantFuture]];// 计时器暂停
[_audioStreamstop];
[_audioStreamplayFromURL:url];
}
else
{
_audioStream.url= url;
[_audioStreampreload];
[_audioStreamplay];
}
}
// self.sliderView.nowTimeLabel.text = @"--:--";
// self.sliderView.totalTimeLabel.text = @"--:--";
if(!self.timer) {
//进度条
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(playerProgress) userInfo:nil repeats:YES];
}
else
{
[self.timer setFireDate:[NSDate distantPast]];// 计时器开始
}
四、进度条
//进度控制
- (void)playerProgress
{
FSStreamPosition position = self.audioStream.currentTimePlayed;
self.playTime = round(position.playbackTimeInSeconds);//四舍五入整数值
doubleminutes =floor(fmod(self.playTime/60.0,60.0));//返回不大于()中的最大整数值
doubleseconds =floor(fmod(self.playTime,60.0));
self.beginTimeLabel.text= [NSStringstringWithFormat:@"%02.0f:%02.0f",minutes, seconds];
if(seconds >0) {
self.loadL.hidden=YES;
[self.dict setObject:@"true" forKey:@"loadHidden"];
}
self.progressSlider.value = position.position;//播放进度
self.totalTime = position.playbackTimeInSeconds/position.position;
NSLog(@"播放进度:%ld,%ld,%@",(long)self.playTime,(long)self.totalTime,[NSNumbernumberWithInteger:self.totalTime]);
//判断分母为空时的情况
if ([[NSString stringWithFormat:@"%f",position.position] isEqualToString:@"0.000000"]) {
self.beginTimeLabel.text=@"--:--";
self.endTimeLabel.text=@"--:--";
if (![[NSNumber numberWithInteger:self.totalTime] isEqualToNumber:[NSNumber numberWithInt:0]]
&& [NSNumber numberWithInteger:self.playTime] == [NSNumber numberWithInteger:self.totalTime]) {
if([self.delegaterespondsToSelector:@selector(PlayMusicFinish:)]){
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate PlayMusicFinish:self.playBtnTag];
});
}
[self.playBBtn setImage:[UIImage imageNamed:@"stopIcon"] forState:UIControlStateNormal];
}
}
else
{
doubleminutes2 =floor(fmod(self.totalTime/60.0,60.0));
doubleseconds2 =floor(fmod(self.totalTime,60.0));
self.endTimeLabel.text= [NSStringstringWithFormat:@"%02.0f:%02.0f",minutes2, seconds2];
}
}
播放
- (void)play
{
// [self.player play];
self.layer.beginTime = 0.0;
CFTimeIntervalpausedTime = [self.layertimeOffset];
CFTimeIntervaltimeSincePause = [self.layerconvertTime:CACurrentMediaTime()fromLayer:nil] - pausedTime;
self.layer.beginTime= timeSincePause;
[self.timer setFireDate:[NSDate distantPast]];// 计时器开始
[self.audioStream pause];
[_audioStream play];
}
暂停
- (void)pause
{
CFTimeInterval pausedTime = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
self.layer.timeOffset= pausedTime;
[self.audioStream pause];
[self.timer setFireDate:[NSDate distantFuture]];// 计时器暂停
}
#pragma mark- 进度条状态改变
- (void)sliderTouchDown:(UISlider*)slider{
_isSliderTouch = YES;
}
- (void)sliderValueChange:(UISlider *)slider{
if(slider.value>0)
{
//初始化一个FSStreamPosition结构体
FSStreamPosition pos;
//只对position赋值
pos.position= slider.value;
[self.audioStream seekToPosition:pos];// 到指定位置播放
}
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.03* NSEC_PER_SEC)); dispatch_after(delayTime, dispatch_get_main_queue(), ^{
//不延迟执行会造成slider瞬间回弹
self->_isSliderTouch=NO;
});
}
销毁播放器
-(void)deallocAvplayer{
NSLog(@"销毁音频播放器");
[self.playBBtn setImage:[UIImage imageNamed:@"stopIcon"] forState:UIControlStateNormal];
[_audioStream stop];
_audioStream =nil;
[_timer invalidate];
_timer=nil;
}