(轉(zhuǎn)帖著名出處:謝謝!)
首先說(shuō)下HLS協(xié)議:
簡(jiǎn)單講就是把整個(gè)流分成一個(gè)個(gè)小的,基于 HTTP 的文件來(lái)下載,每次只下載一些,前面提到了用于 H5 播放直播視頻時(shí)引入的一個(gè) .m3u8 的文件,這個(gè)文件就是基于 HLS 協(xié)議,存放視頻流元數(shù)據(jù)的文件。
每一個(gè) .m3u8 文件,分別對(duì)應(yīng)若干個(gè) ts 文件,這些 ts 文件才是真正存放視頻的數(shù)據(jù),m3u8 文件只是存放了一些 ts 文件的配置信息和相關(guān)路徑,當(dāng)視頻播放時(shí),.m3u8 是動(dòng)態(tài)改變的,video 標(biāo)簽會(huì)解析這個(gè)文件,并找到對(duì)應(yīng)的 ts 文件來(lái)播放,所以一般為了加快速度,.m3u8 放在 web 服務(wù)器上,ts 文件放在 cdn 上。
.m3u8 文件,其實(shí)就是以 UTF-8 編碼的 m3u 文件,這個(gè)文件本身不能播放,只是存放了播放信息的文本文件:
#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 指定每個(gè)媒體段(ts)的持續(xù)時(shí)間(秒),僅對(duì)其后面的URI有效mystream-12.ts
HLS 的請(qǐng)求流程是:
- http 請(qǐng)求 m3u8 的 url。
- 服務(wù)端返回一個(gè) m3u8 的播放列表,這個(gè)播放列表是實(shí)時(shí)更新的,一般一次給出5段數(shù)據(jù)的 url。
- 客戶(hù)端解析 m3u8 的播放列表,再按序請(qǐng)求每一段的 url,獲取 ts 數(shù)據(jù)流。

關(guān)于HLS延遲原因:
hls 協(xié)議是將直播流分成一段一段的小段視頻去下載播放的,所以假設(shè)列表里面的包含5個(gè) ts 文件,每個(gè) TS 文件包含5秒的視頻內(nèi)容,那么整體的延遲就是25秒。因?yàn)楫?dāng)你看到這些視頻時(shí),主播已經(jīng)將視頻錄制好上傳上去了,所以時(shí)這樣產(chǎn)生的延遲。當(dāng)然可以縮短列表的長(zhǎng)度和單個(gè) ts 文件的大小來(lái)降低延遲,極致來(lái)說(shuō)可以縮減列表長(zhǎng)度為1,并且 ts 的時(shí)長(zhǎng)為1s,但是這樣會(huì)造成請(qǐng)求次數(shù)增加,增大服務(wù)器壓力,當(dāng)網(wǎng)速慢時(shí)回造成更多的緩沖,所以蘋(píng)果官方推薦的ts時(shí)長(zhǎng)時(shí)10s,所以這樣就會(huì)大改有30s的延遲
視頻直播的整個(gè)流程:
視頻錄制端:一般是電腦上的音視頻輸入設(shè)備或者手機(jī)端的攝像頭或者麥克風(fēng),目前以移動(dòng)端的手機(jī)視頻為主。
視頻播放端:可以是電腦上的播放器,手機(jī)端的 native 播放器。
視頻服務(wù)器端:一般是一臺(tái) nginx 服務(wù)器,用來(lái)接受視頻錄制端提供的視頻源,同時(shí)提供給視頻播放端流服務(wù)。
簡(jiǎn)單流程

