iOS不用任何第三方,寫一個(gè)簡(jiǎn)單的RTMP直播推流器

2016年是移動(dòng)直播爆發(fā)年,不到半年的時(shí)間內(nèi)無(wú)數(shù)移動(dòng)直播App掀起了全民直播的熱潮。然而個(gè)人覺得直播的門檻相對(duì)較高,從推流端到服務(wù)端器到播放端,無(wú)不需要專業(yè)的技術(shù)來(lái)支撐,僅僅推流端就有不少需要學(xué)習(xí)的知識(shí).目前大部分直播采用的都是RTMP協(xié)議,我這里寫一個(gè)簡(jiǎn)單的Demo,幫助大家更好的理解直播推流的過(guò)程,主要包括:音視頻采集, 音視頻編碼, 數(shù)據(jù)打包, RTMP協(xié)議等相關(guān)的知識(shí)等.項(xiàng)目結(jié)構(gòu)分的很清楚,各個(gè)模塊也用協(xié)議進(jìn)行了分離,方便大家學(xué)習(xí)不同的模塊.


先闡述下推流的整體流程:

  • 建立tcp連接
  • 建立rtmp連接,以及發(fā)送各種控制指令
  • 獲取原始視頻數(shù)據(jù)和音頻數(shù)據(jù)
  • 對(duì)原始視頻數(shù)據(jù)和音頻數(shù)據(jù)進(jìn)行壓縮編碼
  • 對(duì)編碼后的視頻數(shù)據(jù)和音頻數(shù)據(jù)進(jìn)行打包
  • 發(fā)送打包后的音頻和視頻數(shù)據(jù)

