直播原理與web直播實戰

直播在互聯網中已經成爲一個必不可少的東西,話說各大直播平臺 bilibili,虎牙,鬥魚都準備上市了。javascript

富途證券做爲了一家互聯證券公司直播固然也少不了的。目前直播在富途牛牛軟件(如下簡稱:牛牛)中主要功能是教育跟宣傳做用。css

富途牛牛爲領先的港股美股交易軟件。html

文章結構

  1. 直播構成
  2. 直播流程
  3. web中直播技術
    • HLS協議
    • RTMP協議
    • HLS與RTMP對比
  4. 直播實戰
    • 安裝nginx、nginx-rtmp-module、FFmpeg(如下操做均在mac下進行)
    • nginx.conf配置文件,配置RTMP、HLS
    • 重啓nginx
    • 查看端口是否啓動
    • FFmpeg執行命令
    • 代碼
    • 效果
  5. 直播中遇到坑
  6. 總結

直播構成

直播構成

目前牛牛支持狀況:java

  1. 移動牛牛(安卓、IOS)主播端只支持攝像頭直播,觀衆端支持展現nginx

  2. PC牛牛主播端支持攝像頭直播、錄屏直播、攝像頭+錄屏直播,觀衆端支持展現git

  3. MAC牛牛跟web端主播端不支持,觀衆端支持展現github

直播流程

視頻直播能夠分爲採集,前處理,編碼,傳輸,解碼,渲染 這幾個環節。web

採集

通常是由客戶端(IOS、安卓、PC或其它工具,如OBS)完成的,iOS是比較簡單的,Android則要作些機型適配工做,PC最麻煩各類奇葩攝像頭驅動,固然這些問題,騰訊雲已經幫咱們處理好了,呵呵。算法

前處理

主要是處理直播美顏,美顏算法須要用到GPU編程,須要懂圖像處理算法的人,沒有好的開源實現,要本身參考論文去研究。難點不在於美顏效果,而在於GPU佔用和美顏效果之間找平衡。chrome

編碼

確定要採用硬編碼,軟編碼720p徹底沒但願,勉強能編碼也會致使CPU過熱燙到攝像頭。編碼要在分辨率,幀率,碼率,GOP等參數設計上找到最佳平衡點。

傳輸

通常交給了CDN服務商。

解碼

是對以前編碼的操做,進行解碼,在web裏須要解碼是HLS。

渲染

主要用播放器來解決,web中經常使用到的播放器有 video.js ,目前咱們使用是騰訊雲播放器。

其實一個完成直播,遠遠不上面這幾個環節,下面是騰訊雲直播方案的整個流程圖:

直播方案

web中直播技術

目前互聯網上web作直播,主要是展現,主流web展現的話可能涉及到HLS跟RTMP這兩個東西,如今咱們重點講解hls跟RTMP協議。

HLS

HLS(HTTP Live Streaming全稱)是一個基於HTTP的視頻流協議,由Apple公司實現,Mac OS上的QuickTime、Safari 以及iOS上的 Safari都能很好的支持 HLS,高版本 Android 也增長了對 HLS 的支持。

一些常見的客戶端如:MPlayerX、VLC 也都支持HLS協議,若是須要在chrome上播放,須要使用 videojs-contrib-hls.js 解析。

HLS工做流程

HLS工做流程圖

Server服務器

HLS的服務器組件負責獲取的媒體輸入流 , 而後Media編碼後 MPEG-4(H.264 video 和 AAC audio)格式而後用硬件打包到 MPEG-2 (MPEG-2 transport stream)的傳輸流中。圖中顯示,傳輸流會通過stream segmenter, 這裏的工做是MPEG-2傳輸流會被分散爲小片斷而後保存爲一個或多個系列的 .ts 格式的媒體文件。這個過程須要藉助編碼工具來完成,好比 Apple stream segmenter。 (視頻類是.ts文件,純音頻會被編碼爲一些音頻小片斷,一般爲 ADTS頭的AAC、MP三、或者 AC-3格式。) 服務端能夠採用硬件編碼和軟件編碼兩種形式,其功能都是按照上文描述的規則對現有的媒體文件進行切片並使用索引文件進行管理。而軟件切片一般會使用 Apple 公司提供的工具或者第三方的集成工具。

Distribution分配組件

同時上面提到的那個切片器(segmenter)也會建立一個索引文件,一般會包含這些媒體文件的一個列表,也能包含元數據。它通常都是一個個.M38U的列表。列表元素會關聯一個 URL 用於客戶端訪問。而後按序去請求這些 URL。

索引文件結構圖

索引文件結構圖

主索引文件
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=409037,RESOLUTION=416x234,CODECS="mp4a.40.2, avc1.42001e"
Gear1/prog_index.m3u8

複製代碼

第一行:#EXTM3U

每一個M3U文件第一行必須是這個tag,起標示做用

第二行:#EXT-X-STREAM-INF

標籤的屬性列表中直接指明當前流是VIDEO仍是AUDIO

