在网上看到有人说AVplay就可以播放流媒体,便拿过来使用,,结果发现无论如何它都是要把MP3缓存完成之后才开始播放,,音频长的就要等好久,对于M4A 格式的还有好些,MP3就不行了,,这样体验非常差。于是在网上搜罗方法,,找到了FreeStreamer 库 可以实现边缓存边播放MP3文件,,网上资料比较少。。在这里大致做下总结。。我的代码写的并不好 只是给需要的做个参考  支持mp3和m4a格式 后面还有一篇DOUAudioStreamer 的总结 可以参考下

1.使用cocoapods 添加FreeStreamer库

pod 'FreeStreamer','~> 3.7.2'

2.

#import <FSAudioStream.h>

- (void)viewWillAppear:(BOOL)animated{

[superviewWillAppear:animated];

// 开始接受远程控制 为添加到音频中心后台播放做准备

[[UIApplicationsharedApplication]beginReceivingRemoteControlEvents];

[selfbecomeFirstResponder];

}

- (void)viewWillDisappear:(BOOL)animated{

[superviewWillDisappear:animated];

// 结束远程控制 为添加到音频中心后台播放做准备

[[UIApplicationsharedApplication]endReceivingRemoteControlEvents];

[selfresignFirstResponder];

}

// 重写父类成为响应者方法 为添加到音频中心后台播放做准备

- (BOOL)canBecomeFirstResponder {

returnYES;

}

#pragma mark 重写父类方法,接受外部事件的处理 为添加到音频中心后台播放做准备

