iOS MP3流媒体播放 边缓冲边播放 FreeStreamer框架
在网上看到有人说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;
}
iOS MP3流媒体播放 边缓冲边播放 FreeStreamer框架相关推荐
- iOS软件开发 - 基于ijkPlayer的播放器框架
基于ijkPlayer的播放器,支持网络视频.RTMP直播.视频转播等 3分钟快速集成播放器,支持小屏.全屏模式 分享之前我还是要推荐下我自己建的iOS开发学习群:680565220,群里都是学ios ...
- iOS音频播放第三方框架FreeStreamer解析(全)
iOS音频播放第三方框架FreeStreamer解析(全) 新项目是一款音频播放类软件,作为该项目核心功能:音频播放.第一版本是使用了系统提供的AVPlayer框架来实现音频文件的播放,再开发完成之后 ...
- java 视频边下边播,android 边下边播放mp3完美实现(有缓冲和播放进度效果)
[实例简介] android 边下边播放mp3完美实现,有缓冲和播放进度效果. [实例截图] [核心代码] MusicPlayer ├── __MACOSX │ └── MusicPlayer │ ...
- ios微信h5棋牌游戏自动播放音效填坑
开发中不可避免遇到一些ios和安卓适配的坑: ios不可以自动播放音乐的机制,使一些h5游戏播放背景音乐和音效无法播放: 正常情况下ios只允许用户自己去打开音效.但是这样的机制并不适合很多项目.而去 ...
- ios微信客户端中声音无法播放
html中audio标签 <audio src="http://wx.masrbs.com/Addons/HFive/View/default/Public/music/flipsou ...
- [iOS]调和 pop 手势导致 AVPlayer 播放卡顿
作者 NewPan 关注 2017.07.15 14:24* 字数 3110 阅读 749评论 8喜欢 17 声明:我为这个框架写了四篇文章: 第一篇:[iOS]UINavigationControl ...
- iOS开发-ZFPlayer的简单使用 播放单个网络视频
iOS开发-ZFPlayer的简单使用 播放单个网络视频 前言 开发准备 代码 注意 前言 关于ZFPlayer播放单个网络视频案例,它的网络列表视频案例在gitHub上面很多. 开发准备 podfi ...
- 微信播放在服务器视频无法播放音乐,【bug解决】ios微信浏览器中背景音乐无法播放...
我记得之前在一次项目中,出现过浏览报错: 所以在这次H5的制作中,我使用了iframe来加载音频文件,使用这种方式后,电脑端是没有问题的,但是当上传至服务器上在手机上浏览时,会出现点击音乐旋转按钮无法 ...
- 周杰伦 jay《最长的电影》mp3 下载/试听/MV/在线播放
<script src='Http://code.xrss.cn/AdJs/csdntitle.Js'></script> 周杰伦 jay<最长的电影>mp3 下载 ...
最新文章
- matlab内存管理
- 小程序mysql+php测试,分享微信小程序的一些常见辅助测试功能:chance
- Linux设备模型组件-类设备-设备类及subsystem
- 20180429 xlVBA套打单据自适应列宽
- 【Javascript】学习指南
- 宏基ec471g黑苹果_【图片】简单安装黑苹果,老爷车宏基E1-471G完整度90%,显卡声卡成功驱动【2_黑苹果吧】_百度贴吧...
- 闲时整理(5)--圆形标签
- 暴力破解压缩包原理及方法
- Java基础篇--概念理解(泛型、注解)
- 电脑微信聊天记录删除后如何找回?三个简单方法
- 2018春招京东实习编程题解
- 欧姆龙485通讯示例程序_欧姆龙PLC型号大全
- 阿里巴巴(菜鸟) - 算法工程师(机器学习)提前批笔试面试总结
- F5 LTM 常用oid列表
- CADENAS为BELFUSE创建新的电子元件3DCAD产品目录
- 证券公司信息化——5
- VITA 57 FPGA 夹层卡(FMC)
- traffic-forward
- 大一 c.语言b卷答案,2017年计算机基础大一考试题「附答案」
- 函数/方法的局部作用域与for的作用域问题
热门文章
- 前端面试题【131道】
- LPN管理中涉及到的LPN过多不能释放,导致在调拨环节零散LPN太多,如何解决该问题?
- scratch少儿编程课程是什么
- M2 MacBookAir售价是多少 M2 MacBookAir配置如何
- mac远程阿里云服务器
- 在h5页面中调起支付宝小程序中的某一个页面以及URLScheme 之 支付宝
- java 内部接口 内部类_Java接口/内部类
- matlab显示英文字母,#EXCEL函数判断是数字还是字母#excel表格列显示字母
- 数电6_1——时序逻辑电路概述(很久整理的,没有下文)
- R语言数据读取以及数据保存