為什么要在這個時候探索flv.js做直播呢?原因在于各大瀏覽器廠商已經(jīng)默認禁用Flash,之前常見的Flash直播方案需要用戶同意使用Flash后才可以正常使用直播功能,這樣的用戶體驗很致命。
在介紹flv.js之前先介紹下常見的直播協(xié)議以及給出我對它們的延遲與性能所做的測試得出的數(shù)據(jù)。
如果你看的很吃力可以先了解下音視頻技術(shù)的一些基礎(chǔ)概念。
常見直播協(xié)議
RTMP: 底層基于TCP
,在瀏覽器端依賴Flash。
HTTP-FLV: 基于HTTP
流式IO傳輸FLV,依賴瀏覽器支持播放FLV。
WebSocket-FLV: 基于WebSocket
傳輸FLV,依賴瀏覽器支持播放FLV。WebSocket
建立在HTTP
之上,建立WebSocket
連接前還要先建立HTTP
連接。
HLS: Http Live Streaming,蘋果提出基于HTTP
的流媒體傳輸協(xié)議。HTML5
可以直接打開播放。
RTP: 基于UDP
,延遲1秒,瀏覽器不支持。
常見直播協(xié)議延遲與性能數(shù)據(jù)以下數(shù)據(jù)只做對比參考
傳輸協(xié)議 | 播放器 | 延遲 | 內(nèi)存 | CPU |
---|---|---|---|---|
RTMP | Flash | 1s | 430M | 11% |
HTTP-FLV | Video | 1s | 310M | 4.4% |
HLS | Video | 20s | 205M | 3% |
在支持瀏覽器的協(xié)議里,延遲排序是:
RTMP = HTTP-FLV = WebSocket-FLV <>
而性能排序恰好相反:
RTMP > HTTP-FLV = WebSocket-FLV > HLS
也就是說延遲小的性能不好。
可以看出在瀏覽器里做直播,使用HTTP-FLV協(xié)議是不錯的,性能優(yōu)于RTMP+Flash,延遲可以做到和RTMP+Flash一樣甚至更好。
flv.js 簡介
flv.js是來自Bilibli的開源項目。它解析FLV文件喂給原生HTML5 Video標(biāo)簽播放音視頻數(shù)據(jù),使瀏覽器在不借助Flash的情況下播放FLV成為可能。
flv.js 優(yōu)勢
由于瀏覽器對原生Video標(biāo)簽采用了硬件加速,性能很好,支持高清。
同時支持錄播和直播
去掉對Flash的依賴
flv.js 限制
FLV里所包含的視頻編碼必須是H.264
,音頻編碼必須是AAC
或MP3
, IE11和Edge瀏覽器不支持MP3音頻編碼,所以FLV里采用的編碼最好是H.264+AAC,這個讓音視頻服務(wù)兼容不是問題。
對于錄播,依賴 原生HTML5 Video標(biāo)簽
和 Media Source Extensions API
對于直播,依賴錄播所需要的播放技術(shù),同時依賴 HTTP FLV
或者 WebSocket
中的一種協(xié)議來傳輸FLV。其中HTTP FLV
需通過流式IO去拉取數(shù)據(jù),支持流式IO的有fetch或者stream
flv.min.js
文件大小 164Kb,gzip后 35.5Kb,flash播放器gzip后差不多也是這么大。
由于依賴Media Source Extensions
,目前所有iOS和Android4.4.4以下里的瀏覽器都不支持,也就是說目前對于移動端flv.js基本是不能用的。
flv.js依賴的瀏覽器特性兼容列表
HTML5 Video
Media Source Extensions
WebSocket
HTTP FLV: fetch 或 stream
flv.js 原理
flv.js只做了一件事,在獲取到FLV格式的音視頻數(shù)據(jù)后通過原生的JS去解碼FLV數(shù)據(jù),再通過Media Source Extensions API 喂給原生HTML5 Video標(biāo)簽。(HTML5 原生僅支持播放 mp4/webm 格式,不支持 FLV)
flv.js 為什么要繞一圈,從服務(wù)器獲取FLV再解碼轉(zhuǎn)換后再喂給Video標(biāo)簽?zāi)??原因如下?/p>
兼容目前的直播方案:目前大多數(shù)直播方案的音視頻服務(wù)都是采用FLV容器格式傳輸音視頻數(shù)據(jù)。
FLV容器格式相比于MP4格式更加簡單,解析起來更快更方便。
flv.js兼容方案
由于目前flv.js兼容性還不是很好,要用在產(chǎn)品中必要要兼顧到不支持flv.js的瀏覽器。兼容方案如下:
PC端
優(yōu)先使用 HTTP-FLV,因為它延遲小,性能也不差1080P都很流暢。
不支持 flv.js 就使用 Flash播放器播 RTMP 流。Flash兼容性很好,但是性能差默認被很多瀏覽器禁用。
不想用Flash兼容也可以用HLS,但是PC端只有Safari支持HLS
移動端
優(yōu)先使用 HTTP-FLV,因為它延遲小,支持HTTP-FLV的設(shè)備性能運行 flv.js 足夠了。
不支持 flv.js 就使用 HLS,但是 HLS延遲非常大。
HLS 也不支持就沒法直播了,因為移動端都不支持Flash。
flv.js實戰(zhàn)
說了這么多介紹與原理,接下來教大家如何用flv.js搭建一個完整的直播系統(tǒng)。
我已經(jīng)搭建好了一個demo可以供大家體驗。
搭建音視頻服務(wù)
主播推流到音視頻服務(wù),音視頻服務(wù)再轉(zhuǎn)發(fā)給所有連接的客戶端。為了讓你快速搭建服務(wù)推薦我用go語言實現(xiàn)的livego,因為它可以運行在任何操作系統(tǒng)上,對Golang感興趣?請看Golang 中文學(xué)習(xí)資料匯總。
下載livego,注意選對你的操作系統(tǒng)和位數(shù)。
解壓,執(zhí)行livego
,服務(wù)就啟動好了。它會啟動RTMP(1935端口)服務(wù)用于主播推流,以及HTTP-FLV(7001端口)服務(wù)用于播放。
實現(xiàn)播放頁
在react體系里使用react flv.js 組件reflv 快速實現(xiàn)。
先安裝npm i reflv
,再寫代碼:
123456789101112131415 | import React, { PureComponent } from 'react';import Reflv from 'reflv';export class HttpFlv extends PureComponent { render() { return ( |
讓以上代碼在瀏覽器里運行。這是你還看不到直播,是因為還沒有主播推流。
你可以使用OBS來推流,注意要配置好OBS:
也可以使用ffmpeg來推流,推流命令ffmpeg -f avfoundation -i '0' -vcodec h264 -acodec aac -f flv rtmp://localhost/live/test
flv.js延遲優(yōu)化
按照上面的教程運行起來的直播延遲大概有3秒,經(jīng)過優(yōu)化可以到1秒。在教你怎么優(yōu)化前先要介紹下直播運行流程:
主播端在采集到一段時間的音視頻原數(shù)據(jù)后,因為音視頻原數(shù)據(jù)龐大需要先壓縮數(shù)據(jù):
通過H264視頻編碼壓縮數(shù)據(jù)數(shù)據(jù)
通過PCM音頻編碼壓縮音頻AAC數(shù)據(jù)
壓縮完后再通過FLV容器格式封裝壓縮后的數(shù)據(jù),封裝成一個FLV TAG
再把FLV TAG通過RTMP協(xié)議推流到音視頻服務(wù)器,音視頻服務(wù)器再從RTMP協(xié)議里解析出FLV TAG。
音視頻服務(wù)器再通過HTTP協(xié)議通過和瀏覽器建立的長鏈接流式把FLV TAG傳給瀏覽器。
flv.js 獲取FLV TAG后解析出壓縮后的音視頻數(shù)據(jù)喂給Video播放。
知道流程后我們就知道從哪入手優(yōu)化了:
主播端采集時收集了一段時間的音視頻原數(shù)據(jù),它專業(yè)的叫法是GOP??s短這個收集時間(也就是減少GOP長度)可以優(yōu)化延遲,但這樣做的壞處是導(dǎo)致視頻壓縮率不高,傳輸效率低。
關(guān)閉音視頻服務(wù)器的I楨緩存可以優(yōu)化延遲,壞處是用戶看到直播首屏的時間變大。
減少音視頻服務(wù)器的buffer可以優(yōu)化延遲,壞處是音視頻服務(wù)器處理效率降低。
減少瀏覽器端flv.js的buffer可以優(yōu)化延遲,壞處是瀏覽器端處理效率降低。
瀏覽器端開啟flv.js的Worker,多線程運行flv.js提升解析速度可以優(yōu)化延遲,這樣做的flv.js配置代碼是:
12345 | { enableWorker: true, enableStashBuffer: false, stashInitialSize: 128,// 減少首楨顯示等待時長} |
聯(lián)系客服