- (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent {

if (receivedEvent.type ==UIEventTypeRemoteControl) {

switch (receivedEvent.subtype) {//得到事件类型

caseUIEventSubtypeRemoteControlTogglePlayPause://暂停 ios6

self.play =YES;//调用你所在项目的暂停按钮的响应方法下面的也是如此

[selfplayAction];

break;

caseUIEventSubtypeRemoteControlPreviousTrack: //上一首

[selflastButtonAction];

break;

caseUIEventSubtypeRemoteControlNextTrack://下一首

[selfnextButtonAction];

break;

caseUIEventSubtypeRemoteControlPlay://播放

self.play =NO;//调用你所在项目的暂停按钮的响应方法下面的也是如此

[selfplayAction];

break;

caseUIEventSubtypeRemoteControlPause://暂停 ios7

self.play =YES;//调用你所在项目的暂停按钮的响应方法下面的也是如此

[selfplayAction];

break;

default:

break;

}

}

}

//Now Playing Center可以在锁屏界面展示音乐的信息,也达到增强用户体验的作用。

#pragma mark 传递信息到锁屏状态下此方法在播放歌曲与切换歌曲时调用即可

- (void)configNowPlayingCenter:(YiPinXiangXiBody *)body {

NSMutableDictionary * info = [NSMutableDictionarydictionary];

//音乐的标题

[info setObject:body.titleforKey:MPMediaItemPropertyTitle];

//音乐的艺术家

[info setObject:body.columnNameforKey:MPMediaItemPropertyArtist];

//音乐的封面

UIImage *image = [[UIImagealloc]initWithData:[NSDatadataWithContentsOfURL:[NSURLURLWithString:  [NSStringstringWithFormat:@"%@%@",URLADDRESS,body.cover]]]];

MPMediaItemArtwork * artwork = [[MPMediaItemArtworkalloc]initWithImage:image];

[info setObject:artworkforKey:MPMediaItemPropertyArtwork];

//完成设置

[[MPNowPlayingInfoCenterdefaultCenter]setNowPlayingInfo:info];

// NSLog(@"----%lld--------%f------",self.player.currentTime.value,self.totalTime);

}

#pragma mark 初始化播放器

- (void)playerInit:(NSURL *)url{

if (!_audioStream) {

// 创建FSAudioStream对象

_audioStream=[[FSAudioStreamalloc]init];

// 设置声音

[_audioStreamsetVolume:1];

}

_audioStream.url = url;

[_audioStream play];

_audioStream.onFailure=^(FSAudioStreamError error,NSString *description){

NSLog(@"播放出现问题%@",description);

};

__weaktypeof(self) weakSelf =self;

_audioStream.onCompletion=^(){

[weakSelf nextButtonAction];// 播放完成后继续播放下一个

};

// 计时器 获取播放进度和缓存进度

self.playerTimer = [NSTimerscheduledTimerWithTimeInterval:1target:selfselector:@selector(playProgressAction)userInfo:nilrepeats:YES];

// 将视频信息添加到Playing Center 锁屏显示播放信息 控制播放暂停

[selfconfigNowPlayingCenter:self.yiPinXiangXi.body];

}

#pragma mark 音频缓存和播放进度提示

- (void)playProgressAction{

FSStreamPosition cur =self.audioStream.currentTimePlayed;

self.playbackTime =cur.playbackTimeInSeconds/1;

double minutesElapsed =floor(fmod(self.playbackTime/60.0,60.0));

double secondsElapsed =floor(fmod(self.playbackTime,60.0));

self.nowTimeLabel.text = [NSStringstringWithFormat:@"%02.0f:%02.0f",minutesElapsed, secondsElapsed];

self.sliderProgress.value = cur.position;//播放进度

// 获取视频的总时长

self.totalTime =self.playbackTime/cur.position;

NSLog(@"-=-=-=-=-=%f",self.totalTime);

if ([[NSStringstringWithFormat:@"%f",self.totalTime]isEqualToString:@"nan"]) {

self.totalTimeLabel.text =@"00:00";

}else{

double minutesElapsed1 =floor(fmod(self.totalTime/60.0,60.0));

double secondsElapsed1 =floor(fmod(self.totalTime,60.0));

self.totalTimeLabel.text = [NSStringstringWithFormat:@"%02.0f:%02.0f",minutesElapsed1, secondsElapsed1];

}

float  prebuffer = (float)self.audioStream.prebufferedByteCount;

float contentlength = (float)self.audioStream.contentLength;

if (contentlength>0) {

self.playerProgress.progress = prebuffer /contentlength;//缓存进度

}

/// 更新airPlay后台和锁屏播放进度====================

NSMutableDictionary *dict = [NSMutableDictionarydictionaryWithDictionary:[[MPNowPlayingInfoCenterdefaultCenter]nowPlayingInfo]];

[dict setObject:@(self.playbackTime)forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];

//音乐的总时间

[dict setObject:@(self.totalTime)forKey:MPMediaItemPropertyPlaybackDuration];

[[MPNowPlayingInfoCenterdefaultCenter] setNowPlayingInfo:dict];

}

#pragma mark 播放暂停按钮=================

- (void)playAction{

//先将未到时间执行前的任务取消 防止变态点击导致崩溃

[[selfclass]cancelPreviousPerformRequestsWithTarget:selfselector:@selector(theplayAction)object:nil];

[selfperformSelector:@selector(theplayAction)withObject:nilafterDelay:0.2f];// 0.2不可改

}

- (void)theplayAction{

if (self.play ==YES) {// 如果正在播放 则暂停

[self.audioStreampause];

[self.playerTimersetFireDate:[NSDatedistantFuture]];// 计时器暂停

[_playButtonsetImage:[UIImageimageNamed:@"bofang"]forState:UIControlStateNormal];// 按钮换状态

}else{

[self.audioStreampause];// 如果是暂停,则播放。。这里并不是使用[self.audioStream play];不信你可以试试...不知道为什么会这样

[self.playTimersetFireDate:[NSDatedistantPast]];

[self.playerTimersetFireDate:[NSDatedistantPast]];

[_playButtonsetImage:[UIImageimageNamed:@"audioPause"]forState:UIControlStateNormal];

}

self.play = !self.play;

}

#pragma mark 拖动进度条到指定位置播放,重新添加播放进度。 事先创建好进度条添加滑动方法

- (void)durationSliderTouchEnded:(UISlider *)slider{

[selfslidertoPlay:slider.value];

}

#pragma mark 滑动进度条跳到指定位置,播放状态

- (void)slidertoPlay:(CGFloat)time{

if (time ==1) {// 当滑动到头的时候自动播放下一曲。。

[selfnextButtonAction];

}elseif (time >=0) {

FSStreamPosition pos = {0};

pos.position = time;

[self.audioStreamseekToPosition:pos];// 到指定位置播放

}

}

#pragma mark 上一曲按钮点击方法

- (void)lastButtonAction{

//先将未到时间执行前的任务取消 防止变态点击

[[selfclass]cancelPreviousPerformRequestsWithTarget:selfselector:@selector(theLastButtonAction)object:nil];

[selfperformSelector:@selector(theLastButtonAction)withObject:nilafterDelay:0.2f];// 0.2不可改

}

- (void)theLastButtonAction{ // 我这边上一曲下一曲是通过网络获取 根据具体情况进行更改

if (self.lastIdentifier ==nil) {

}else{

[self.playTimersetFireDate:[NSDatedistantFuture]];

self.playerProgress.progress =0.0;

self.play =YES;

self.sliding =NO;

[selfplayerItemDealloc];// 播放器销毁

self.identifier =self.lastIdentifier;

[selfaddData]; // 获取到上一曲后,,创建播放器

}

}

#pragma mark 下一曲按钮点击方法

- (void)nextButtonAction{

//先将未到时间执行前的任务取消

[[selfclass]cancelPreviousPerformRequestsWithTarget:selfselector:@selector(thenextButtonAction)object:nil];

[selfperformSelector:@selector(thenextButtonAction)withObject:nilafterDelay:0.2f];// 0.2不可改

}

- (void)thenextButtonAction{

if (self.nextIdentifier ==nil) {

}else{

[self.playTimersetFireDate:[NSDatedistantFuture]];

self.playerProgress.progress =0.0;

self.play =YES;

self.sliding =NO;

[selfplayerItemDealloc];

self.identifier =self.nextIdentifier;

[selfaddData];

}

}

#pragma mark 销毁播放器,,清除缓存的音频(freestreamer 会自动下载音频,可以不清除,,但可能文件越来越大,,我这里不保留,,基本是缓冲一点点马上可以播放,,离线的话就播不了了)

- (void)playerItemDealloc{

NSArray *arr = [[NSFileManagerdefaultManager]contentsOfDirectoryAtPath:_audioStream.configuration.cacheDirectoryerror:nil];

for (NSString *filein arr) {

if ([filehasPrefix:@"FSCache-"]) {

NSString *path = [NSStringstringWithFormat:@"%@/%@",_audioStream.configuration.cacheDirectory, file];

[[NSFileManagerdefaultManager]removeItemAtPath:patherror:nil];

}

}

[_audioStreamstop];

_audioStream =nil;

[_playerTimerinvalidate];

_playerTimer =nil;

}

#pragma mark 解决slider小范围滑动不能触发的问题(也曾困扰很久的问题)

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{

if([gestureRecognizerlocationInView:gestureRecognizer.view].y >=_sliderProgress.frame.origin.y && !_sliderProgress.hidden)

returnNO;

returnYES;

}

// 系统自带API解析MP3时长

- (CGFloat)getMusicTime:(NSURL *)url{

AVURLAsset *avURLAsset = [[AVURLAssetalloc]initWithURL:urloptions:nil];

// 获取音频总时长

CGFloat time = avURLAsset.duration.value / avURLAsset.duration.timescale;

return time;

}

https://github.com/muhku/FreeStreamer

iOS MP3流媒体播放 边缓冲边播放 FreeStreamer框架相关推荐

  1. iOS软件开发 - 基于ijkPlayer的播放器框架

    基于ijkPlayer的播放器,支持网络视频.RTMP直播.视频转播等 3分钟快速集成播放器,支持小屏.全屏模式 分享之前我还是要推荐下我自己建的iOS开发学习群:680565220,群里都是学ios ...

  2. iOS音频播放第三方框架FreeStreamer解析(全)

    iOS音频播放第三方框架FreeStreamer解析(全) 新项目是一款音频播放类软件,作为该项目核心功能:音频播放.第一版本是使用了系统提供的AVPlayer框架来实现音频文件的播放,再开发完成之后 ...

  3. java 视频边下边播,android 边下边播放mp3完美实现(有缓冲和播放进度效果)

    [实例简介] android 边下边播放mp3完美实现,有缓冲和播放进度效果. [实例截图] [核心代码] MusicPlayer ├── __MACOSX │   └── MusicPlayer │ ...

  4. ios微信h5棋牌游戏自动播放音效填坑

    开发中不可避免遇到一些ios和安卓适配的坑: ios不可以自动播放音乐的机制,使一些h5游戏播放背景音乐和音效无法播放: 正常情况下ios只允许用户自己去打开音效.但是这样的机制并不适合很多项目.而去 ...

  5. ios微信客户端中声音无法播放

    html中audio标签 <audio src="http://wx.masrbs.com/Addons/HFive/View/default/Public/music/flipsou ...

  6. [iOS]调和 pop 手势导致 AVPlayer 播放卡顿

    作者 NewPan 关注 2017.07.15 14:24* 字数 3110 阅读 749评论 8喜欢 17 声明:我为这个框架写了四篇文章: 第一篇:[iOS]UINavigationControl ...

  7. iOS开发-ZFPlayer的简单使用 播放单个网络视频

    iOS开发-ZFPlayer的简单使用 播放单个网络视频 前言 开发准备 代码 注意 前言 关于ZFPlayer播放单个网络视频案例,它的网络列表视频案例在gitHub上面很多. 开发准备 podfi ...

  8. 微信播放在服务器视频无法播放音乐,【bug解决】ios微信浏览器中背景音乐无法播放...

    我记得之前在一次项目中,出现过浏览报错: 所以在这次H5的制作中,我使用了iframe来加载音频文件,使用这种方式后,电脑端是没有问题的,但是当上传至服务器上在手机上浏览时,会出现点击音乐旋转按钮无法 ...

  9. 周杰伦 jay《最长的电影》mp3 下载/试听/MV/在线播放

    <script src='Http://code.xrss.cn/AdJs/csdntitle.Js'></script> 周杰伦 jay<最长的电影>mp3 下载 ...

最新文章

  1. matlab内存管理
  2. 小程序mysql+php测试,分享微信小程序的一些常见辅助测试功能:chance
  3. Linux设备模型组件-类设备-设备类及subsystem
  4. 20180429 xlVBA套打单据自适应列宽
  5. 【Javascript】学习指南
  6. 宏基ec471g黑苹果_【图片】简单安装黑苹果,老爷车宏基E1-471G完整度90%,显卡声卡成功驱动【2_黑苹果吧】_百度贴吧...
  7. 闲时整理(5)--圆形标签
  8. 暴力破解压缩包原理及方法
  9. Java基础篇--概念理解(泛型、注解)
  10. 电脑微信聊天记录删除后如何找回?三个简单方法
  11. 2018春招京东实习编程题解
  12. 欧姆龙485通讯示例程序_欧姆龙PLC型号大全
  13. 阿里巴巴(菜鸟) - 算法工程师(机器学习)提前批笔试面试总结
  14. F5 LTM 常用oid列表
  15. CADENAS为BELFUSE创建新的电子元件3DCAD产品目录
  16. 证券公司信息化——5
  17. VITA 57 FPGA 夹层卡(FMC)
  18. traffic-forward
  19. 大一 c.语言b卷答案,2017年计算机基础大一考试题「附答案」
  20. 函数/方法的局部作用域与for的作用域问题

热门文章

  1. 前端面试题【131道】
  2. LPN管理中涉及到的LPN过多不能释放,导致在调拨环节零散LPN太多,如何解决该问题?
  3. scratch少儿编程课程是什么
  4. M2 MacBookAir售价是多少 M2 MacBookAir配置如何
  5. mac远程阿里云服务器
  6. 在h5页面中调起支付宝小程序中的某一个页面以及URLScheme 之 支付宝
  7. java 内部接口 内部类_Java接口/内部类
  8. matlab显示英文字母,#EXCEL函数判断是数字还是字母#excel表格列显示字母
  9. 数电6_1——时序逻辑电路概述(很久整理的,没有下文)
  10. R语言数据读取以及数据保存