項(xiàng)目各個(gè)類的作用

  • SGSimpleSession 是Api接口層,負(fù)責(zé)對(duì)外提供可直接調(diào)用的接口,同時(shí)也是一個(gè)數(shù)據(jù)分發(fā)中心,獲取到的原始音視頻數(shù)據(jù)和編碼后的數(shù)據(jù)都在這里被分發(fā)到不同的類進(jìn)行處理.

  • 視頻相關(guān)的類

    • SGVideoSource 原始視頻數(shù)據(jù)獲取類,底層用的是AVFoundation框架來(lái)實(shí)現(xiàn).對(duì)外提供原始未經(jīng)編碼的的視頻數(shù)據(jù),同時(shí)提供圖像預(yù)覽功能.如果需要添加美顏,攝像頭切換,翻轉(zhuǎn),閃光燈等操作,也是在這里處理的.

      原始視頻幀 : 原始視頻數(shù)據(jù)其實(shí)就是一幀一幀的數(shù)據(jù),它們沒有經(jīng)過(guò)壓縮編碼,每一幀包含了圖像信息和時(shí)間信息,我們通過(guò)代碼提取出圖片.

      fps :1s中包含的幀數(shù)就是幀速(fps),一般fps的范圍是15~30幀,幀速越高畫面越流暢,帶寬消耗量越大.實(shí)際直播中,大部分采用15到20就可以了.

      分辨率: 一幀的圖像的大小,iOS原生的有352*288,640*480,1280*720等,一般直播采用640 *480,然后裁剪為640 *360.

      碼率 : 也叫比特率,數(shù)據(jù)傳輸時(shí)單位時(shí)間傳送的數(shù)據(jù)位數(shù). 可以理解為碼率決定一幀圖像的顯示精細(xì)程度.在一定范圍內(nèi),碼率越大,圖像越清晰,消耗帶寬或者文件體積就越大.超過(guò)一定范圍后,清晰度不變.一般640 * 480分辨率的,碼率512kbps就能夠保證清晰度.

    • SGVideoConfig 這個(gè)視頻配置的類,主要包括壓縮等級(jí),分辨率,碼率等的配置

    • SGH264Encoder 這個(gè)類是編碼器,主要功能是對(duì)原始的視頻幀進(jìn)行編碼壓縮處理,這里采用的是硬編碼,編碼輸出格式為H264格式.

      編碼 : 編碼是指將原始的幀數(shù)據(jù)編碼壓縮,編碼后數(shù)據(jù)更小,方便在網(wǎng)絡(luò)上傳輸.原始數(shù)據(jù)體積較大,網(wǎng)絡(luò)傳輸十分不方便,因此需要將數(shù)據(jù)壓縮,視頻壓縮算法當(dāng)前比較主流的是H264,這里我們壓縮格式是H264格式.H264有不同的壓縮等級(jí),壓縮等級(jí)不同,壓縮比也不同.常見的壓縮等級(jí)有:baseline , main , high.

      硬編碼 : 硬編碼是相對(duì)軟編碼而言的,一般軟編碼是通過(guò)cpu來(lái)運(yùn)算,比較消耗cpu性能,耗時(shí)大,但是兼容性好,軟編碼一般采用ffmpeg或者x264.相對(duì)而言,硬編碼使用gpu來(lái)編碼,速度效率很高.這里采用的是iOS自帶的硬解碼,只支持iOS8以后的系統(tǒng).

      壓縮后的視頻幀 : 壓縮后的視頻有三種幀類型:I ,B ,P幀,I幀也叫關(guān)鍵幀.經(jīng)過(guò)解碼后能夠獨(dú)立展示出一幅圖像,P幀是前向預(yù)測(cè)幀,參考前一幀才能解碼顯示出一幅完整的圖像.B 為雙向預(yù)測(cè)幀,必須參考前一幀和后一幀才能解碼出圖像.因此,I幀的壓縮比最低,大約為0.7,它只能采用幀內(nèi)壓縮,P幀壓縮比次之,大概能達(dá)到0.5,B幀壓縮比則更高,達(dá)到了0.3~0.5,B幀和P幀采用的是幀內(nèi)壓縮和幀間壓縮技術(shù)(也就是運(yùn)動(dòng)估計(jì),原理是相鄰幀的圖像有一部分是一樣的,專業(yè)術(shù)語(yǔ)叫空間冗余).實(shí)際上,視頻壓縮等級(jí)不同,幀種類也不同,比如baseline等級(jí)壓縮后的視頻只有I幀 和 P幀.main等級(jí)high等級(jí) 則三種幀都包含,它們的整體壓縮比要比baseline要高.但是因?yàn)锽幀需要參考前一幀和后一幀才能顯示,很容易造成卡頓情況,因?yàn)槿f(wàn)一后面的幀沒有獲取到,導(dǎo)致前一幀已也不能顯示,所以在實(shí)際應(yīng)用中(直播app),一般壓縮等級(jí)采用baseline.

      gop : 這個(gè)我試著描述一下:因?yàn)槌薎幀,其它幀都不能獨(dú)立渲染顯示,理論上只需要一個(gè)I幀其它全部是非I幀,這樣壓縮比最高,但是因?yàn)?code>(B幀和P幀)參考其他幀的原因會(huì)有一定的誤差,當(dāng)一段時(shí)間后,累計(jì)誤差會(huì)原來(lái)越大,導(dǎo)致圖像失真.解決辦法就是以一小段為一個(gè)單元,每個(gè)單元第一幀都是I幀;這樣,即使前面某一小段出了問(wèn)題也不會(huì)影響后面的一小段,每一個(gè)小段我們稱作一個(gè)關(guān)gop.每個(gè)gop的第一幀一定是關(guān)鍵幀,因?yàn)槟愕臎]得參考;通常我們?cè)O(shè)置gop的大小為1s到3s,因此關(guān)鍵幀與關(guān)鍵幀之間的間隔就是1s的幀數(shù)(對(duì)應(yīng)gop為1s)到3s的幀數(shù)(對(duì)應(yīng)gop為3s),根據(jù)上面的定義,1s的幀數(shù)為fps,因此關(guān)鍵幀間隔為1*fps 到 3*fps.秒開的優(yōu)化點(diǎn)之一就是減小gop大小,因?yàn)間op第一幀是關(guān)鍵幀,能獨(dú)立渲染出來(lái),用戶進(jìn)入直播間的時(shí)間是隨機(jī)的,為確保用戶盡快拿到關(guān)鍵幀,盡快渲染出圖像;同時(shí)gop越小,關(guān)鍵幀數(shù)量就越多,帶寬消耗量就越大.

    • SGH264Packager 這個(gè)類負(fù)責(zé)對(duì)已經(jīng)編碼好的H264幀數(shù)據(jù)進(jìn)行打包處理,打包成符合RTMP協(xié)議格式的數(shù)據(jù),然后才能發(fā)送.

  • 音頻相關(guān)類

    • SGAudioSource 這個(gè)類主要負(fù)責(zé)錄制音頻數(shù)據(jù),輸出原始音頻幀,音頻的格式為PCM格式.

    • SGAudioConfig 這個(gè)類是音頻配置相關(guān)的類,主要包括聲道數(shù),碼率,采樣率的配置.

    • SGAACEncoder 這個(gè)類作用是將原始PCM音頻數(shù)據(jù)進(jìn)行編碼壓縮,編碼結(jié)果為AAC格式的音頻數(shù)據(jù),這里采用的是硬編碼.軟編碼的庫(kù)有faac.

    • SGAACPackager 這個(gè)了類作用是將編碼后的AAC格式數(shù)據(jù)大波按成符合RTMP協(xié)議的數(shù)據(jù).

  • RTMP相關(guān)類

    • SGStreamSession這個(gè)類主要是用來(lái)建立tcp連接,底層數(shù)據(jù)的讀取和發(fā)送,以及連接狀態(tài)的回調(diào),整個(gè)連接狀態(tài)貫穿整個(gè)項(xiàng)目,十分重要.
    • SGRtmpSession這個(gè)類主要與RTMP相關(guān),主要負(fù)責(zé)與服務(wù)器交互,包括RTMP握手,指令的發(fā)送,對(duì)數(shù)據(jù)的進(jìn)一步封裝,封裝成消息,然后再發(fā)送.指令有很多,說(shuō)點(diǎn)重要的,比如握手完成以后,要重新協(xié)商消息大小(默認(rèn)128字節(jié)),但是128字節(jié)太小,影響效率,一般都稍微改大點(diǎn),比如這里設(shè)置為16kb,如果太大也不好,會(huì)導(dǎo)致帶寬浪費(fèi).這個(gè)類涉及到rtmp相關(guān)的比較多,比較難以理解,網(wǎng)上有開源的實(shí)現(xiàn)librtmp這個(gè)庫(kù),可以用這個(gè)來(lái)替代.

