前言:剛來公司時士嚎,就接手了直播功能版塊的開發(fā)呜魄。推拉流走通了,邏輯框架和UI界面也都搭好了莱衩,但是因為資源問題爵嗅,老板決定放棄這個版塊。??
當時用的是網(wǎng)易云直播的sdk笨蚁,沒有集成IJKPlay睹晒,最近空閑時間比較多,就集成了一下IJKPlayer括细,使用很方便伪很,集成起來會麻煩一點
簡述下直播原理:
一個完整的直播程序,包括音視頻采集/處理奋单,視頻轉(zhuǎn)碼锉试,解碼拉取等。概括來說览濒,要有下面幾個環(huán)節(jié)進行配合:
推流端:采集主播的音視頻信息呆盖,進行美顏、變聲贷笛、信息編碼应又,將媒體流推流至服務器。
服務器端:對媒體流進行轉(zhuǎn)碼乏苦,錄制等處理株扛,分發(fā)數(shù)據(jù)。
拉流端:從服務器拉取媒體流汇荐,進行解碼席里、渲染、提供音視頻播放環(huán)境拢驾。
互動系統(tǒng):聊天室奖磁、彈幕、點贊繁疤。
其中核心環(huán)節(jié)無外乎就是 推/拉流 過程咖为,集成IJKPlayer,可以方便我們在這一步驟上所做的處理稠腊。
一. 什么是IJKPlayer躁染?
ijkplayer是B站的一款開源框架褪迟,專門用來做視頻直播歼冰,基于ffmpeg,同時支持 Android 和 iOS 平臺曹动。
對于 App 中的直播功能,如果我們成功集成ijkplayer 饰恕,那么只要得到一個拉流 URL挠羔,就能實現(xiàn)簡單的音視頻直播功能了。
二. 下載IJKPlayer
IJKPlayer下載地址
三. 運行demo埋嵌,編譯IJKPlayer
下載IJKPlayer時破加,在README里面已經(jīng)告訴了我們應該如何集成IJKPlayer,所以在編譯demo前雹嗦,應當在終端中按照圖中步驟進行相應操作范舀,如果沒有按照上面的提示步驟,而是直接運行demo了罪,因為缺少文件锭环,編譯器就會報錯,
readme中提示步驟:
-
打開終端泊藕,cd到IJKPlayer文件夾:
-
執(zhí)行./init-ios.sh命令(等待下載···):
進程結(jié)束后辅辩,會發(fā)現(xiàn)extra文件夾下會多出這兩個文件:
-
cd到ios文件夾下:
-
依次執(zhí)行:./compile-ffmpeg.sh clean 和 ./compile-ffmpeg.sh all命令(等待編譯ffmpeg···),過程比較久吱七,要耐心等待一會
-
進程結(jié)束后,查看是否編譯成功:
-
打開IJKPlayerDemo鹤竭,進行編譯:
四. 打包IJKPlayer進行集成
集成IJKPlayer有兩種方式:
- 按照README中的方法踊餐,和demo中一樣,將IJKMediaPlayer.xcodeproj導入到我們自己的項目中臀稚,直接按照README中的提示進行操作吝岭,這里不做多余贅述。
# Demo
# open ios/IJKMediaDemo/IJKMediaDemo.xcodeproj with Xcode
#
# Import into Your own Application
# Select your project in Xcode.
# File -> Add Files to ... -> Select ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj
# Select your Application's target.
# Build Phases -> Target Dependencies -> Select IJKMediaFramework
# Build Phases -> Link Binary with Libraries -> Add:
# IJKMediaFramework.framework
#
# AudioToolbox.framework
# AVFoundation.framework
# CoreGraphics.framework
# CoreMedia.framework
# CoreVideo.framework
# libbz2.tbd
# libz.tbd
# MediaPlayer.framework
# MobileCoreServices.framework
# OpenGLES.framework
# QuartzCore.framework
# UIKit.framework
# VideoToolbox.framework
#
# ... (Maybe something else, if you get any link error)
#
- 將IJKPlayer打包成framework吧寺,導入到項目中:
-
打開IJKMediaPlayer.xcodeproj
注:這里有兩個target窜管,IJKMediaFramework 和 IJKMediaFrameworkWithSSL,在支持https的情況下稚机,我們選擇IJKMediaFrameworkWithSSL進行編譯:
- 將編譯環(huán)境調(diào)成release模式:
-
分別在真機和模擬器上進行編譯幕帆,機型不限。
如果編譯報錯“l(fā)ibrary not found for -lcrypto”赖条,說明缺少文件
解決方法:我的解決方法是下載libcrypto和libssl文件拷貝到當前項目下失乾。
我在電腦上全局搜這兩個文件,發(fā)現(xiàn)之前的第三方里有這兩個文件纬乍,就直接拿來用了:
拷貝到文件夾下
添加文件:
再次編譯碱茁。
-
編譯成功后,進入Finder中仿贬,查看編譯結(jié)果:
-
將真機和模擬器上編譯生成的文件進行合并纽竣,要合并的文件在圖中進行了標記:
在終端執(zhí)行合成命令:
lipo -create 真機版本編譯后文件路徑 模擬器版本編譯后文件路徑 -output 合成后路徑(這里我放在Products文件夾下)
注: 合成后路徑指的是:合成后所放的文件夾/合成后的文件名,這里我把合成后文件命名為:“IJKMediaFrameWithSSL”,合成后路徑為:/Build/Products/IJKMediaFrameWithSSL
執(zhí)行完成后蜓氨,在Products文件夾下看到新的合成文件:
使用新的合成文件聋袋,替換掉真機版本編譯后文件路徑下的文件:
五. 將IJKPlayer集成到項目中
-
將打包好的IJKPlayer靜態(tài)庫和一些依賴庫添加到項目中:
編譯查看是否報錯:
這里暫時發(fā)現(xiàn)的有兩個錯誤:
1、xxx does not contain bitcode:
xcode默認開啟了bitcode语盈,如果我們集成的庫沒有bitcode編譯的包舱馅,則有可能出現(xiàn)報錯。
解決方法:target-->build setting-->enable bitcode-->NO
- 運行時crash刀荒,提示:dyld: Library not loaded: @rpath xxx reason: image not found
出現(xiàn)這種錯誤代嗤,是因為在運行時沒有找到framewok對應的包,如果運行到這個包時缠借,就會崩潰干毅。
解決方法:
手動添加framework到項目中:
六. 模仿demo,進行測試:
這里我寫了一個tableView泼返,鏈接到不同的拉流地址:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSURL *url = [NSURL URLWithString:_dataArray[indexPath.row]];
NSString *scheme = [[url scheme]lowercaseString];
if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"] || [scheme isEqualToString:@"rtmp"]) {
[XSIJKMediaPlayerViewController presentFromViewController:self withTitle:@"Livestream" URL:_dataArray[indexPath.row] completion:nil];
}
}
放入測試地址:
- (void)requestData{
NSArray *urls = @[@"rtmp://live.hkstv.hk.lxdns.com/live/hks",@"http://wzfree.10043.doftp.com/tvtest/182tv.php/live/id/suntv.m3u8",@"invalidUrl"];
_dataArray = [[NSMutableArray alloc]initWithArray:urls];
[_tableView reloadData];
}
在直播頁面的ViewController中進行配置:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor grayColor];
#ifdef DEBUG
//設置是否打印信息
[IJKFFMoviePlayerController setLogReport:YES];
[IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_DEBUG];
#else
[IJKFFMoviePlayerController setLogReport:NO];
[IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_INFO];
#endif
[IJKFFMoviePlayerController checkIfFFmpegVersionMatch:YES];
//配置參數(shù):數(shù)據(jù)處理硝逢、videotoolbox解碼、設置音視頻屬性參數(shù)設置
IJKFFOptions *options = [IJKFFOptions optionsByDefault];
self.player = [[IJKFFMoviePlayerController alloc]initWithContentURL:self.url withOptions:options];
self.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
self.player.view.frame = self.view.bounds;
self.player.scalingMode = IJKMPMovieScalingModeAspectFit;
self.player.shouldAutoplay = YES;
self.view.autoresizesSubviews = YES;
[self.view addSubview:self.player.view];
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(20, 20, 40, 40)];
[btn setTitle:@"返回" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(leftClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
運行效果:
這里只寫了簡單的拉流绅喉,代碼很簡單渠鸽,就不上demo了,其他相關代碼可以看IJKPlayer的demo柴罐,里面寫的很詳細徽缚。