iOS从零开始学习直播之音频4.歌词
2016-12-06 10:42
288 查看
上一篇讲了歌曲的切换,这一篇主要讲歌词部分的实现。
先看效果图。当歌手唱到这句歌词时候,我们要标记出来,这里显示字体为黄色。
![](https://images2015.cnblogs.com/blog/872567/201612/872567-20161206104015397-436168906.png)
![](https://images2015.cnblogs.com/blog/872567/201612/872567-20161206104037460-1095495636.png)
我用FHLrcModel管理每句歌词。
FHLrcModel.h
FHLrcModel.m
备注: 主要看更新歌词部分,其他可以略过。
这样就可以把当前演唱的歌词实时标记出来了,还可以随着演唱往上滑动。这个一定有其他的方法,大家可以和我探讨,只有交流才能知道自己的不足,才能不断进步。项目地址GitUp ,欢迎下载。
先看效果图。当歌手唱到这句歌词时候,我们要标记出来,这里显示字体为黄色。
![](https://images2015.cnblogs.com/blog/872567/201612/872567-20161206104015397-436168906.png)
1.获取歌词
一般歌词都是一个链接。类似于“http://musicdata.baidu.com/data2/lrc/131707548/131707548.lrc” ,我们从服务器下载下来,显示到页面上。每句歌词后面都有“\n”,前面都有时间。这个链接有可能直接下载,看不到下面的效果。换个浏览器多试几次就可以了,尽量使用谷歌浏览器。![](https://images2015.cnblogs.com/blog/872567/201612/872567-20161206104037460-1095495636.png)
#pragma mark - 获取歌词 - (void)getAlbumLrc { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 异步并发下载歌曲 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:_currentModel.lrclink]]; // 二进制转为字符串 NSString *allLrcStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; // 分割字符串 NSArray *lrcArray = [allLrcStr componentsSeparatedByString:@"\n"]; // 添加到数组中 [self.lrcArr removeAllObjects]; for (NSString *lrc in lrcArray) { FHLrcModel *lrcModel = [FHLrcModel allocLrcModelWithLrc:lrc]; [self.lrcArr addObject:lrcModel]; } // 主线程更新UI dispatch_async(dispatch_get_main_queue(), ^{ [_lrcTableView reloadData]; }); }); }
我用FHLrcModel管理每句歌词。
FHLrcModel.h
#import <Foundation/Foundation.h> @interface FHLrcModel : NSObject @property (nonatomic, copy) NSString *lrc; // 歌词 @property (nonatomic, assign) int presenTime; //显示这句歌词的时间 @property (nonatomic, assign) bool isPresent; // 当前显示的是否是这句歌词 // 实例化方法 + (instancetype)allocLrcModelWithLrc: (NSString *)lrc; @end
FHLrcModel.m
#import "FHLrcModel.h" @implementation FHLrcModel + (instancetype)allocLrcModelWithLrc: (NSString *)lrc { FHLrcModel *model =[FHLrcModel new]; // 把歌词和时间分割开 NSArray *array = [lrc componentsSeparatedByString:@"]"]; // 处理时间 [00:01.70] =》 1.70 NSString *timeStr; if ([array[0] length] >8) { timeStr = [array[0] substringWithRange:NSMakeRange(1, 8)]; } NSArray *timeArr = [timeStr componentsSeparatedByString:@":"]; if (timeArr.count > 1) { model.presenTime = (int)[timeArr[0] floatValue] * 60 + [timeArr[1] intValue]; } // 如果没有歌词 就换行 if (array.count > 1) { model.lrc = array[1]; }else { model.lrc = @"\n"; } return model; } @end
2.显示歌词
显示歌词显然用UITableView了,这个很简单。实例化UITableView的方法我就不贴出来了,我只贴它的代理部分的代码。#pragma mark - UITableView - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.lrcArr.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [_lrcTableView dequeueReusableCellWithIdentifier:@"LrcCell" forIndexPath:indexPath]; // 去掉点击效果 cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.backgroundColor = [UIColor clearColor]; FHLrcModel *lrcmodel = self.lrcArr[indexPath.row]; cell.textLabel.text = lrcmodel.lrc; cell.textLabel.textAlignment = NSTextAlignmentCenter; if (lrcmodel.isPresent) { // 当前歌词显示黄色 cell.textLabel.textColor = [UIColor yellowColor]; }else { cell.textLabel.textColor = [UIColor whiteColor]; } return cell; }
3.同步歌词
这部分挺有难度。我走了很多弯路。后来我想了一个办法,当前播放时间和歌词数组里的第一个元素去比较,比较成功了,再去比较第二个元素。这样就避免了用for循环每一次都比较全部,这样节省内存和时间。这样做是因为我发现了歌词的时间从上往下是不断增加的,没有歌词复用的情况。至于怎么监听播放进度可以看我前面的播放。#pragma mark - 添加监听播放进度的观察者 - (void)addTimePlayProgerssObserver { __block UISlider *weakPregressSlider = _playerSlider; __weak UILabel *waekCurrentLabel = _currentLabel; __block int weakRow = _row;// 来记录当前歌词显示到第几行 __weak typeof(self) weakSelf = self; self.timePlayProgerssObserver = [self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { // 当前播放的时间 float current = CMTimeGetSeconds(time); // ***更新歌词*** if (weakRow < weakSelf.lrcArr.count) { FHLrcModel *model = weakSelf.lrcArr[weakRow]; // 比较时间 比较成功了刷新TabelView if (model.presenTime == (int)current) { [weakSelf reloadTabelViewWithRow:weakRow]; weakRow++; } } // 总时间 float total = CMTimeGetSeconds(weakSelf.avPlayer.currentItem.duration); // 更改当前播放时间 NSString *currentSStr = [weakSelf FormatTime: (int)current % 60]; waekCurrentLabel.text = [NSString stringWithFormat:@"%d:%@",(int)current / 60,currentSStr]; // 更新播放进度条 weakPregressSlider.value = current / total; }]; }
备注: 主要看更新歌词部分,其他可以略过。
#pragma mark - 更新歌词 - (void)reloadTabelViewWithRow:(int)row { // 找到cell NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0]; UITableViewCell *cell = [_lrcTableView cellForRowAtIndexPath:indexPath]; // 字体变色 cell.textLabel.textColor = [UIColor yellowColor]; // 当前歌词滑动到TableView中间 [_lrcTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; // 上一句变为白色 如果是第一句就没有上一句,所以不操作 if (row > 0) { UITableViewCell *preCell = [_lrcTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:row - 1 inSection:0]]; preCell.textLabel.textColor = [UIColor whiteColor]; } }
这样就可以把当前演唱的歌词实时标记出来了,还可以随着演唱往上滑动。这个一定有其他的方法,大家可以和我探讨,只有交流才能知道自己的不足,才能不断进步。项目地址GitUp ,欢迎下载。
相关文章推荐
- iOS从零开始学习直播之音频2.后台播放和在线播放
- iOS从零开始学习直播之音频1.播放本地音频文件
- iOS从零开始学习直播之音频1.播放本地音频文件
- iOS从零开始学习直播之音频2.后台播放和在线播放
- iOS从零开始学习直播之音频3.歌曲切换
- iOS从零开始学习直播之3.美颜
- iOS从零开始学习直播之1.播放
- iOS从零开始学习直播之2.采集
- iOS音频学习笔记一:常见音频封装格式及编码格式
- 第二章、Objective-C中的@property、@synthesize和dynamic的用法(iOS学习笔记,从零开始)
- 第二章、小实例,画字,画线,矩形,画图,动画(iOS学习笔记,从零开始。)
- iOS音频播放学习(2)
- 三 :ios学习笔记 音频 视频
- iOS学习,音频,本地选歌,播放
- iOS音频播放学习(4)
- IOS学习笔记 -- 音频视频
- iOS基础学习(5)------音频(一)AudioservicesPlaySystemSound和AVAudioPlayer的使用
- iOS音频学习笔记三:音频会话管理
- iOS音频学习笔记二:iOS SDK中与音频有关的相关框架
- 第三章、一些基本数据结构使用和解析(iOS学习笔记,从零开始。)