包含屬性 :

  1. BANDWIDTH 指定碼率
  2. PROGRAM-ID 惟一ID (這個屬性在後面的協議版本廢除了)
  3. CODECS 指定流的編碼類型
  4. RESOLUTION:分辨率
子索引文件
#EXTM3U
#EXT-X-TARGETDURATION:11
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10.133333,
fileSequence0.ts
#EXTINF:10.000666,
fileSequence1.ts
#EXTINF:10.667334,
fileSequence2.ts
#EXTINF:9.686001,
fileSequence3.ts
#EXTINF:9.768665,
fileSequence4.ts
#EXTINF:10.000000,
fileSequence5.ts
#EXT-X-ENDLIST

複製代碼

#EXTM3U m3u文件頭,必須放在第一行。

#EXT-X-TARGETDURATION 每一個分片TS的最大的時長。

#EXT-X-VERSION 用以標示協議版本。

#EXT-X-MEDIA-SEQUENCE TS分片的序列號。

#EXT-X-PLAYLIST-TYPE 提供關於PlayList的可變性的信息, 這個對整個PlayList文件有效,是可選的。

#EXTINF extra info,分片TS的信息,如時長,帶寬等。

主索引文件與子索引文件的區別
  • 主索引文件和子索引文件都是.M3U8的playlist
  • 主索引文件只需下載一次,但對於直播節目子索引文件按期從新加載

client客戶端

分配組件由標準的網絡服務器。他們負責接受Client客戶端請求並提供相關聯的資源給客戶端。

videojs-contrib-hls.js組件解析過程

videojs-contrib-hls.js

videojs-contrib-hls.js解析圖

HLS簡單講就是把整個流分紅一個個小的片斷,基於 HTTP 的文件來下載,每次只下載一小部分。

前面提到了用於 H5 播放直播視頻時引入的一個 .m3u8 的文件,這個文件就是基於 HLS 協議,存放視頻流元數據的文件。

每個 .m3u8 文件,分別對應若干個 ts 文件,這些 ts 文件纔是真正存放視頻的數據,m3u8 文件只是存放了一些 ts 文件的配置信息和相關路徑,當視頻播放時,.m3u8 是動態改變的,再經過解析器(videojs-contrib-hls.js)解析這個文件,並找到對應的 ts 文件來播放,因此通常爲了加快速度,.m3u8 放在 web 服務器上,ts 文件放在 cdn 上。

RTMP

Real Time Messaging Protocol(簡稱 RTMP)是 Macromedia 開發的一套視頻直播協議,如今屬於 Adobe。這套方案須要搭建專門的 RTMP 流媒體服務如 Adobe Media Server,而且在瀏覽器中只能使用 Flash 實現播放器。它的實時性很是好,延遲很小,但沒法支持移動端 WEB 播放是它的硬傷。

瀏覽器端,HTML5 video標籤沒法播放 RTMP 協議的視頻,能夠經過 video.js 來實現。

<link href="http://vjs.zencdn.net/5.8.8/video-js.css" rel="stylesheet">
 
<video id="example_video_1" class="video-js vjs-default-skin" controls preload="auto" width="640" height="264" loop="loop" webkit-playsinline>
<source src="rtmp://10.14.221.17:1935/rtmplive/home" type='rtmp/flv'>
</video>
 
<script src="http://vjs.zencdn.net/5.8.8/video.js"></script>
<script> videojs.options.flash.swf = 'video.swf'; videojs('example_video_1').ready(function() { this.play(); }); </script>
複製代碼

HLS VS RTMP 優缺點對比

協議 原理 延時 優勢 缺點 使用場景
HLS(http) 集合一段時間數據生成ts切片文件更m3u8文件 10s-30s 跨平臺 延時性高 移動端
RTMP(TCP) 每一個時刻的數據收到後當即發送 2s 延時低、實時性好 跨平臺差 PC+直播+實時性要求高+互動性強

直播實戰(搭建RTMP、HLS直播流服務)

安裝nginx

brew install nginx
複製代碼

安裝nginx-rtmp-module

brew install nginx-full --with-rtmp-module
複製代碼

而後安裝FFmpeg(是一個集錄制、轉換、音/視頻編碼解碼功能 爲一體的完整的開源工具,咱們下面用它來作推流跟切片)。

brew install ffmpeg
複製代碼

nginx.conf配置文件,配置RTMP、HLS

查找到nginx.conf配置文件(/usr/local/etc/nginx/nginx.conf),並配置相應的直播流配置。

rtmp {
    server {
    	#監聽的端口
    	listen 1935;
    	# RTMP 直播流配置
    	application rtmplive {
            live on;
            #爲 rtmp 引擎設置最大鏈接數。默認爲 off
            max_connections 1024;
        }
    	# HLS 直播流配置
    	application hls{
            live on;
            hls on;
            hls_path /Users/youname/Documents/notes/live/public/hls;  #這裏的路徑切片須要保存的路徑
            hls_fragment 1s;
        }
    }
}
複製代碼

