前言
在看這篇之前,如果您還不了解直播原理,請(qǐng)查看上篇文章如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app(原理篇)
開(kāi)發(fā)一款直播app,集成ijkplayer成功后,就算完成直播功能一半的工程了,只要有拉流url,就能播放直播啦
本篇主要講解的是直播app中,需要用到的一個(gè)很重要的開(kāi)源框架ijkplayer,然后集成這個(gè)框架可能對(duì)大多數(shù)初學(xué)者還是比較有難度的,所以本篇主要教你解決集成【ijkplayer】遇見(jiàn)的各種坑。
很多文章,可能講解的是如何做,我比較注重講解為什么這樣做,大家有什么不明白,還可以多多提出來(lái)。
如果喜歡我的文章,可以關(guān)注我微博:袁崢Seemygo,也可以來(lái)袁崢Seemygo,了解下我們的iOS培訓(xùn)課程。后續(xù)還會(huì)更新更多內(nèi)容,有任何問(wèn)題,歡迎簡(jiǎn)書(shū)留言崢吖。。。
效果
直播.gif
一、基本知識(shí)
README.md文件:框架的描述文件,描述這個(gè)框架怎么使用
編譯語(yǔ)言:程序在被執(zhí)行之前,需要一個(gè)專(zhuān)門(mén)的編譯過(guò)程,把程序編譯成為機(jī)器語(yǔ)言的文件,運(yùn)行時(shí)不需要翻譯,所以編譯型語(yǔ)言的程序執(zhí)行效率高,比如OC,C,C++
解釋性語(yǔ)言:解釋性語(yǔ)言的程序不需要編譯,在運(yùn)行程序的時(shí)候才翻譯,每個(gè)語(yǔ)句都是執(zhí)行的時(shí)候才翻譯。這樣解釋性語(yǔ)言每執(zhí)行一次就需要逐行翻譯一次,效率比較低
解釋性語(yǔ)言執(zhí)行和編譯語(yǔ)言執(zhí)行的區(qū)別:
解釋性語(yǔ)言一行一行的解析,如果有錯(cuò)誤,就不會(huì)執(zhí)行,直接執(zhí)行下一行。
編譯語(yǔ)言,只要有錯(cuò),就不能編譯,一行都不能執(zhí)行。
腳本語(yǔ)言:屬于解析語(yǔ)言,必須通過(guò)解釋器解析,將其一條條的翻譯成機(jī)器可識(shí)別的指令,并按程序順序執(zhí)行。
python:腳本語(yǔ)言,適合網(wǎng)絡(luò)應(yīng)用程序的開(kāi)發(fā),有利于開(kāi)發(fā)效率,現(xiàn)在顯得越來(lái)越強(qiáng)大
PHP:服務(wù)器端腳本語(yǔ)言,適合做動(dòng)態(tài)網(wǎng)站
JS:作為客戶(hù)端的腳本語(yǔ)言,在瀏覽中解釋執(zhí)行,
shell:操作系統(tǒng)腳本語(yǔ)言,一般指Unix/Linux中使用的命令行
編譯語(yǔ)言,執(zhí)行文件是二進(jìn)制。腳本語(yǔ)言是解釋執(zhí)行的,執(zhí)行文件是文本
shell解釋器:shell是一個(gè)命令行解釋器,相當(dāng)于windows的cmd,處于內(nèi)核和用戶(hù)之間,負(fù)責(zé)把用戶(hù)的指令傳遞給內(nèi)核并且把執(zhí)行結(jié)果回顯給用戶(hù).
默認(rèn)Unix都有shell,OS基于Unix,因此OS自帶shell。
bash: bash是一種shell解釋器版本,shell有很多種版本,就像人,也分不同國(guó)家的人。
牛程序員看到不爽的Shell解釋器,就會(huì)自己重新寫(xiě)一套,慢慢形成了一些標(biāo)準(zhǔn),常用的Shell解釋器有這么幾種,sh、bash、csh等
shell:通常我們說(shuō)的shell,指的是shell腳本語(yǔ)言,而不是shell解釋器。
在編寫(xiě)shell時(shí),第一行一定要指明系統(tǒng)需要哪種shell解釋器解釋你的shell腳本,如:#! /bin/bash,使用bash解析腳本語(yǔ)言
什么時(shí)候使用shell命令,比如有些系統(tǒng)命令經(jīng)常需要用到,可以把命令封裝到一個(gè)腳本文件,以后就不用再敲一遍了,直接執(zhí)行腳本語(yǔ)言。
比如ijkplayer,就用腳本文件下載ffmpeg,因?yàn)橄螺dffmpeg需要執(zhí)行很多命令,全部封裝到腳本文件中。
在導(dǎo)入一些第三方框架的時(shí)候,經(jīng)常需要用到一些命令,所以一般都會(huì)封裝到一個(gè)腳本文件中,以后只要執(zhí)行腳本,就會(huì)自動(dòng)執(zhí)行集成第三方框架的命令。
sh:sheel腳本文件后綴名
二、下載ijkPlayer
去到B站得github主頁(yè),找到ijkplayer項(xiàng)目,下載源碼ijkplayer下載地址
打開(kāi)Demo,查看用法,一般學(xué)習(xí)第三方庫(kù),都是先查看Demo
Snip20160825_4.png
三、編譯ijkPlayer的步驟
1、找到ijkPlayerMediaDemo并運(yùn)行
提示'libavformat/avformat.h' file not found
bug1.png
原因:因?yàn)閘ibavformat是ffmpeg中的庫(kù),而ijkplayer是基于ffmpeg這個(gè)庫(kù)的,因此需要導(dǎo)入ffmpeg
解決:查看ijkplayer的README.md,一般都會(huì)有說(shuō)明。
執(zhí)行腳本.png
init-ios.sh腳本的作用:下載ffmpeg源碼
想了解腳本具體怎么做的,可以查看之前寫(xiě)的文章帶你走進(jìn)腳本世界,ijkplayer之【init-ios.sh】腳本分析,全面剖析了init-ios.sh這個(gè)腳本做了哪些事情。
如何執(zhí)行init-ios.sh腳本文件
步驟一:找到init-ios.sh腳本文件
找到init-ios.sh文件.png
步驟二:打開(kāi)終端,cd進(jìn)入到ijkplayer-master的目錄中
進(jìn)入init-ios.sh目錄.png
注意是 cd 這個(gè)文件夾
cd ijkplayer-master.png
步驟三:輸入./init-ios.sh,就會(huì)執(zhí)行當(dāng)前腳本了。
執(zhí)行init-ios.sh.png
執(zhí)行完腳本后,就會(huì)發(fā)現(xiàn)ijkplayer中有ffmpeg了
執(zhí)行腳本后.png
2、下載好ffmpeg源碼后,再次運(yùn)行Demo
發(fā)現(xiàn)還是報(bào)'libavformat/avformat.h' file not found錯(cuò)誤
原因:執(zhí)行init-ios.sh,僅僅是下載源碼,但是源碼并沒(méi)有參與編譯,需要把源碼編譯成.a文件
Demo依賴(lài)于IJKMediaPlayer庫(kù)
Demo源碼.png
打開(kāi)? ? IJKMediaPlayer庫(kù),查看下源碼
IJKMediaPlayer工程位置.png
打開(kāi)? ? IJKMediaPlayer庫(kù)
IJKMediaPlayer源碼.png
右擊,發(fā)現(xiàn)FFMPEG中的庫(kù)都是紅的,表示不存在
Snip20160829_23.png
解決:查看ijkplayer的README.md
編譯ffmpeg.png
編譯ffmpeg庫(kù)
步驟一:進(jìn)入到腳本文件的目錄下
cd? ios.png
步驟二:執(zhí)行./compile-ffmpeg.sh clean
步驟二功能:刪除一些文件和文件夾,為編譯ffmpeg.sh做準(zhǔn)備,在編譯ffmpeg.sh的時(shí)候,會(huì)自動(dòng)創(chuàng)建剛剛刪除的那些文件,為避免文件名沖突,因此在編譯ffmpeg.sh之前先刪除等會(huì)會(huì)自動(dòng)創(chuàng)建的文件夾或者文件
Snip20160828_19.png
步驟三:執(zhí)行./compile-ffmpeg.sh all,真正的編譯各個(gè)平臺(tái)的ffmpeg庫(kù),并生成所以平臺(tái)的通用庫(kù).
執(zhí)行./compile-ffmpeg.sh all
執(zhí)行compile-ffmpeg.sh all前
編譯前.png
執(zhí)行compile-ffmpeg.sh all后
編譯后.png
3.再次運(yùn)行Demo,就能成功了,因?yàn)镮JKMediaPlayer庫(kù)獲取到ffmpeg庫(kù)了
編譯完ffmpeg后,IJKMediaPlayer庫(kù)中顯示
成功獲取到ffmpeg庫(kù).png
cmd+r,Demo運(yùn)行成功
Demo運(yùn)行成功.png
四、如何集成到ijkplayer到自己的項(xiàng)目中
注意:ijkplayer的README中的方法比較麻煩,不方便攜帶,不推薦。
Snip20160830_9.png
1.推薦自己把IJKMediaPlayer打包成靜態(tài)庫(kù),在導(dǎo)入到自己的項(xiàng)目中。
如何打包,請(qǐng)參考,iOS中集成ijkplayer視頻直播框架,寫(xiě)的非常不錯(cuò),就不一一詳細(xì)介紹了,但是只有發(fā)布版本的庫(kù)。
我自己打包了ijkplayer兩個(gè)版本庫(kù),分別用于調(diào)試和發(fā)布(DEBUG和Release),點(diǎn)擊下載
由于文件太大上傳不了GitHUb,就上傳到百度云了
2.直接把ijkplayer庫(kù)拖入到自己的工程中,
調(diào)試的話,拖入調(diào)試版本的ijkplayer庫(kù),發(fā)布的話,拖入發(fā)布版本的ijkplayer庫(kù)
Snip20160829_5.png
3.導(dǎo)入ijkplayer依賴(lài)的庫(kù),具體可以查看ijkplayer的README
Snip20160829_6.png
Snip20160829_7.png
五、使用ijkplayer直播
1.ijkplayer用法簡(jiǎn)介
ijkplayer用法比較簡(jiǎn)單,其實(shí)只要有直播地址,就能直播了
注意:最好真機(jī)測(cè)試,模擬器測(cè)試比較卡,不流暢,真機(jī)就沒(méi)有問(wèn)題了
2.抓取數(shù)據(jù)
抓了很多直播app的數(shù)據(jù),發(fā)現(xiàn)映客主播的質(zhì)量是最高的。
映客主播url:http://116.211.167.106/api/live/aggregation?uid=133825214&interest=1
uid=賬號(hào)ID,這里是我的賬號(hào)ID
interest=興趣 ,1表示只查看女生,哈哈
上下拉刷新的接口沒(méi)抓到,就一下加載200條數(shù)據(jù),哈哈
- (void)loadData{// 映客數(shù)據(jù)urlNSString*urlStr =@"http://116.211.167.106/api/live/aggregation?uid=133825214&interest=1";// 請(qǐng)求數(shù)據(jù)AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];? ? mgr.responseSerializer= [AFJSONResponseSerializer serializer];? ? mgr.responseSerializer.acceptableContentTypes= [NSSetsetWithObjects:@"text/plain",nil];? ? [mgr GET:urlStr parameters:nilprogress:nilsuccess:^(NSURLSessionDataTask* _Nonnull task,NSDictionary* _Nullable responseObject) {? ? ? ? _lives = [YZLiveItem mj_objectArrayWithKeyValuesArray:responseObject[@"lives"]];? ? ? ? [_tableView reloadData];? ? } failure:^(NSURLSessionDataTask* _Nullable task,NSError* _Nonnull error) {NSLog(@"%@",error);? ? }];}
3.獲取拉流url,直播
IJKFFMoviePlayerController:用來(lái)做直播的類(lèi)
- (void)viewDidLoad {? ? [superviewDidLoad];self.view.backgroundColor= [UIColorwhiteColor];// 設(shè)置直播占位圖片NSURL*imageUrl = [NSURLURLWithString:[NSStringstringWithFormat:@"http://img.meelive.cn/%@",_live.creator.portrait]];? ? [self.imageViewsd_setImageWithURL:imageUrl placeholderImage:nil];// 拉流地址NSURL*url = [NSURLURLWithString:_live.stream_addr];// 創(chuàng)建IJKFFMoviePlayerController:專(zhuān)門(mén)用來(lái)直播,傳入拉流地址就好了IJKFFMoviePlayerController *playerVc = [[IJKFFMoviePlayerController alloc] initWithContentURL:url withOptions:nil];// 準(zhǔn)備播放[playerVc prepareToPlay];// 強(qiáng)引用,反正被銷(xiāo)毀_player = playerVc;? ? playerVc.view.frame= [UIScreenmainScreen].bounds;? ? [self.viewinsertSubview:playerVc.viewatIndex:1];}
4.結(jié)束播放
界面不播放,一定要記得結(jié)束播放,否則會(huì)報(bào)內(nèi)存溢出
內(nèi)存bug.png
- (void)viewWillDisappear:(BOOL)animated{? ? [superviewWillDisappear:animated];// 界面消失,一定要記得停止播放[_player pause];? ? [_player stop];}
結(jié)束語(yǔ)
后續(xù)還會(huì)更新更多有關(guān)直播的資料,希望做到教會(huì)每一個(gè)朋友從零開(kāi)始做一款直播app,并且Demo也會(huì)慢慢完善.
Demo點(diǎn)擊下載
由于FFMPEG庫(kù)比較大,大概100M。
本來(lái)想自己上傳所有代碼了,上傳了1個(gè)小時(shí),還沒(méi)成功,就放棄了。
提供另外一種方案,需要你們自己導(dǎo)入IJKPlayer庫(kù)
具體步驟:
下載Demo后,打開(kāi)YZLiveApp.xcworkspace問(wèn)題
打開(kāi)YZLiveApp.xcworkspace問(wèn)題
pod install就能解決
Snip20160830_12.png
下載jkplayer庫(kù),點(diǎn)擊下載
把jkplayer直接拖入到與Classes同一級(jí)目錄下,直接運(yùn)行程序,就能成功了
拖入ijkplayer到與Classes同一級(jí)目錄下.png
注意不需要打開(kāi)工程,把jkplayer拖入到工程中,而是直接把jkplayer庫(kù)拷貝到與Classes同一級(jí)目錄下就可以了。
錯(cuò)誤示范:不要向下面這樣操作