1. 程式人生 > >iOS 真正的流音訊秒播 邊緩衝邊播放 DOUAudioStreamer框架

iOS 真正的流音訊秒播 邊緩衝邊播放 DOUAudioStreamer框架

上一篇音訊流播放 使用的是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 = [_streamerbufferingRatio];

}

 /// 播放器銷燬

- (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;

}


demo  地址 http://code.cocoachina.com/view/135275