上一篇音频流播放 使用的是freestreamer 框架 后来又研究了一下DOUAudioStreamer 整理如下 仅供参考
安装
pod 'DOUAudioStreamer','~> 0.2.15'
1.创建一对 track 文件继承于 NSObject
track.h
#import <Foundation/Foundation.h>
#import <DOUAudioFile.h>
@interface Track :NSObject<DOUAudioFile>
@property (nonatomic,strong)NSURL *audioFileURL;
@end
track.m#import "Track.h"
@implementation Track
@end
2. 创建播放器控制器 添加播放暂停,,上一曲,下一曲,进度提示,,缓冲提示,,当前时间提示,,总时间提示控件,,
进度提示使用uislider 可滑动选择播放位置,,缓存提示使用UIprogressView,,(
相关设置 ,,uislider覆盖在UIprogressView上面并设置为透明色
self.progress = [[UIProgressViewalloc]init];
[self.viewaddSubview:self.progress];
self.progress.tintColor = [UIColorcyanColor];
[self.progressmas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.nowTimeLabel.mas_right).offset(0);
make.centerY.mas_equalTo(self.nowTimeLabel.mas_centerY);
make.height.mas_equalTo(2);
make.width.mas_equalTo([UIScreenmainScreen].bounds.size.width - 140);
}];
self.slider = [[UISlideralloc]init];
[self.viewaddSubview:self.slider];
self.slider.tintColor = [UIColorredColor];
self.slider.maximumTrackTintColor = [UIColorclearColor];
[self.slidersetThumbImage:[UIImageimageNamed:@"球足球沙滩球-4"]forState:UIControlStateNormal];
self.slider.continuous =YES;
[self.slideraddTarget:selfaction:@selector(_actionSliderProgress:)forControlEvents:UIControlEventValueChanged];
[self.slideraddTarget:selfaction:@selector(durationSliderTouchEnded:)forControlEvents:UIControlEventTouchUpInside];
[self.slidermas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.nowTimeLabel.mas_right).offset(0);
make.top.mas_equalTo(self.progress.mas_top).offset(-10);
make.height.mas_equalTo(20); // 这个数值不能设置太小 高度代表可滑动范围 太小的话划不动的
make.width.mas_equalTo([UIScreenmainScreen].bounds.size.width - 140);
}];
/// 其余控件省略了)
- (void)viewDidLoad {
[superviewDidLoad];
self.view.backgroundColor = [UIColorwhiteColor];
[selfcreateView]; // 创建控件 省略
[selfloadData];
// 音频进度计时器
self.timer = [NSTimerscheduledTimerWithTimeInterval:1target:selfselector:@selector(_timerAction:)userInfo:nilrepeats:YES];
}
- (void)loadData{
self.titleLabel.text = self.songDic[@"title"];
self.nameLabel.text = self.songDic[@"nicName"];
NSURL *imageurl = [NSURLURLWithString:[NSStringstringWithFormat:@"%@%@",URLADDRESS,self.songDic[@"cover"]]];
[self.bigImageViewsd_setImageWithURL:imageurlplaceholderImage:[UIImageimageNamed:@""]];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSString *InPutUrl = [NSStringstringWithFormat:@"%@/audio/getAudioByIdentifier2/%@/0",URLADDRESS,self.songDic[@"identifier"]];
// 耗时的操作
[FMAFNetWorkingToolgetUrl:InPutUrlbody:nilresult:FMJSONheaderFile:nilsuccess:^(id result) {
self.audioTrack = [[Trackalloc]init];
// 获取音频播放地址
self.audioTrack.audioFileURL = [NSURLURLWithString:result[@"body"][@"ios_url_b"]];
// 创建播放器
[selfcreatePlayer];
/// 向前加载一条 向后加载一条 实现上下一曲 按需求更改
[selfloadMoreVideo:result[@"body"][@"id"]];
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
});
} failure:^(NSError *error) {
}];
});
}
- (void)createPlayer{
//// 如果要实现全局播放的播放器,,可以把播放器的创建使用单利创建。。。
self.streamer = [DOUAudioStreamerstreamerWithAudioFile:self.audioTrack];
[self.streameraddObserver:selfforKeyPath:@"status"options:NSKeyValueObservingOptionNewcontext:kStatusKVOKey];
[self.streameraddObserver:selfforKeyPath:@"duration"options:NSKeyValueObservingOptionNewcontext:kDurationKVOKey];
[self.streameraddObserver:selfforKeyPath:@"bufferingRatio"options:NSKeyValueObservingOptionNewcontext:kBufferingRatioKVOKey];
[self.streamerplay];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if (context ==kStatusKVOKey) {
[selfperformSelector:@selector(_updateStatus)
onThread:[NSThreadmainThread]
withObject:nil
waitUntilDone:NO];
}elseif (context ==kDurationKVOKey) {
[selfperformSelector:@selector(_timerAction:)
onThread:[NSThreadmainThread]
withObject:nil
waitUntilDone:NO];
}elseif (context ==kBufferingRatioKVOKey) {
}else {
[superobserveValueForKeyPath:keyPathofObject:objectchange:changecontext:context];
}
}
- (void)_updateStatus{
switch ([_streamerstatus]) {
caseDOUAudioStreamerPlaying:
[self.playButtonsetImage:[UIImageimageNamed:@"暂停"]forState:UIControlStateNormal];
break;
caseDOUAudioStreamerPaused:
[self.playButtonsetImage:[UIImageimageNamed:@"播放-3"]forState:UIControlStateNormal];
break;
caseDOUAudioStreamerIdle:
break;
caseDOUAudioStreamerFinished:
/// 当前音频播放完成,,播放下一个音频
[selfnextButtonAction];
break;
caseDOUAudioStreamerBuffering:
break;
caseDOUAudioStreamerError:
break;
}
}
//// 计时器 显示 播放进度 时间
- (void)_timerAction:(id)timer{
if ([_streamerduration] ==0.0) {
[self.slidersetValue:0.0fanimated:NO];
self.nowTimeLabel.text =@"00:00";
}else {
/// 播放进度条 self.sliding bool值 在滑动进度调试设置为yes 暂时停止进度条赋值。。
if (self.sliding ==YES) {
}else{ // 滑动结束后正常赋值
[self.slidersetValue:[_streamercurrentTime] / [_streamerduration]animated:YES];
}
//// 当前播放时间
double minutesElapsed =floor(fmod([_streamercurrentTime]/60.0,60.0));
double secondsElapsed =floor(fmod([_streamercurrentTime],60.0));
self.nowTimeLabel.text = [NSStringstringWithFormat:@"%02.0f:%02.0f",minutesElapsed, secondsElapsed];
/// 音频总时长
double minutesElapsedtotal =floor(fmod([_streamerduration]/60.0,60.0));
double secondsElapsedtotal =floor(fmod([_streamerduration],60.0));
self.totalTimeLabel.text = [NSStringstringWithFormat:@"%02.0f:%02.0f",minutesElapsedtotal, secondsElapsedtotal];
}
/// 缓冲进度
self.progress.progress = [_streamer bufferingRatio];
}
/// 播放器销毁
- (void)_cancelStreamer{
if (_streamer !=nil) {
[_streamerpause];
[_streamerremoveObserver:selfforKeyPath:@"status"];
[_streamerremoveObserver:selfforKeyPath:@"duration"];
[_streamerremoveObserver:selfforKeyPath:@"bufferingRatio"];
_streamer =nil;
}
}
// 此为进度条开始滑动的方法 ,,具体在uislider 创建的时候添加
- (void)_actionSliderProgress:(id)sender{
self.sliding =YES;
}
// 此为进度条滑动结束的方法 ,,具体在uislider 创建的时候添加
- (void)durationSliderTouchEnded:(UISlider *)slider{
/// 延时0.5秒 再给进度条赋值,,防止滑动进度条结束时会产生回弹。。
[selfperformSelector:@selector(reloadprogressValue)withObject:selfafterDelay:0.5];
/// 跳到指定时间播放
[_streamersetCurrentTime:[_streamerduration] * [slider value]];
}
- (void)reloadprogressValue{
self.sliding = NO;
}
- (void)lastButtonAction{
[self_cancelStreamer];
// 实现上一曲方法 创建播放器 添加URL 播放
}
- (void)nextButtonAction{
[self_cancelStreamer];
// 实现下一曲方法 创建播放器 添加URL 播放
}
/// 播放 暂停按钮点击方法
- (void)playButtonAction{
if ([_streamerstatus] == DOUAudioStreamerPaused ||
[_streamerstatus] ==DOUAudioStreamerIdle) {
[_streamerplay];
[self.playButtonsetImage:[UIImageimageNamed:@"暂停"]forState:UIControlStateNormal];
[self.timersetFireDate:[NSDatedistantPast]];
}else {
[_streamerpause];
[self.playButtonsetImage:[UIImageimageNamed:@"播放-3"]forState:UIControlStateNormal];
[self.timersetFireDate:[NSDatedistantFuture]];
}
}
/// 返回按钮 销毁计时器和播放器
- (void)backaction{
[_timerinvalidate];
_timer =nil;
[self_cancelStreamer];
[selfdismissViewControllerAnimated:YEScompletion:^{
}];
}
#pragma mark 解决slider小范围滑动不能触发的问题
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if([gestureRecognizerlocationInView:gestureRecognizer.view].y >=self.slider.frame.origin.y && !self.slider.hidden)
returnNO;
returnYES;
}