數(shù)據(jù)采集原理:
下面將利用 ios 上的攝像頭,進(jìn)行音視頻的數(shù)據(jù)采集,主要分為以下幾個(gè)步驟:
- 音視頻的采集,ios 中,利用 AVCaptureSession和AVCaptureDevice 可以采集到原始的音視頻數(shù)據(jù)流。
- 對(duì)視頻進(jìn)行 H264 編碼,對(duì)音頻進(jìn)行 AAC 編碼,在 ios 中分別有已經(jīng)封裝好的編碼庫(kù)來(lái)實(shí)現(xiàn)對(duì)音視頻的編碼。
- 對(duì)編碼后的音、視頻數(shù)據(jù)進(jìn)行組裝封包;
- 建立 RTMP 連接并上推到服務(wù)端。
ps:由于編碼庫(kù)大多使用 c 語(yǔ)言編寫(xiě),需要自己使用時(shí)編譯,對(duì)于 ios,可以使用已經(jīng)編譯好的編碼庫(kù)。
x264編碼:https://github.com/kewlbear/x264-ios(復(fù)制此鏈接到瀏覽器打開(kāi))
faac編碼:https://github.com/fflydev/faac-ios-build(操作同上)
ffmpeg編碼:https://github.com/kewlbear/FFmpeg-iOS-build-script(操作同上)
關(guān)于如果想給視頻增加一些特殊效果,例如增加濾鏡等,一般在編碼前給使用濾鏡庫(kù),但是這樣也會(huì)造成一些耗時(shí),導(dǎo)致上傳視頻數(shù)據(jù)有一定延時(shí)。
RTMP介紹:
Real Time Messaging Protocol(簡(jiǎn)稱(chēng) RTMP)是 Macromedia 開(kāi)發(fā)的一套視頻直播協(xié)議。和 HLS 一樣都可以應(yīng)用于視頻直播,區(qū)別是 RTMP 基于 flash 無(wú)法在 ios 的瀏覽器里播放,但是實(shí)時(shí)性比 HLS 要好。所以一般使用這種協(xié)議來(lái)上傳視頻流,也就是視頻流推送到服務(wù)器。
對(duì)比:
- RTMP 首先就是延遲低,基于TCP的長(zhǎng)鏈接,對(duì)于數(shù)據(jù)處理及時(shí),收到即刻發(fā)送,推薦使用場(chǎng)景:即時(shí)互動(dòng)。
- HLS 延遲高,短鏈接,原理是集合了一段時(shí)間的視頻數(shù)據(jù),切割ts片,逐個(gè)下載播放。優(yōu)點(diǎn)是跨平臺(tái)。
推流:
推流,就是將我們已經(jīng)編碼好的音視頻數(shù)據(jù)發(fā)往視頻流服務(wù)器中,一般常用的是使用 rtmp 推流,可以使用第三方庫(kù) librtmp-iOS 進(jìn)行推流,librtmp 封裝了一些核心的 api 供使用者調(diào)用,如果覺(jué)得麻煩,可以使用現(xiàn)成的 ios 視頻推流sdk,也是基于 rtmp 的。具體說(shuō)下:
也就是對(duì)編碼好的音視頻數(shù)據(jù)推到服務(wù)器上,這里我們又分為兩類(lèi)推流模式:手機(jī)端推流,服務(wù)器本地推流。就拿我上一家公司的電視直播來(lái)說(shuō),視頻源是來(lái)自電視臺(tái)的,需要通過(guò)ffmpeg命令來(lái)進(jìn)行個(gè)推流,那么推流協(xié)議的話(huà)這里又分為了:HLS推流和rtmp推流,這里的取舍主要涉及到了是否需要及其實(shí)時(shí)的直播問(wèn)題,也就是延遲20 30s是否接受,當(dāng)然電視直播并不是主播實(shí)時(shí)互動(dòng),所以不需要使用實(shí)時(shí)流媒體協(xié)議的rtmp,所以通過(guò)ffmpeg -loglevel 這么一個(gè)命令將電視臺(tái)給的視頻進(jìn)行各像nginx服務(wù)器的一個(gè)推流,那么我們就可以通過(guò)nginx服務(wù)器給的鏈接,配合我的第三方的直播框架,就可以實(shí)現(xiàn)個(gè)直播,這個(gè)是服務(wù)器本地的HLS協(xié)議的一個(gè)推流。當(dāng)然如果我們要做一個(gè)沒(méi)有延遲的比如實(shí)現(xiàn)各主播互動(dòng)的一個(gè)直播,那么就是iOS客戶(hù)端用rtmp協(xié)議的一個(gè)往nginx服務(wù)器的一個(gè)推流了。在iOS設(shè)備上進(jìn)行各推流的話(huà),是通過(guò)AVCaptureSession這么一個(gè)捕捉會(huì)話(huà),指定兩個(gè)AVCaptureDevice 也就是iOS的攝像頭和麥克風(fēng),獲取個(gè)原始視頻和音頻,然后需要進(jìn)行個(gè)H.264的視頻編碼和AAC的音頻編碼,再將編碼后的數(shù)據(jù)整合成一個(gè)音視頻包,通過(guò)rmtp推送到nginx服務(wù)器。這里這些步驟,我們可以通過(guò)各第三方集成好的推流工具進(jìn)行推流,這個(gè)工具有l(wèi)ibrtmp,和騰訊的GDLiveStreaming進(jìn)行個(gè)推流。