H5直播入門(理論篇)

前言

這篇總結實際上是去年公司每週技術分享會輪到個人時候寫的。那時候公司正在大刀闊斧地準備直播業務,私覺得主管會委以重任,就翻了很多論壇,作了一次簡單的技術分享。後來直播業務讓另外一位同事承擔了,本身也就沒了實踐直播的機會,有點惋惜吧。好了,廢話很少說,開始咱們的理論篇~html

技術背景

能夠看到,直播從 PC 到一直髮展到移動端,愈來愈多的直播類 App 上線,同時移動直播進入了史無前例的爆發階段,可是對於大多數移動直播來講,仍是要以 Native 客戶端實現爲主,可是 H5 在移動直播端也承載着不可替代的做用,例如 H5 有着傳播快,易發佈的優點,同時最爲關鍵的是 H5 一樣能夠播放直播視頻。

2016年是直播元年,一是因爲各大寬帶提供商順應民意增寬降價,二是大量資本流進了直播板塊,促進了技術的更新迭代。市面上,最經常使用的是 Apple 推出的 HLS 直播協議(原始支持 H5 播放),固然,還有 RTMP、HTTP-FLV、RTP等。前端

視頻文件格式和直播協議

視頻文件格式

視頻文件格式實際上,咱們經常稱做爲容器格式,也就是,咱們通常生活中最常常談到的格式,flv,mp4,ogg 格式等。它就能夠理解爲將比特流按照必定順序放進特定的盒子裏。那選用不一樣格式來裝視頻有什麼問題嗎?android

答案是,沒有任何問題,可是你須要知道如何將該盒子解開,而且可以找到對應的解碼器進行解碼。那若是按照這樣看的話,對於這些 mp4,ogv,webm等等視頻格式,只要我有這些對應的解碼器以及播放器,那麼就沒有任何問題。那麼將視頻比特流放進一個盒子裏面,若是其中某一段出現問題,那麼最終生成的文件其實是不可用的,由於這個盒子自己就是有問題的。ios

不過,上面有一個誤解的地方在於,我只是將視頻理解爲一個靜態的流。試想一下,若是一個視頻須要持續不斷的播放,例如,直播,現場播報等。這裏,咱們就拿 TS/PS 流來進行講解。nginx

  • PS(Program Stream): 靜態文件流web

  • TS(Transport Stream): 動態文件流chrome

針對於上面兩種容器格式,其實是對一個視頻比特流作了不同的處理。瀏覽器

  • PS: 將完成視頻比特流放到一個盒子裏,生成固定的文件
  • TS: 將接受到的視頻,分紅不一樣的盒子裏。最終生成帶有多個盒子的文件。

那麼結果就是,若是一個或多個盒子出現損壞,PS 格式沒法觀看,而 TS 只是會出現跳幀或者馬賽克效應。二者具體的區別就是:對於視頻的容錯率越高,則會選用 TS,對視頻容錯率越低,則會選用 PS。服務器

直播協議HLS

HTTP Live Streaming(簡稱 HLS)是一個基於 HTTP 的視頻流協議。這是 Apple 提出的直播流協議。目前,IOS 和 高版本 Android 都支持 HLS。那什麼是 HLS 呢?HLS 主要的兩塊內容是 .m3u8 文件和 .ts 播放文件。架構

HLS 協議基於 HTTP,而一個提供 HLS 的服務器須要作兩件事:

編碼:以 H.263 格式對圖像進行編碼,以 MP3 或者 HE-AAC 對聲音進行編碼,最終打包到 MPEG-2 TS(Transport Stream)容器之中;

分割:把編碼好的 TS 文件等長切分紅後綴爲 ts 的小文件,並生成一個 .m3u8 的純文本索引文件;

瀏覽器使用的是 m3u8 文件。m3u8 跟音頻列表格式 m3u 很像,能夠簡單的認爲 m3u8 就是包含多個 ts 文件的播放列表。播放器按順序逐個播放,所有放完再請求一下 m3u8 文件,得到包含最新 ts 文件的播放列表繼續播,周而復始。整個直播過程就是依靠一個不斷更新的 m3u8 和一堆小的 ts 文件組成,m3u8 必須動態更新,ts 能夠走 CDN。

這裏,咱們着重介紹一下客戶端的過程。首先,直播之因此是直播,在於它的內容是實時更新的。那 HLS 是怎麼完成呢?

咱們使用 HLS 直接就用一個 video 進行包括便可:

<video autoplay controls>
    <source src="xxx.m3u8" type="application/vnd.apple.mpegurl" />
    <p class="warning">Your browser doesn't support video</p>
</video>
複製代碼

根據上面的描述,它實際上就是去請求一個 .m3u8 的索引文件。該文件包含了對 .ts 文件的相關描述,例如:

不過,這只是一個很是簡單,不涉及任何功能的直播流。實際上,HLS 的整個架構,能夠分爲:
masterplaylist 主要乾的事就是根據, 當前用戶的帶寬,分辨率,解碼器等條件決定使用哪個流。因此,master playlist 是爲了更好的用戶體驗而存在的。

當填寫了 master playlist URL,那麼用戶只會下載一次該 master playlist。接着,播放器根據當前的環境決定使用哪個 media playlist(就是 子 m3u8 文件)。若是,在播放當中,用戶的播放條件發生變化時,播放器也會切換對應的 media playlist。

固然,HLS 支持的功能,並不僅是分片播放(專門適用於直播),它還包括其餘應有的功能。

  • 使用 HTTPS 加密 ts 文件

  • 快/倒放

  • 廣告插入

  • 不一樣分辨率視頻切換

