使用flv.js做直播


來自:https://github.com/gwuhaolin/blog/issues/3#issue-229271574

為什么要在這個時候探索flv.js做直播呢?原因在於各大瀏覽器廠商已經默認禁用Flash,之前常見的Flash直播方案需要用戶同意使用Flash后才可以正常使用直播功能,這樣的用戶體驗很致命。

在介紹flv.js之前先介紹下常見的直播協議以及給出我對它們的延遲與性能所做的測試得出的數據。
如果你看的很吃力可以先了解下音視頻技術的一些基礎概念

常見直播協議

  • RTMP: 底層基於TCP,在瀏覽器端依賴Flash。
  • HTTP-FLV: 基於HTTP流式IO傳輸FLV,依賴瀏覽器支持播放FLV。
  • WebSocket-FLV: 基於WebSocket傳輸FLV,依賴瀏覽器支持播放FLV。WebSocket建立在HTTP之上,建立WebSocket連接前還要先建立HTTP連接。
  • HLS: Http Live Streaming,蘋果提出基於HTTP的流媒體傳輸協議。HTML5可以直接打開播放。
  • RTP: 基於UDP,延遲1秒,瀏覽器不支持。

常見直播協議延遲與性能數據以下數據只做對比參考

傳輸協議 播放器 延遲 內存 CPU
RTMP Flash 1s 430M 11%
HTTP-FLV Video 1s 310M 4.4%
HLS Video 20s 205M 3%

在支持瀏覽器的協議里,延遲排序是:
RTMP = HTTP-FLV = WebSocket-FLV < HLS
而性能排序恰好相反:
RTMP > HTTP-FLV = WebSocket-FLV > HLS
也就是說延遲小的性能不好。

可以看出在瀏覽器里做直播,使用HTTP-FLV協議是不錯的,性能優於RTMP+Flash,延遲可以做到和RTMP+Flash一樣甚至更好。

flv.js 簡介

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

flv.js 優勢

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

flv.js 限制

  • FLV里所包含的視頻編碼必須是H.264,音頻編碼必須是AACMP3, IE11和Edge瀏覽器不支持MP3音頻編碼,所以FLV里采用的編碼最好是H.264+AAC,這個讓音視頻服務兼容不是問題。
  • 對於錄播,依賴 原生HTML5 Video標簽 和 Media Source Extensions API
  • 對於直播,依賴錄播所需要的播放技術,同時依賴 HTTP FLV 或者 WebSocket 中的一種協議來傳輸FLV。其中HTTP FLV需通過流式IO去拉取數據,支持流式IO的有fetch或者stream
  • flv.min.js 文件大小 164Kb,gzip后 35.5Kb,flash播放器gzip后差不多也是這么大。
  • 由於依賴Media Source Extensions,目前所有iOS和Android4.4.4以下里的瀏覽器都不支持,也就是說目前對於移動端flv.js基本是不能用的。

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

flv.js 原理

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

flv.js 為什么要繞一圈,從服務器獲取FLV再解碼轉換后再喂給Video標簽呢?原因如下:

  1. 兼容目前的直播方案:目前大多數直播方案的音視頻服務都是采用FLV容器格式傳輸音視頻數據。
  2. FLV容器格式相比於MP4格式更加簡單,解析起來更快更方便。

flv.js兼容方案

由於目前flv.js兼容性還不是很好,要用在產品中必要要兼顧到不支持flv.js的瀏覽器。兼容方案如下:

PC端

  1. 優先使用 HTTP-FLV,因為它延遲小,性能也不差1080P都很流暢。
  2. 不支持 flv.js 就使用 Flash播放器播 RTMP 流。Flash兼容性很好,但是性能差默認被很多瀏覽器禁用。
  3. 不想用Flash兼容也可以用HLS,但是PC端只有Safari支持HLS

移動端

  1. 優先使用 HTTP-FLV,因為它延遲小,支持HTTP-FLV的設備性能運行 flv.js 足夠了。
  2. 不支持 flv.js 就使用 HLS,但是 HLS延遲非常大。
  3. HLS 也不支持就沒法直播了,因為移動端都不支持Flash。

flv.js實戰

說了這么多介紹與原理,接下來教大家如何用flv.js搭建一個完整的直播系統。
我已經搭建好了一個demo可以供大家體驗。

搭建音視頻服務

主播推流到音視頻服務,音視頻服務再轉發給所有連接的客戶端。為了讓你快速搭建服務推薦我用go語言實現的livego,因為它可以運行在任何操作系統上,對Golang感興趣?請看Golang 中文學習資料匯總

  1. 下載livego,注意選對你的操作系統和位數。
  2. 解壓,執行livego,服務就啟動好了。它會啟動RTMP(1935端口)服務用於主播推流,以及HTTP-FLV(7001端口)服務用於播放。

實現播放頁

在react體系里使用react flv.js 組件reflv 快速實現。
先安裝npm i reflv,再寫代碼:

import React, { PureComponent } from 'react'; import Reflv from 'reflv'; export class HttpFlv extends PureComponent { render() { return ( <Reflv url={`http://localhost:7001/live/test.flv`} type="flv" isLive cors /> ) } }

讓以上代碼在瀏覽器里運行。這是你還看不到直播,是因為還沒有主播推流。

  • 你可以使用OBS來推流,注意要配置好OBS:

screen shot 2017-06-07 at 5 41 32 pm

  • 也可以使用ffmpeg來推流,推流命令ffmpeg -f avfoundation -i "0" -vcodec h264 -acodec aac -f flv rtmp://localhost/live/test

flv.js延遲優化

按照上面的教程運行起來的直播延遲大概有3秒,經過優化可以到1秒。在教你怎么優化前先要介紹下直播運行流程:

  1. 主播端在采集到一段時間的音視頻原數據后,因為音視頻原數據龐大需要先壓縮數據:

    • 通過H264視頻編碼壓縮數據數據
    • 通過PCM音頻編碼壓縮音頻AAC數據
  2. 壓縮完后再通過FLV容器格式封裝壓縮后的數據,封裝成一個FLV TAG

  3. 再把FLV TAG通過RTMP協議推流到音視頻服務器,音視頻服務器再從RTMP協議里解析出FLV TAG。

  4. 音視頻服務器再通過HTTP協議通過和瀏覽器建立的長鏈接流式把FLV TAG傳給瀏覽器。

  5. flv.js 獲取FLV TAG后解析出壓縮后的音視頻數據喂給Video播放。

知道流程后我們就知道從哪入手優化了:

  • 主播端采集時收集了一段時間的音視頻原數據,它專業的叫法是GOP。縮短這個收集時間(也就是減少GOP長度)可以優化延遲,但這樣做的壞處是導致視頻壓縮率不高,傳輸效率低。
  • 關閉音視頻服務器的I楨緩存可以優化延遲,壞處是用戶看到直播首屏的時間變大。
  • 減少音視頻服務器的buffer可以優化延遲,壞處是音視頻服務器處理效率降低。
  • 減少瀏覽器端flv.js的buffer可以優化延遲,壞處是瀏覽器端處理效率降低。
  • 瀏覽器端開啟flv.js的Worker,多線程運行flv.js提升解析速度可以優化延遲,這樣做的flv.js配置代碼是:
{
          enableWorker: true, enableStashBuffer: false, stashInitialSize: 128,// 減少首楨顯示等待時長 }

這里是優化后的完整代碼

閱讀原文


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM