前言
最近做專案,遇到了需要播放網路音訊的功能,由於以前對於音訊方面的至少了解的不是很多,於是通過查閱資料對音訊方面做了一些學習,然後利用VLCKit仿照網易雲音樂的播放介面寫了個Demo,在此記錄一下,大神勿噴。
關於VLCKit,它是一款功能強大的全平臺播放器,幾乎支援所有格式的音訊、視訊檔案的播放
整合方式
1、 按照wiki的說明去自己編譯:[wiki.videolan.org/iOSCompile]
2、cocoapods方式
通過pos search MobileVLCKit去搜尋相關的庫,會發現有好幾個庫,我最終選擇了MobileVLCKit-unstable(因為這個庫更新的多,而且還在不時的更新)
pod 'MobileVLCKit-unstable', '~> 3.0.0a42'複製程式碼
說明
本Demo主要實現的有以下功能:
* 播放網路音訊、歌曲
* 唱片(播放時旋轉、左右滑動切換歌曲)
* 歌詞滾動、音量控制、歌曲切換
* 設定迴圈型別、上一曲、下一曲、喜歡歌曲等
* 鎖屏控制(播放、暫停、喜歡、上一曲、下一曲、播放條拖動)
* 耳機線控(播放、暫停、上一曲、下一曲、快進、快退)
* 通知監聽(插拔耳機、播放打斷)
* 支援AirPlay複製程式碼
不足:
* 不能獲取緩衝進度(播放庫的問題)
* 不支援本地快取(每次播放都需要網路請求)複製程式碼
demo中的音樂資料來自百度音樂,僅供學習使用,請勿在商業中使用
實現
1、播放
demo中對VLCKit實現了二次封裝GKPlayer,主要實現的有播放、暫停、停止,以及播放狀態、進度、時間等的回撥,這裡就不貼程式碼了,具體可到Demo中檢視GKPlayer。
2、轉盤
歌曲播放是需要實現轉盤無限旋轉的效果,這裡用到了CADisplayLink定時器不斷的重新整理,然後通過設定檢視的transform來實現
首先建立CADisplayLink
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animation)];
// 加入到主迴圈中
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];複製程式碼
監聽方法中改變檢視的transform
self.diskView.transform = CGAffineTransformRotate(self.diskView.transform, M_PI_4 / 100);複製程式碼
這樣就做到了檢視的無限旋轉,而且側滑返回的時候也不會停止,下面看看效果圖
轉盤左右滑動切換歌曲也比較簡單,用到了UIScrollView,然後再上面放了三個轉盤檢視,通過監聽UIScrollView的滾動來切換歌曲,看看效果圖吧。
3、歌詞
對於歌詞首先當然是解析歌詞了,通過換行符\n來分離每行的歌詞,然後再通過正規表示式,分離歌詞的時間與內容。
/**
解析歌詞方法
@param lyricString 歌詞對應的字串
@param isDelBlank 是否去掉空白行歌詞
@return 歌詞解析後的模型陣列
*/
+ (NSArray *)lyricParaseWithLyricString:(NSString *)lyricString isDelBlank:(BOOL)isDelBlank {
// 1. 以\n分割歌詞
NSArray *linesArray = [lyricString componentsSeparatedByString:@"\n"];
// 2. 建立模型陣列
NSMutableArray *modelArray = [NSMutableArray new];
// 3. 開始解析
// 由於有形如
// [ti:如果沒有你]
// [00:00.64]歌詞
// [00:01.89][03:01.23][05:03.43]歌詞
// [00:00.8]
// 這樣的歌詞形式,所以最好的方法是用正規表示式匹配 [00:00.00] 來獲取時間
for (NSString *line in linesArray) {
// 正規表示式
NSString *pattern = @"\\[[0-9][0-9]:[0-9][0-9].[0-9]{1,}\\]";
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
// 進行匹配
NSArray *matchesArray = [regular matchesInString:line options:NSMatchingReportProgress range:NSMakeRange(0, line.length)];
// 獲取歌詞部分
// 方法一
// NSTextCheckingResult *match = matchesArray.lastObject;
//
// NSString *content = [line substringFromIndex:(match.range.location + match.range.length)];
// 方法二 [00:01.78]歌詞
NSString *content = [line componentsSeparatedByString:@"]"].lastObject;
// 獲取時間部分[00:00.00]
for (NSTextCheckingResult *match in matchesArray) {
NSString *timeStr = [line substringWithRange:match.range];
// 去掉開頭和結尾的[],得到時間00:00.00
// 去掉[
timeStr = [timeStr substringFromIndex:1];
// 去掉]
timeStr = [timeStr substringToIndex:(timeStr.length - 1)];
// 分、秒、毫秒
NSString *minStr = [timeStr substringWithRange:NSMakeRange(0, 2)];
NSString *secStr = [timeStr substringWithRange:NSMakeRange(3, 2)];
// 由於毫秒有一位或者兩位,所以應從小數點(第六位)後獲取
NSString *mseStr = [timeStr substringFromIndex:6];
// 轉換成以毫秒秒為單位的時間 1秒 = 1000毫秒
NSTimeInterval time = [minStr floatValue] * 60 * 1000 + [secStr floatValue] * 1000 + [mseStr floatValue];
// 建立模型,賦值
GKLyricModel *lyricModel = [GKLyricModel new];
lyricModel.content = content;
lyricModel.msTime = time;
lyricModel.secTime = time / 1000;
lyricModel.timeString = [GKTool timeStrWithMsTime:time];
[modelArray addObject:lyricModel];
}
}
// 去掉空白行歌詞
if (isDelBlank) {
[modelArray enumerateObjectsUsingBlock:^(GKLyricModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (!obj.content || [obj.content isEqualToString:@""]) {
[modelArray removeObject:obj];
}
}];
}
// 陣列根據時間進行排序 時間(time)
// ascending: 是否升序
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"msTime" ascending:YES];
return [modelArray sortedArrayUsingDescriptors:@[descriptor]];
}複製程式碼
然後就是歌曲播放是,滾動歌詞了,這裡通過在UITableView中前後都加上5行的空白行,讓歌詞能夠顯示在中間,然後根據歌曲播放的時間,重新整理tableview選中當前時間對應的歌詞並顯示在tableview的中間。
/**
根據當前時間及總時間滾動歌詞
@param currentTime 當前時間
@param totalTime 總時間
*/
- (void)scrollLyricWithCurrentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime {
if (self.lyrics.count == 0) self.lyricIndex = 0;
for (NSInteger i = 0; i < self.lyrics.count; i++) {
GKLyricModel *currentLyric = self.lyrics[i];
GKLyricModel *nextLyric = nil;
if (i < self.lyrics.count - 1) {
nextLyric = self.lyrics[i + 1];
}
if ((self.lyricIndex != i && currentTime > currentLyric.msTime) && (!nextLyric || currentTime < nextLyric.msTime)) {
self.lyricIndex = i;
//刷表
[self.lyricTable reloadData];
// 不是由拖拽產生的滾動,自動滾滾動歌詞
if (!self.isScrolling) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(self.lyricIndex + 5) inSection:0];
[self.lyricTable selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
}
}
}複製程式碼
看看效果圖吧
其他效果圖
當然還有很多的細節處理,在這裡就不在贅述了。具體實現還是去看Demo吧。
小結
本demo中其實並沒有音視訊的底層的知識,只是做了對VLCKit的使用,介面也是完全仿照網易雲音樂做的,這裡只是做一下分享,如果有寫的不好的地方還請見諒。
最後,如果您覺得還不錯,點個star吧!???
github地址:GKAudioPlayerDemo