手牽手之流媒體視頻協議前端解決方案詳參

1. 前言

因本人厚積薄發,忽然對流媒體來了興致😄,機緣巧合須要整理方案,因而乎整理了關於流媒體協議,前端基本解決方案的一些見解。javascript

2. 流媒體背景

流媒體就是指採用流式傳輸技術在網絡上連續實時播放的媒體格式,如音頻、視頻或多媒體文件。流媒體技術也稱流式媒體技術。若有疑惑能夠先了解下音視頻技術的一些基礎概念css

3. 流媒體協議

流媒體協議是服務器與客戶端之間通訊遵循的規定。當前網絡上主要的流媒體協議如圖表所示。html

名稱 推出機構 傳輸層協議 客戶端 使用領域 優缺點
RTSP+RTP IETF TCP+UDP VLC,WMP IPTV 支持組播,效率較高,存在丟包問題,瀏覽器不支持。
RTMP Adobe Inc TCP Flash 互聯網直播 Adobe支持度高,適合長時間播放,延遲低(1s),有累積延遲。
RTMFP Adobe Inc UDP Flash 互聯網直播 帶寬消耗低,數據傳輸速率高,但需安裝Flash Player 10。
HLS Apple TCP Video 互聯網點播 Apple支持度高,兼容性好,但延時高(20S),緩存,存儲有難度。
HTTP-FLV Adobe Inc TCP Video 互聯網直播/點播 兼容性好,延遲低(1s),拉流、保密性不強。

延遲、性能排序:前端

在支持瀏覽器的協議裏,延遲排序(由高到低)是:java

HLS > WebSocket-FLV >RTMP = HTTP-FLVreact

而性能排序(由高到低)剛好相反:nginx

RTMP > HTTP-FLV = WebSocket-FLV > HLSgit

也就是說延遲小的性能很差。github

對比分析:web

  • 在瀏覽器裏作直播,使用HTTP-FLV協議是不錯的,性能優於RTMP+Flash,延遲能夠作到和RTMP+Flash同樣甚至更好。
  • HLS 延遲大,適合視頻點播。
  • RTMP強在瀏覽器支持好,加載Flash插件後就能直接播放。

4. 基於流媒體視頻前端解決方案

4.1 hls.js

4.1.1 hls.js簡介

hls.js是一個實現HTTP Live Streaming客戶端的JavaScript庫。它依靠HTML5視頻和MediaSource擴展進行播放。

它的工做原理是將MPEG-2傳輸流和AAC / MP3流轉換爲ISO BMFF(MP4)片斷。若是在瀏覽器中可用,則可使用Web Worker異步執行此傳輸。hls.js也支持HLS+fmp4,正如在WWDC2016期間宣佈的那樣hls.js不須要任何播放器,它直接在標準的HTML <video>元素之上工做。hls.js 使用ECMAScript6編寫,使用BabelECMAScript5中編譯。

4.1.2 hls.js的優缺點及兼容性

優點:

  • 體積比較小,很純淨。
  • 原生支持Video標籤。
  • HTMLVideoElement控件和事件能夠無縫使用。
  • UI能夠根據本身的業務自擴展,本身封裝功能和UI。

限制:

  • 沒有封裝好的UI,功能上也須要本身去實現。
  • 有必定延遲。

兼容性:

hls.js與支持MediaSource擴展(MSE)API的瀏覽器兼容,帶有'video / MP4'mimetypes輸入。

  • Chrome for Android 34+
  • Chrome for Desktop 34+
  • 適用於Android 41+的Firefox
  • Firefox for Desktop 42+
  • IE11 +適用於Windows 8.1+
  • 適用於Windows 10+的Edge
  • Opera for Desktop
  • Vivaldi for Desktop
  • Safari for Mac 8+(測試版)
  • 最新兼容詳情

請注意: iOS Safari「Mobile」不支持MediaSource API。然而,Safari瀏覽器經過普通視頻「標記」源URL支持內置HLS。當平臺既沒有MediaSource也沒有本機HLS支持時,您將沒法播放HLS。

4.1.3 hls.js原理

事件流:

因爲內部通訊都是基於 EventEmitter 來實現,經過事件流,你能夠了解到代碼運行的總體流程。

hls總體流程以下:

hls實際會先經過 ajax(loader 是能夠完成自定義的) 請求 m3u8文件,而後會讀取到文件的分片列表,以及視頻的編碼格式,時長等。隨後會按照順序(非 seek )去對分片進行請求,這些也是經過 ajax 請求二進制的文件,而後藉助 Media Source Extensions 將 buffer 內容進行合流,而後組成一個可播的媒體資源文件。

因爲內部經過自定事件進行數據傳遞和流程控制,參考下面的圖:

4.1.4 hls.js使用

安裝:

npm install  hls.js --save

npm install @types/hls.js -dev 

或者

https://cdnjs.cloudflare.com/ajax/libs/hls.js/0.12.4/hls.min.js
複製代碼

案例:

參考:

事件基本使用:

const hls = new Hls();
hls.on(Hls.Events.ERROR, (data) => {
    // do something~~        
});
複製代碼

注意:

聲明hls實例 const hls = new Hls() ,必定要在組件銷燬前,使用 hls.destroy() 註銷hls實例,不然會形成內存泄漏(都是坑出來的o(╥﹏╥)o)

4.2 flv.js

4.2.1 flv.js簡介

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

4.2.2 flv.js的優缺點及兼容