在http中添加 HLS 的配置:

location /hls {
    # Serve HLS fragments
    types {
        application/vnd.apple.mpegurl m3u8;
        video/mp2t ts;
    }
    root /Users/youname/Documents/notes/live/public;#切片的路徑
    #add_header Cache-Controll no-cache;
    expires -1;
}
複製代碼

重啓nginx

sudo nginx -s reload
複製代碼

查看端口是否啓動

netstat -an | grep 1935
複製代碼

若是顯示以下,顯示已經啓用。

ng

http端口同理。

到如今咱們已經完成了,服務的搭建。

  1. RTMP推流地址爲 rtmp://127.0.0.1:1935/rtmplive/home
  2. HLS推流地址爲 rtmp://localhost:1935/rtmplive/hls

FFmpeg執行命令

咱們以推流MP4文件爲例,個人視頻文件地址:/Users/youname/Desktop/w01661pl9vw.p702.1.mp4

RTMP 協議推流命令:

ffmpeg -re -i /Users/youname/Desktop/w01661pl9vw.p702.1.mp4 -vcodec libx264 -acodec aac -f flv rtmp://127.0.0.1:1935/rtmplive/home

複製代碼

HLS 協議推流命令:

ffmpeg -re -i  /Users/youname/Desktop/w01661pl9vw.p702.1.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -q 10 rtmp://127.0.0.1:1935/hls/test 

複製代碼

參數:

  1. 視頻的地址:/Users/youname/Desktop/w01661pl9vw.p702.1.mp4
  2. 推流地址:rtmp://127.0.0.1:1935/rtmplive/home,rtmp://localhost:1935/rtmplive/hls

上面的命令操做後,命令行出現了以下圖,表示已經成功了。

ffmpeg

關於FFmpeg功能命令可參考:FFmpeg功能命令集合

web實現直播

兩種推流方式播放的話,咱們都使用video.js播放器播放(牛牛裏使用的是騰訊雲播放器)

RTMP協議代碼實現

須要注意的是src中的地址填的是RTMP推流地址。播放時,若是出現「當前系統環境不支持播放該視頻格式」,瀏覽器須要啓用flash,才能正常播放。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link href="http://vjs.zencdn.net/5.19/video-js.min.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/5.19/video.min.js"></script>
</head>
<body>
<video id="my-player" class="video-js" controls preload="auto" data-setup='{}'>
    <source src='rtmp://127.0.0.1/rtmplive/home' type='rtmp/flv'/>  
  </p>
</video>
<script type="text/javascript"> var player = videojs('my-player'); var options = {}; var player = videojs('my-player', options, function onPlayerReady() { videojs.log('Your player is ready!'); // In this context, `this` is the player that was created by Video.js. this.play(); // How about an event listener? this.on('ended', function() { videojs.log('Awww...over so soon?!'); }); }); </script>
</body>
</html>
複製代碼

HLS代碼實現

下面的src填的是切片地址。

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>videojs-contrib-hls embed</title>
  <link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
  <script src="https://unpkg.com/video.js/dist/video.js"></script>
  <script src="https://unpkg.com/videojs-contrib-hls/dist/videojs-contrib-hls.js"></script>
</head>
<body>
  <video id="my_video_1" class="video-js vjs-default-skin" controls preload="auto" width="640" height="268" data-setup='{}'>
    <source src="http://www.tony.com/hls/test.m3u8" type="application/x-mpegURL">
  </video>
</body>
</html>
複製代碼

效果

咱們來看看真正的效果如何。

RTMP效果

RTMP效果圖

HLS效果

HLS效果

ts和m3u8文件

ts和m3u8文件

實戰中遇到的坑

  • 自動播放問題
  • 各平臺播放器表現不統一
  • 內頁面調試困難
  • Native與web通訊問題

自動播放問題

在X5內核瀏覽器裏必須使用觸發touchend、click、doubleclick或keydown事件等標準的事件才能觸發。

各平臺播放器表現不統一

安卓下不少瀏覽器把video標籤替換成了原生自帶播放器樣式跟行爲,很難控制其行爲跟樣式。

內嵌頁面調試困難

目前使用的是weinre調試,但weinre調試看不到在native實際效果,好比web調用native,須要native反饋一種效果,weinre是看不到效果。

Native與web通訊

schema跟jsBridge,schema只能作到web調用native,並且作不到native調用web;jsBridge雖然能夠作native調用web,但在iframe沒加載完的狀況下,也是通知不到web的;

總結

整個直播是一個很是複雜的過程,實現過程當中會遇到不少性能問題,須要在性能跟即時性作一個權衡,ts跟m3u8儘可能作到緩存,瀏覽器裏儘可能使用推流。

歡迎你們關注富途web開發團隊,原文連接

參考資料:

如何搭建一個完整的視頻直播系統?

H5直播起航

有支持M3U8格式的HTML5播放器嗎?

HTTP Live Streaming (HLS) - 概念

M3U8格式講解及實際應用分析

相關文章
相關標籤/搜索