以上就是整個(gè)項(xiàng)目的基本結(jié)構(gòu),整個(gè)過(guò)程類似工廠流水線,可以自行對(duì)各個(gè)模塊進(jìn)行替換和研究.demo中注釋也不少,方便理解.是不是感覺信息量有點(diǎn)大?可能有些地方說(shuō)的不嚴(yán)謹(jǐn),還望大家多多指正哈.


這個(gè)項(xiàng)目在去年7月份左右就寫完了,后來(lái)加了一些烏七八糟的東西,后來(lái)項(xiàng)目掛了,轉(zhuǎn)戰(zhàn)新項(xiàng)目(還是直播).中間寫過(guò)幾篇入門文章,本來(lái)打算寫成一個(gè)系列文章,無(wú)奈太忙了,寫的不完整.新年伊始,趁著項(xiàng)目不太忙,趕緊整理了一下,純碼字,如果有任何問(wèn)題可以直接留言.


附上學(xué)習(xí)博客:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瞧壮,一起剝皮案震驚了整個(gè)濱河市实夹,隨后出現(xiàn)的幾起案子直砂,更是在濱河造成了極大的恐慌幌陕,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件存崖,死亡現(xiàn)場(chǎng)離奇詭異冻记,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)金句,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門檩赢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人违寞,你說(shuō)我怎么就攤上這事贞瞒。” “怎么了趁曼?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵军浆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我挡闰,道長(zhǎng)乒融,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任摄悯,我火速辦了婚禮赞季,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奢驯。我一直安慰自己申钩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布瘪阁。 她就那樣靜靜地躺著撒遣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪管跺。 梳的紋絲不亂的頭發(fā)上义黎,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音豁跑,去河邊找鬼廉涕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的火的。 我是一名探鬼主播壶愤,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼馏鹤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起娇哆,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤湃累,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后碍讨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體治力,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年勃黍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宵统。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡覆获,死狀恐怖马澈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情弄息,我是刑警寧澤痊班,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站摹量,受9級(jí)特大地震影響涤伐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缨称,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一凝果、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧睦尽,春花似錦器净、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至宁玫,卻和暖如春粗恢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背欧瘪。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工眷射, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓妖碉,卻偏偏與公主長(zhǎng)得像涌庭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子欧宜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容