亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS利用AVPlayer播放網絡音樂的方法教程

2020-07-26 02:48:14
字體:
來源:轉載
供稿:網友

前言

假如你現在打算做一個類似百度音樂、豆瓣電臺的在線音樂類APP,你會怎樣做?

首先了解一下音頻播放的實現級別:

       (1) 離線播放:這里并不是指應用不聯網,而是指播放本地音頻文件,包括先下完完成音頻文件再進行播放的情況,這種使用AVFoundation里的AVAudioPlayer可以滿足

       (2) 在線播放:使用AVFoundation的AVPlayer可以滿足

       (3) 在線播放同時存儲文件:使用AudioFileStreamer + AudioQueue 可以滿足

       (4) 在線播放且帶有音效處理:使用AudioFileStreamer + AudioQueue + 音效模塊(系統自帶或者自行開發)來滿足

本文主要針對第二種級別,介紹如何使用AVPlayer實現網絡音樂的播放。

什么是AVPlayer

AVPlayer存在于AVFoundation中,其實它是一個視頻播放器,但是用它來播放音樂是沒問題的,當然播放音樂不需要呈現界面,因此我們不需要實現它的界面。

跟AVPlayer聯系密切的名詞:

Asset:AVAsset是抽象類,不能直接使用,其子類AVURLAsset可以根據URL生成包含媒體信息的Asset對象。

AVPlayerItem:和媒體資源存在對應關系,管理媒體資源的信息和狀態。

功能需求

通常音樂播放并展示到界面上需要我們實現的功能如下:

       1、(核心)播放器通過一個網絡鏈接播放音樂

       2、(基本)播放器的常用操作:暫停、播放、上一首、下一首等等

       3、(基本)監聽該音樂的播放進度、獲取音樂的總時間、當前播放時間

       4、(基本)監聽改播放器狀態:

     (1)媒體加載狀態

     (2)數據緩沖狀態

     (3)播放完畢狀態

       5、(可選)Remote Control控制音樂的播放

       6、(可選)Now Playing Center展示正在播放的音樂

功能實現

1、通過一個網絡鏈接播放音樂

NSURL * url = [NSURL URLWithString:self.currentSong.url];AVPlayerItem * songItem = [[AVPlayerItem alloc]initWithURL:url];AVPlayer * player = [[AVPlayer alloc]initWithPlayerItem:songItem];

這里是用一個asset來初始化player,當然你也可以直接用URL初始化:

AVPlayer * player = [[AVPlayer alloc] initWithURL:url];

需要獲取當前播放的item可以這樣獲取:

AVPlayerItem * songItem = player.currentItem;

2、播放器的常用操作

播放:

[player play];

需要注意的是初始化完player之后不一定會馬上開始播放,需要等待player的狀態變為ReadyToPlay才會進行播放。

暫停:

[player pause];

上一首、下一首:

這里我們有兩種方式可以實現,一種是由你自行控制下一首歌曲的item,將其替換到當前播放的item

[player replaceCurrentItemWithPlayerItem:songItem];

另一種是使用AVPlayer的子類AVQueuePlayer來播放多個item,調用advanceToNextItem來播放下一首音樂

NSArray * items = @[item1, item2, item3 ....];AVQueuePlayer * queuePlayer = [[AVQueuePlayer alloc]initWithItems:items];

3、監聽播放進度

使用addPeriodicTimeObserverForInterval:queue:usingBlock:來監聽播放器的進度

      (1)方法傳入一個CMTime結構體,每到一定時間都會回調一次,包括開始和結束播放

      (2)如果block里面的操作耗時太長,下次不一定會收到回調,所以盡量減少block的操作耗時

      (3)方法會返回一個觀察者對象,當播放完畢時需要移除這個觀察者

添加觀察者:

id timeObserve = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {  float current = CMTimeGetSeconds(time);    float total = CMTimeGetSeconds(songItem.duration);    if (current) {       weakSelf.progress = current / total;       weakSelf.playTime = [NSString stringWithFormat:@"%.f",current];       weakSelf.playDuration = [NSString stringWithFormat:@"%.2f",total];  } }];

移除觀察者:

if (timeObserve) {  [player removeTimeObserver:_timeObserve];  timeObserve = nil; }

4、監聽改播放器狀態

(1) 媒體加載狀態

[songItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];

然后可以在KVO方法中獲取其status的改變

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"status"]) {  switch (self.player.status) {      case AVPlayerStatusUnknown:        BASE_INFO_FUN(@"KVO:未知狀態,此時不能播放");        break;      case AVPlayerStatusReadyToPlay:        self.status = SUPlayStatusReadyToPlay;         BASE_INFO_FUN(@"KVO:準備完畢,可以播放");        break;   case AVPlayerStatusFailed:    BASE_INFO_FUN(@"KVO:加載失敗,網絡或者服務器出現問題");    break;      default:        break;    } }}

一般初始化player到播放都會經歷Unknown到ReadyToPlay這個過程,網絡情況良好時可能不會出現Unknown狀態的提示,網絡情況差的時候Unknown的狀態可能會持續比較久甚至可能不進入ReadyToPlay狀態,針對這種情況我們要做特殊的處理。

播放完成之后需要移除觀察者:

[songItem removeObserver:self forKeyPath:@"status"];

(2) 數據緩沖狀態

[songItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];

然后可以在KVO方法中獲取其status的改變

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {  AVPlayerItem * songItem = object; if ([keyPath isEqualToString:@"loadedTimeRanges"]) {  NSArray * array = songItem.loadedTimeRanges;    CMTimeRange timeRange = [array.firstObject CMTimeRangeValue]; //本次緩沖的時間范圍  NSTimeInterval totalBuffer = CMTimeGetSeconds(timeRange.start) + CMTimeGetSeconds(timeRange.duration); //緩沖總長度  SuLog(@"共緩沖%.2f",totalBuffer); }}

如果你需要在進度條展示緩沖的進度,可以增加這個觀察者。

播放完成之后需要移除觀察者:

[songItem removeObserver:self forKeyPath:@" loadedTimeRanges"];

(3) 播放完畢狀態

監聽AVPlayer播放完成通知

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:songItem];- (void)playbackFinished:(NSNotification *)notice {  BASE_INFO_FUN(@"播放完成");  [self playNext];}

播放完畢后,一般都會進行播放下一首的操作。

播放下一首前,別忘了移除這個item的觀察者:

[[NSNotificationCenter defaultCenter] removeObserver:self];

5、Remote Control控制音樂的播放

Remote Control可以讓你在不打開APP的情況下控制其播放,最常見的出現于鎖屏界面、從屏幕底部上拉和耳機線控三種,可以達到增強用戶體驗的作用。

我們在AppDelegate里去設置Remote Control:

(1)聲明接收Remote Control事件

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

(2)重寫方法,成為第一響應者

- (BOOL)canBecomeFirstResponder {  return YES;}

(3)對事件進行處理

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {   switch (event.subtype) {    case UIEventSubtypeRemoteControlPlay:   [self.player startPlay];   BASE_INFO_FUN(@“remote_播放");   break;    case UIEventSubtypeRemoteControlPause:      [self.player pausePlay];   BASE_INFO_FUN(@"remote_暫停");   break;    case UIEventSubtypeRemoteControlNextTrack:   [self.player playNextSong];   BASE_INFO_FUN(@"remote_下一首");   break;    case UIEventSubtypeRemoteControlTogglePlayPause:      self.player.isPlaying ? [self.player pausePlay] : [self.player startPlay];      BASE_INFO_FUN(@“remote_耳機的播放/暫停");   break;    default:      break; }}

6、Now Playing Center

Now Playing Center可以在鎖屏界面展示音樂的信息,也達到增強用戶體驗的作用。

- (void)configNowPlayingCenter { BASE_INFO_FUN(@"配置NowPlayingCenter"); NSMutableDictionary * info = [NSMutableDictionary dictionary]; //音樂的標題 [info setObject:_player.currentSong.title forKey:MPMediaItemPropertyTitle];  //音樂的藝術家 [info setObject:_player.currentSong.artist forKey:MPMediaItemPropertyArtist];  //音樂的播放時間 [info setObject:@(self.player.playTime.intValue) forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];  //音樂的播放速度 [info setObject:@(1) forKey:MPNowPlayingInfoPropertyPlaybackRate];  //音樂的總時間 [info setObject:@(self.player.playDuration.intValue) forKey:MPMediaItemPropertyPlaybackDuration];  //音樂的封面 MPMediaItemArtwork * artwork = [[MPMediaItemArtwork alloc] initWithImage:_player.coverImg]; [info setObject:artwork forKey:MPMediaItemPropertyArtwork];  //完成設置 [[MPNowPlayingInfoCenter defaultCenter]setNowPlayingInfo:info];}

Now Playing Center并不需要每一秒都去刷新(設置),它是根據你設置的PlaybackRate來計算進度條展示的進度,比如你PlaybackRate傳1,那就是1秒刷新一次進度顯示,當然暫停播放的時候它也會自動暫停。

那什么時候設置Now Playing Center比較合適呢?對于播放網絡音樂來說,需要刷新的有幾個時間點:當前播放的歌曲變化時(如切換到下一首)、當前歌曲信息變化時(如從Unknown到ReadyToPlay)、當前歌曲拖動進度時。

如果有讀者是使用百度音樂聽歌的話,會發現其帶有鎖屏歌詞,其實它是采用“將歌詞和封面合成新的圖片設置為Now Playing Center的封面 + 歌詞躍進時刷新Now Playing Center”來實現的,有興趣的筒子可以研究一下。

關于總體的播放邏輯

總結一下音樂播放器的播放邏輯:

     (1) 初始化播放界面

     (2)從接口獲取播放列表、選擇第一首為當前播放歌曲

     (3)根據當前歌曲初始化播放器 、同步歌曲信息到播放界面(此時播放界面應展示歌曲信息,但是播放按鈕應不可用且有loading之類的提示表示正在加載歌曲)、同步歌曲信息到Now Playing Center

     (4)當播放器的status變為ReadyToPlay時,播放歌曲、同步播放信息到播放界面(播放時間、總時間、進度條等等)、同步播放信息到Now Playing Center

     (5)當用戶進行暫停操作時,刷新播放界面

     (6)當用戶進行下一首、上一首操作時,或完成某一首歌曲的播放時,將對應的歌曲設置為當前播放歌曲,重復3-5步驟

     (7)由于網絡情況不好造成播放器自動暫停播放時,應刷新播放界面

     (8)由于網絡情況不好造成播放器不能進入播放狀態時,應有所處理(比如提示耐心等待或者播放本地離線的歌曲)

后記

本文僅以實現基本功能的角度介紹了AVPlayer來播放網絡音樂的實現,事實上AVPlayer的功能不僅于此,有興趣的同學可以深入學習AVFoundation。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97精品伊人久久久大香线蕉| 欧美区二区三区| 欧美日韩中文字幕在线视频| 国产亚洲精品久久久久久777| 日韩精品在线观看一区二区| 国产精品极品美女粉嫩高清在线| 日韩毛片中文字幕| 日韩电影在线观看永久视频免费网站| 性欧美办公室18xxxxhd| 亚洲综合精品一区二区| 欧美一级视频在线观看| 亚洲va国产va天堂va久久| 久久久国产精品视频| 久久久亚洲国产天美传媒修理工| 91久久精品国产| 久久精品视频在线| 超碰日本道色综合久久综合| 国产精品久久久久久久久久久新郎| 日韩最新中文字幕电影免费看| 欧美激情精品久久久久久黑人| 色老头一区二区三区| 欧美性极品少妇精品网站| 欧美精品性视频| 亚洲美腿欧美激情另类| 精品magnet| 97av在线视频免费播放| 91社影院在线观看| 欧美丰满少妇xxxxx| 亚洲国内高清视频| 日韩在线观看免费高清完整版| 欧美成人久久久| 九九精品在线播放| 黑人巨大精品欧美一区二区三区| 日本久久久久久久久久久| 欧美中文字幕在线| 亚州精品天堂中文字幕| 成人精品一区二区三区电影免费| 亚洲综合中文字幕68页| 欧美成人三级视频网站| 亚洲香蕉av在线一区二区三区| 亚洲欧美中文另类| 日韩高清电影免费观看完整版| 国产91在线播放| 国产精品高清在线| 亚洲精品国产精品乱码不99按摩| 精品日本高清在线播放| 国产成人精品a视频一区www| 96国产粉嫩美女| 久久久久久18| 亚洲精品自在久久| 亚洲激情在线观看| 91麻豆国产精品| 亚洲视频一区二区三区| 成人h猎奇视频网站| 日韩精品视频三区| 国产精品久久久久91| 亚洲乱码国产乱码精品精| 色悠悠久久88| 日韩高清免费观看| 97在线观看免费高清| 欧美大胆在线视频| 日韩电影免费观看在线| 亚洲毛片在线观看.| 97在线观看免费| 国产欧美久久久久久| 日韩在线观看免费av| 亚洲伊人成综合成人网| 亚洲国产精品99久久| 亚洲精品www久久久久久广东| 97久久超碰福利国产精品…| 国产成人jvid在线播放| 日韩欧美成人区| 91成人国产在线观看| 国内外成人免费激情在线视频| 黑人巨大精品欧美一区二区免费| 国产一区二区在线免费| 国产精品福利在线观看| 精品偷拍各种wc美女嘘嘘| 亚洲成人激情在线观看| 法国裸体一区二区| 国产福利精品av综合导导航| 国产欧美 在线欧美| 91免费版网站入口| 欧美亚洲国产精品| 日韩激情在线视频| 海角国产乱辈乱精品视频| 欧美精品在线第一页| 亚洲黄色成人网| 韩国欧美亚洲国产| 日韩欧美有码在线| 精品久久久香蕉免费精品视频| 欧美主播福利视频| 日韩av观看网址| 亚洲成人a级网| 欧美精品在线观看| 日韩精品电影网| 国产精品午夜一区二区欲梦| 乱亲女秽乱长久久久| 91最新国产视频| 亚洲欧洲日本专区| 久久99亚洲精品| 久久精品视频中文字幕| 久久网福利资源网站| 欧美国产日韩视频| 成人在线播放av| 欧美成人免费网| 亚洲欧美日韩成人| 91九色在线视频| 中文字幕精品一区久久久久| 亚洲网站在线观看| 久久不射热爱视频精品| 久久九九精品99国产精品| 久久成年人视频| 91av在线免费观看视频| 欧洲精品久久久| 日韩欧美在线视频观看| 97香蕉久久超级碰碰高清版| 亚洲香蕉伊综合在人在线视看| 免费91麻豆精品国产自产在线观看| 97久久精品人搡人人玩| 中文字幕亚洲情99在线| 国产精品久久久久久中文字| 国产精品久久久久久av福利| 日韩一区二区精品视频| 中文字幕视频在线免费欧美日韩综合在线看| 亚洲色图美腿丝袜| 日韩在线中文字幕| 久久艳片www.17c.com| 国产精品91久久久| 欧美午夜片欧美片在线观看| 97视频免费看| 国产久一一精品| 精品少妇一区二区30p| 国产美女91呻吟求| 久久色在线播放| 色综合久久久888| 亚洲精品国产福利| 亚洲人成绝费网站色www| 国产69精品久久久| 亚洲国产精品一区二区三区| 欧亚精品在线观看| 91超碰中文字幕久久精品| 欧美日韩国产成人高清视频| 日产精品久久久一区二区福利| 国模精品一区二区三区色天香| 日韩欧美亚洲范冰冰与中字| 日韩禁在线播放| 日韩成人中文字幕在线观看| 久久久久久亚洲精品不卡| 91精品国产综合久久香蕉的用户体验| 欧美精品激情在线| 亚洲人成77777在线观看网| 国a精品视频大全| 国产婷婷成人久久av免费高清| 亚洲成色777777在线观看影院| 国产欧美日韩91| 国产精品视频白浆免费视频| 欧美日产国产成人免费图片| 亚洲欧美在线免费观看| 国产午夜精品全部视频在线播放| 欧美国产日韩二区| 久热在线中文字幕色999舞| 欧美在线视频a| 国产精品一区二区av影院萌芽|