推流完成后,需要拉流才能進行完整的直播。拉流我們采用的也是一個開源的第三方庫IJKMediaFramework。
這個庫本質是一個播放器,能播放flv格式的播放器。用起來和ios自帶的AVPlayer很相似。
實現功能:1.拉流播放。2.監聽。
一.創建占位圖和卡頓占位動效,代碼如下:
//直播前的占位圖片
- (UIImageView *)placeHolderView { if (!_placeHolderView) { _placeHolderView = [[UIImageView alloc] init]; _placeHolderView.frame = self.view.bounds; _placeHolderView.image = [UIImage imageNamed:@"profile_user_414x414"]; // 強制布局 [_placeHolderView layoutIfNeeded]; } return _placeHolderView; }
//卡頓占位動效 - (void)showActivityView{ if (!_activity) { _activity= [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; _activity.frame = CGRectMake((SCREAM_WEIGHT-100)*0.5, (SCREAM_HIGHT-100)*0.5, 100, 100); } [self.activity startAnimating]; [self.view addSubview:self.activity]; } //關閉卡頓占位動效 - (void)stopActivityView{ if ([_activity isAnimating]) { [_activity startAnimating]; } [_activity removeFromSuperview]; _activity = nil; }
二.拉流播放(創建播放器播放),代碼如下:
- (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.placeHolderView]; [self showActivityView]; IJKFFOptions *options = [IJKFFOptions optionsByDefault]; [options setPlayerOptionIntValue:1 forKey:@"videotoolbox"]; // 幀速率(fps) (可以改,確認非標准楨率會導致音畫不同步,所以只能設定為15或者29.97) [options setPlayerOptionIntValue:29.97 forKey:@"r"]; // -vol——設置音量大小,256為標准音量。(要設置成兩倍音量時則輸入512,依此類推 [options setPlayerOptionIntValue:512 forKey:@"vol"]; IJKFFMoviePlayerController *moviePlayer = [[IJKFFMoviePlayerController alloc] initWithContentURLString:PLAY_URL withOptions:options]; moviePlayer.view.frame = self.view.bounds; moviePlayer.scalingMode = IJKMPMovieScalingModeAspectFill; // 設置自動播放(必須設置為NO, 防止自動播放, 才能更好的控制直播的狀態) moviePlayer.shouldAutoplay = NO; // 默認不顯示 moviePlayer.shouldShowHudView = NO; [self.view insertSubview:moviePlayer.view atIndex:0]; [moviePlayer prepareToPlay]; self.moviePlayer = moviePlayer; // 設置監聽 [self addObserver]; [self.view addSubview:self.outBtn]; }
三.設置監聽(主要是監聽緩存情況),代碼如下:
- (void)addObserver { //監聽加載狀態改變通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadStateDidChange:) name:IJKMPMoviePlayerLoadStateDidChangeNotification object:self.moviePlayer]; } - (void)loadStateDidChange:(NSNotification *) notification { //狀態為緩沖幾乎完成,可以連續播放 if ((self.moviePlayer.loadState & IJKMPMovieLoadStatePlaythroughOK) != 0) { if (!self.moviePlayer.isPlaying) { //開始播放 [self.moviePlayer play]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if (_placeHolderView) { [_placeHolderView removeFromSuperview]; _placeHolderView = nil; } [self stopActivityView]; }); }else{ // 如果是網絡狀態不好, 斷開后恢復, 也需要去掉加載 if ([_activity isAnimating]) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self stopActivityView]; }); } } } //緩沖中 else if (self.moviePlayer.loadState & IJKMPMovieLoadStateStalled){ [self showActivityView]; /* 這里主播可能已經結束直播了。我們需要請求服務器查看主播是否已經結束直播。 方法: 1、從服務器獲取主播是否已經關閉直播。 優點:能夠正確的獲取主播端是否正在直播。 缺點:主播端異常crash的情況下是沒有辦法通知服務器該直播關閉的。 2、用戶http請求該地址,若請求成功表示直播未結束,否則結束 優點:能夠真實的獲取主播端是否有推流數據 缺點:如果主播端丟包率太低,但是能夠恢復的情況下,數據請求同樣是失敗的。 */ } }
四.記得關閉前釋放
- (void)dealloc{ if (_moviePlayer) { [_moviePlayer shutdown]; [_moviePlayer.view removeFromSuperview]; _moviePlayer = nil; } [[NSNotificationCenter defaultCenter]removeObserver:self]; }
-----------------------------分割線-------------------------------------
新手上路,共同進步群號:240970537