直播在2016年是一個(gè)非常火熱的領(lǐng)域伪冰,我也有幸在今年參與了新浪微博直播客戶(hù)端的開(kāi)發(fā)独旷,在此分享一下關(guān)于直播開(kāi)發(fā)的一些經(jīng)驗(yàn)余赢。
1.視頻直播的基本原理
視頻直播的過(guò)程大概由這么幾個(gè)部分構(gòu)成:
- 推流端
- 源服務(wù)器
- CDN邊緣節(jié)點(diǎn)
- 播放端
整個(gè)直播流轉(zhuǎn)的過(guò)程是:推流端將視頻流推向源服務(wù)器构眯,源服務(wù)器對(duì)視頻流進(jìn)行編碼或者轉(zhuǎn)存愕难,CDN負(fù)責(zé)負(fù)載均衡與緩存早龟,CDN節(jié)點(diǎn)從源服務(wù)器獲取視頻流惫霸,播放端再?gòu)腃DN上把視頻流拉下來(lái)。
2.不同的直播協(xié)議
- HLS
HLS全稱(chēng)是Http live stream葱弟,是蘋(píng)果公司主導(dǎo)的一種直播協(xié)議壹店,完全符合http協(xié)議標(biāo)準(zhǔn),Html對(duì)其原生進(jìn)行支持芝加,所以這種協(xié)議的優(yōu)勢(shì)就在于無(wú)論是在web端硅卢,還是iOS端都可以方便快捷的播放HLS的視頻流。HLS協(xié)議不僅支持直播還支持點(diǎn)播藏杖,廣泛的應(yīng)用于H5產(chǎn)品當(dāng)中将塑。
HLS本身請(qǐng)求的是一個(gè)m3u8格式的文件:
#EXTM3U m3u文件頭,必須放在第一行
#EXT-X-MEDIA-SEQUENCE 第一個(gè)TS分片的序列號(hào)
#EXT-X-TARGETDURATION 每個(gè)分片TS的最大的時(shí)長(zhǎng)
#EXT-X-ALLOW-CACHE 是否允許cache
#EXT-X-ENDLIST m3u8文件結(jié)束符
#EXTINF extra info蝌麸,分片TS的信息点寥,如時(shí)長(zhǎng),帶寬等
里面保存了一個(gè)一個(gè).ts格式的視頻分片文件路徑
直播流會(huì)首先下載當(dāng)前生成好的m3u8文件来吩,再去一個(gè)一個(gè)下載里面的分片視頻敢辩,所以對(duì)于源服務(wù)器來(lái)講,生成好了一個(gè)m3u8文件之后弟疆,客戶(hù)端才可能會(huì)拉到這個(gè)視頻流戚长,這也造成了HLS協(xié)議高延遲的問(wèn)題。倘若一個(gè)m3u8文件里面所有的分片長(zhǎng)度為10s怠苔,那么客戶(hù)端拉到這個(gè)視頻流的延遲至少為10s同廉。
rtmp
rtmp全稱(chēng)Real Time Messaging Protocol,是一種基于TCP的數(shù)據(jù)通信協(xié)議,廣泛的被應(yīng)用于流媒體的傳輸中來(lái)恤溶,此協(xié)議是實(shí)時(shí)傳輸數(shù)據(jù)流乓诽,所以延遲比HLS要低,由于具備TCP協(xié)議的擁塞控制咒程,對(duì)數(shù)據(jù)的完整性有一定保證鸠天。與此同時(shí),Adoube對(duì)rtmp協(xié)議的支持也做的很好帐姻,F(xiàn)lash可以完美的支持rtmp協(xié)議的視頻流播放稠集,大多數(shù)推流端都使用rtmp協(xié)議進(jìn)行推流。http-flv
http-flv是通過(guò)http協(xié)議傳輸flv的視頻流饥瓷,HTTP協(xié)議中有個(gè)content-length字段剥纷,規(guī)定了請(qǐng)求http的body部分的長(zhǎng)度,如果請(qǐng)求的時(shí)候不加content-length字段呢铆,那么客戶(hù)端會(huì)一直受到數(shù)據(jù)晦鞋。基于傳輸包的http-flv協(xié)議可以將數(shù)據(jù)包做的比rtmp做的更小棺克,在流量上有比較大的優(yōu)勢(shì)悠垛,而延遲幾乎和rtmp相同。UDP
在過(guò)去傳統(tǒng)的視頻通話(huà)廣泛的基于UDP協(xié)議娜谊,由于不像以上幾種協(xié)議都基于TCP這種帶擁塞控制的協(xié)議确买,UDP可以做到1s以?xún)?nèi)的超低延遲,在直播中UDP沒(méi)有廣泛采用的原因是需要對(duì)服務(wù)端的架構(gòu)進(jìn)行改造纱皆,所以對(duì)于之前做過(guò)視頻通話(huà)的廠(chǎng)商來(lái)講湾趾,他們擁有著得天獨(dú)厚的優(yōu)勢(shì),目前很多互聯(lián)網(wǎng)教育廠(chǎng)商由于對(duì)超低延遲的需求派草,基本都采用了UDP協(xié)議
3.直播延遲問(wèn)題
隨著視頻直播領(lǐng)域變得越來(lái)越火搀缠,直播的延遲問(wèn)題也日趨收到開(kāi)發(fā)者的關(guān)注,根據(jù)不同也業(yè)務(wù)需求近迁,廠(chǎng)商對(duì)延遲的要求也有所不同艺普,美女秀場(chǎng)直播2~5s之間可以忍受,對(duì)于在線(xiàn)教育來(lái)講1s左右才能保證正常的教學(xué)需求钳踊≈缘校總體來(lái)看,目前影響直播延遲基本有這么幾種原因:
- 網(wǎng)絡(luò)速度
在整個(gè)視頻直播流轉(zhuǎn)的過(guò)程中拓瞪,無(wú)論是推流端到源服務(wù)器之間的網(wǎng)速缴罗,還是播放端從CDN拉流的速度都影響著整個(gè)視頻直播過(guò)程的體驗(yàn)。所以網(wǎng)速往往是直播延遲最至關(guān)重要的原因祭埂。 - 傳輸協(xié)議
在上一節(jié)中講到了不同的傳輸協(xié)議對(duì)延遲的影響面氓,這里不再贅述兵钮。 - 編解碼速度
對(duì)于視頻直播來(lái)講編解碼的速度,好的編解碼策略也對(duì)直播卡頓延遲問(wèn)題有的很大的影響舌界,下一節(jié)我們來(lái)從了解H.264編碼的原理上思考如何做一個(gè)好的編解碼策略掘譬。
4.H.264編碼
我們知道視頻本身是由一張一張的圖片構(gòu)成,快速播放起來(lái)欺騙我們的眼睛呻拌,讓我們覺(jué)得圖片里面的場(chǎng)景是動(dòng)態(tài)的葱轩。但是如果一個(gè)1080p的視頻,以60幀的幀率來(lái)播放藐握,在視頻完全不壓縮的情況下靴拱,將是一個(gè)龐然大物,單單其中的一幀圖片就要好幾M猾普。所以大家發(fā)明了很多視頻編碼的來(lái)將視頻進(jìn)行壓縮袜炕。壓縮的基本思路就是將視頻中一張一張完整的圖片,有變化的部分存下來(lái)初家,一樣的部分就只存一張就好了偎窘,去除了冗余的部分視頻就會(huì)小得多。
我們讓一部分幀保存了完整的圖片溜在,對(duì)于這種幀我們叫做I幀陌知,如果I幀可以seek,我們將它叫做關(guān)鍵幀炕泳。兩個(gè)I幀之間叫做一個(gè)GOP纵诞。
只保存了變化部分的幀上祈,我們叫做參考幀培遵,其中又分為前向參考幀(P幀)和雙向參考幀(B幀)。參考幀的意思就是根據(jù)I幀或者P幀進(jìn)行參考登刺,決定自己保留圖片中的哪部分內(nèi)容籽腕。參考幀越多,尤其是B幀越多纸俭,這個(gè)視頻就越小皇耗,因?yàn)閳D片保留的部分就越少。
可以看到揍很,B幀需要前后都要參考郎楼,雖然更多的B幀可以更好的壓縮視頻的體積,但是對(duì)于編解碼也變得更加的困難窒悔,因?yàn)楫?dāng)我收到一個(gè)B幀之后呜袁,我必須等到后面有一個(gè)P幀或者I幀出現(xiàn)我才能進(jìn)行解碼,這對(duì)于直播的流暢性來(lái)講是有影響的简珠。
5.對(duì)于直播首幀的優(yōu)化
- GOP緩存
對(duì)于播放端的解碼器而言阶界,只有當(dāng)遇到一個(gè)I幀的時(shí)候,視頻才可以播放,假設(shè)播放端拉流的時(shí)候膘融,剛好需要等2s才會(huì)遇到下一個(gè)I幀芙粱,這個(gè)播放器就可能會(huì)黑2s。所以為了能夠秒開(kāi)氧映,快速的播放到第一幀視頻春畔,廠(chǎng)商往往會(huì)將最近的一個(gè)GOP緩存在CDN中,當(dāng)播放端去拉流的時(shí)候岛都,直接把上一個(gè)I幀傳下來(lái)拐迁,保證播放器拉到流直接就可以播放。 - 更小的緩沖buffer
直播視頻的buffer一般為百毫秒級(jí)疗绣,降低buffer可能幫助首幀快速的被渲染出來(lái)线召,但缺點(diǎn)是,在網(wǎng)絡(luò)狀態(tài)不好的條件下有可能出現(xiàn)頻繁caching的情況多矮。所以建議只策略的降低第一個(gè)緩沖buffer的大小缓淹,來(lái)幫助首幀可以快速呈現(xiàn)。 - CDN最近策略
由于CDN負(fù)載均衡的策略塔逃,CDN會(huì)根據(jù)當(dāng)前各個(gè)邊緣節(jié)點(diǎn)的負(fù)載情況來(lái)指定客戶(hù)端從哪個(gè)邊緣節(jié)點(diǎn)來(lái)拉流讯壶,但這樣有可能會(huì)導(dǎo)致播放端走了一個(gè)比較遠(yuǎn)的路由,從而增加延遲湾盗。有的廠(chǎng)商會(huì)在播放端密集的地區(qū)增加CDN的負(fù)載容納量伏蚊,并且指派就近原則,選取最近而不是根據(jù)負(fù)載來(lái)判斷拉流的路徑格粪。 - UDP策略
將基于TCP的視頻流協(xié)議換成無(wú)擁塞控制的UDP躏吊。 - local DNS
由于拉流時(shí)的請(qǐng)求地址往往是帶域名的,請(qǐng)求過(guò)程中走DNS服務(wù)器有時(shí)會(huì)耗費(fèi)一定的時(shí)間帐萎,可以選用local DNS比伏,在客戶(hù)端本地拿到緩存的ip地址直接請(qǐng)求服務(wù)器。