能夠看到 HLS 協議本質仍是一個個的 HTTP 請求 / 響應,因此適應性很好,不會受到防火牆影響。但它也有一個致命的弱點:延遲現象很是明顯。若是每一個 ts 按照 5 秒來切分,一個 m3u8 放 6 個 ts 索引,那麼至少就會帶來 30 秒的延遲。若是減小每一個 ts 的長度,減小 m3u8 中的索引數,延時確實會減小,但會帶來更頻繁的緩衝,對服務端的請求壓力也會成倍增長。因此只能根據實際狀況找到一個折中的點。

注意:HLS 在 PC 端僅支持safari瀏覽器,相似chrome瀏覽器使用HTML5 video標籤沒法播放 m3u8 格式,可直接採用網上一些比較成熟的方案,如:sewise-player、MediaElement、videojs-contrib-hls、jwplayer。

直播協議RTMP

Real Time Messaging Protocol(簡稱 RTMP)是 Macromedia 開發的一套視頻直播協議,如今屬於 Adobe。和 HLS 同樣均可以應用於視頻直播,區別是 RTMP 基於 flash 沒法在 iOS 的瀏覽器裏播放,可是實時性比 HLS 要好。因此通常使用這種協議來上傳視頻流,也就是視頻流推送到服務器。

下面是 HLS 和 RTMP 的對比:

直播協議HTTP-FLV

HTTP-FLV 和 RTMP 相似,都是針對於 FLV 視頻格式作的直播分發流。但,二者有着很大的區別。

  • 直接發起長鏈接,下載對應的 FLV 文件
  • 頭部信息簡單

如今市面上,比較經常使用的就是 HTTP-FLV 進行播放。但,因爲手機端上不支持,因此,H5 的 HTTP-FLV 也是一個痛點。不過,如今 flv.js 能夠幫助高版本的瀏覽器,經過 mediaSource 來進行解析。HTTP-FLV 的使用方式也很簡單。和 HLS 同樣,只須要添加一個鏈接便可:

<object type="application/x-shockwave-flash" src="xxx.flv"></object>
複製代碼

直播基本架構

目前較爲成熟的直播產品,大體都是以 Server 端和 H5 和 Native(android,ios)搭配實現直播,基本是下圖這個套路:

完整的直播能夠分爲如下幾塊:

  • 視頻錄製端:通常是電腦上的音視頻輸入設備或者手機端的攝像頭或者麥克風,目前以移動端的手機視頻爲主。

  • 視頻播放端:能夠是電腦上的播放器,手機端的 Native 播放器,還有就是 H5 的 video 標籤等,目前仍是已手機端的 Native 播放器爲主。

  • 視頻服務器端:通常是一臺 nginx 服務器,用來接受視頻錄製端提供的視頻源,同時提供給視頻播放端流服務。

而現行H5相似直播頁面,實現技術難點不大,其能夠經過實現方式分爲:① 底部視頻背景使用video視頻標籤實現播放 ② 關注、評論模塊利用 WebScoket 來實時發送和接收新的消息經過DOM 和 CSS3 實現 ③ 點贊利用 CSS3 動畫

對於彈幕來講,要稍微複雜一些,可能須要關注如下幾點:

  • 彈幕實時性,能夠利用 webscoket 來實時發送和接收新的彈幕並渲染出來。

  • 對於不支持 webscoket 的瀏覽器來講,只能降級爲長輪詢或者前端定時器發送請求來獲取實時彈幕。

  • 彈幕渲染時的動畫和碰撞檢測(即彈幕不重疊)等等

H5直播方案

使用flv.js作直播

  • 簡介

flv.js是來自Bilibli的開源項目。它解析FLV文件餵給原生HTML5 Video標籤播放音視頻數據,使瀏覽器在不借助Flash的狀況下播放FLV成爲可能。

  • 優點

因爲瀏覽器對原生Video標籤採用了硬件加速,性能很好,支持高清。同時支持錄播和直播。去掉對Flash的依賴。

  • 瀏覽器依賴

flv.js依賴的瀏覽器特性兼容列表

一、HTML5 Video

二、Media Source Extensions

三、WebSocket

四、HTTP FLV: fetch 或 stream

  • 原理

flv.js只作了一件事,在獲取到FLV格式的音視頻數據後經過原生的JS去解碼FLV數據,再經過Media Source Extensions API 餵給原生HTML5 Video標籤。(HTML5 原生僅支持播放 mp4/webm 格式,不支持 FLV)

flv.js 爲何要繞一圈,從服務器獲取FLV再解碼轉換後再餵給Video標籤呢?緣由以下:

一、兼容目前的直播方案:目前大多數直播方案的音視頻服務都是採用FLV容器格式傳輸音視頻數據。

二、FLV容器格式相比於MP4格式更加簡單,解析起來更快更方便。

  • 兼容方案

PC端

一、優先使用 HTTP-FLV,由於它延遲小,性能也不差1080P都很流暢。

二、不支持 flv.js 就使用 Flash播放器播 RTMP 流。Flash兼容性很好,可是性能差默認被不少瀏覽器禁用。

三、不想用Flash兼容也能夠用HLS,可是PC端只有Safari支持HLS

移動端

一、優先使用 HTTP-FLV,由於它延遲小,支持HTTP-FLV的設備性能運行 flv.js 足夠了。

二、不支持 flv.js 就使用 HLS,可是 HLS延遲很是大。

三、HLS 也不支持就無法直播了,由於移動端都不支持Flash。

好了,畢竟是入門理論篇,後續若是有業務實踐我會更新的,感受閱讀至此,比心~

相關文章
相關標籤/搜索