優點:

  • 因爲瀏覽器對原生Video標籤採用了硬件加速,性能很好,支持高清。
  • 同時支持錄播和直播。
  • 去掉對Flash的依賴。
  • FLV over WebSocket直播流播放。
  • HTTP FLV低延遲直播流播放。
  • 支持ts編譯。

限制:

  • FLV裏所包含的視頻編碼必須是H.264,音頻編碼必須是AAC或MP3, 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基本是不能用的。。
  • HTTP FLV實時流當前不適用於全部瀏覽器,請參閱livestream.md

兼容性:

  • 因爲IO限制,flv.js能夠支持HTTP FLV直播流Chrome 43+,FireFox 42+,Edge 15.15048+和Safari 10.1+如今。
  • HTTP FLV直播,必須Access-Control-Allow-Origin在流服務器上正確配置標頭。有關詳細信息,請參閱cors.md
  • flv.js依賴的瀏覽器特性兼容列表

flv.js兼容方案:

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

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。

4.2.3 flv.js原理

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

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

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

4.2.4 flv.js使用

安裝:

npm install --save flv.js
複製代碼

案例:

入門demo

搭建音視頻服務:

gwuhaolin 用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
      />
    )
  }
}
複製代碼

注: reflv是我的封裝flv.js,能夠參考,不建議直接使用。

讓以上代碼在瀏覽器裏運行。這是你還看不到直播,是由於尚未主播推流。

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

    6b12348fbc7d13903c39a8b2f141b6bc.png

  • 也可使用ffmpeg來推流,推流命令

    ffmpeg -f avfoundation -i "0" -vcodec h264 -acodec aac -f flv rtmp://localhost/live/test
    複製代碼

參考:

flv.js延遲優化:

優化前先要介紹下直播運行流程:

  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,// 減小首楨顯示等待時長
    }
    複製代碼

4.3 video.js

4.3.1 video.js簡介

Video.js是一款基於HTML5的網絡視頻播放器。它支持HTML5和Flash視頻,以及YouTube和Vimeo(經過插件)。支持在桌面和移動設備上播放視頻。這個項目從2010年中期開始,現已經在40多萬個網站上使用。

4.3.2 video.js的優缺點

優點:

  • 開源免費,能夠在github很容易的獲取它的最新代碼。
  • 兼容主流瀏覽器。
  • 界面能夠定製,純javascript和css打造。
  • 支持HLS, RTMP需引入插件支持。
  • 靈活插件機制。
  • 比較完善的文檔。
  • 項目熱度,開源做者對項目的維護比較積極。

限制:

  • 內置hls.js,體積偏大。

4.3.3 video.js原理

參考: H5播放器源碼解讀 (video.js)

4.3.4 video.js使用

安裝:

CDN

<link href="//vjs.zencdn.net/7.3.0/video-js.min.css" rel="stylesheet">
<script src="//vjs.zencdn.net/7.3.0/video.min.js"></script>
// 支持RTMP
<script src="https://cdn.jsdelivr.net/npm/videojs-flash@2/dist/videojs-flash.min.js"></script>
複製代碼

npm

yarn add video.js --save
// 支持RTMP
yarn add videojs-flash -- save
複製代碼

案例:

入門demo

Video.js 踩坑簡單入門:

採坑 採坑2

參考:

video.js文檔

5. HTML5視頻播放器

如下幾款HTML5視頻播放器,可配置插件,皮膚,自帶UI,支持彈幕,支持FLV,HLS按需引入,集成配置功能。可參考使用。更多功能可參考文檔。

xgplayer

xgplayer是一個網絡視頻播放器庫。它基於一切都是組件化的原則設計了一個獨立的,可拆卸的UI組件。更重要的是,它不只在UI層中具備靈活性,並且在功能上也大膽:它消除了視頻加載,緩衝和視頻依賴的格式支持。特別是在mp4上它能夠分階段加載,由於它不支持流mp4。這意味着無縫切換,清晰度,負載控制和視頻節省。它還集成了FLV,HLS和dash的按需和實時支持。

DPlayer

DPlayer是一個可愛的HTML5 danmaku視頻播放器,能夠幫助人們輕鬆地構建視頻和danmaku。

6. 流媒體測試

6.1 流媒體測試工具

要播放視頻直播流,或者測試一個直播視頻地址是否可使用。這裏推薦 VLC 媒體播放器。功能強大且跨平臺。支持 Windows、Mac OS、Linux、Android、iOS。

官網地址:連接

使用:

6.1 流媒體直播測試源

於2019年6月21日經測試可用。

HLS直播源地址:

RTMP直播源地址:

  • 香港衛視1:rtmp://live.hkstv.hk.lxdns.com/live/hks1

  • 香港衛視2:rtmp://live.hkstv.hk.lxdns.com/live/hks2

  • 湖南衛視:rtmp://58.200.131.2:1935/livetv/hunantv

  • 美國1:rtmp://ns8.indexforce.com/home/mystream

  • 美國中文電視:rtmp://media3.sinovision.net:1935/live/livestream

  • 香港財經:rtmp://202.69.69.180:443/webcast/bshdlive-pc

  • 韓國GoodTV:rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp

7. 參考

8. 小結

聲明:部份內容從網絡獲取,若有侵權行爲,請與做者聯繫,做者將於2日內刪除。

Peace: 👋 祝大家明天也是元氣慢慢的一天哦~~ 😄

相關文章
相關標籤/搜索