音視頻學習 (十) 基於 Nginx 搭建(rtmp、http)直播服務器

前言

最近這幾年作直播和短視頻領域是真的很火,並且直播的領域也很普遍,能夠預見,將來的音視頻技術將會做爲一種基礎技術應用到更普遍的場景中。它能夠與 AR/VR 結合,讓你在遠端體驗虛擬與現實,如虛擬服裝體驗;也能夠與人工智能結合用於提升服務質量,如用於教學上幫助老師提升教學質量;它還能夠與物聯網結合,用在自動駕駛、家庭辦公等領域。那麼這麼火範圍這麼廣的領域咱們可不能夠參與一下呢,確定是能夠的,下面咱們藉助 Nginxnginx-http-flv-module 搭建一個簡易的直播服務器,固然若是對併發要求不是過高的,這個徹底能夠知足了。css

因爲筆者沒有後臺服務開發的經驗而且對一些服務環境配置也不太懂,因此也是參考了一些博客最後總結了一套安裝使用教程,下面附上詳細的步驟。html

注意: 如下文字中若有出現 http://ip:port ,請替換成您本身的 IP 或域名。前端

直播協議介紹

國內常見公開的直播協議有幾個:RTMP、HLS、HDL(HTTP-FLV)、RTP,咱們來逐一介紹。node

RTMP

它是 Adobe 的專利協議,如今大部分國外的 CDN 已不支持。在國內流行度很高。緣由有幾個方面:android

一、開源軟件和開源庫的支持穩定完整。如鬥魚主播經常使用的 OBS 軟件,開源的 librtmp 庫,服務端有 nginx-rtmp 插件。nginx

二、播放端安裝率高。只要瀏覽器支持 FlashPlayer 就能很是簡易的播放 RTMP 的直播,協議詳解能夠 Google 瞭解。相對其餘協議而言,RTMP 協議初次創建鏈接的時候握手過程過於複雜(底層基於 TCP,這裏說的是 RTMP 協議自己的交互),視不一樣的網絡情況會帶來給首開帶來 100ms 以上的延遲。基於 RTMP 的直播通常內容延遲在2~5 秒。git

HTTP-FLV

即便用 HTTP 協議流式的傳輸媒體內容。相對於 RTMP,HTTP 更簡單和廣爲人知,並且不擔憂被 Adobe 的專利綁架。內容延遲一樣能夠作到 2~5 秒,打開速度更快,由於 HTTP 自己沒有複雜的狀態交互。因此從延遲角度來看,HTTP-FLV 要優於 RTMP。github

HLS

即 Http Live Streaming ,是由蘋果提出基於 HTTP 的流媒體傳輸協議。HLS 有一個很是大的優勢:HTML5 能夠直接打開播放;這個意味着能夠把一個直播連接經過微信等轉發分享,不須要安裝任何獨立的 APP,有瀏覽器便可,因此流行度很高。社交直播 APP,HLS 能夠說是剛需,下來咱們分析下其原理 。ajax

基於 HLS 的直播流 URL 是一個 m3u8 的文件,裏面包含了最近若干個小視頻 TS(一種視頻封裝格式,這裏就不擴展介紹)文件。如 http://ip:port/live.m3u8 是一個直播留連接,其內容以下:正則表達式

假設列表裏面的包含 5 個 TS 文件,每一個 TS 文件包含 5 秒的視頻內容,那麼總體的延遲就是 25 秒。固然能夠縮短列表的長度和單個 TS 文件的大小來下降延遲,極致來講能夠縮減列表長度爲 1,1 秒內容的 m3u8 文件,可是極易受網絡波動影響形成卡頓。經過公網的驗證,目前按同城網絡能夠作到比較好的效果是 5~7 秒的延遲,也是綜合流暢度和內容延遲的結果。

RTP

即 Real-time Transport Protocol ,用於 Internet 上針對多媒體數據流的一種傳輸層協議。

實際應用場景下常常須要 RTCP(RTP Control Protocol)配合來使用,能夠簡單理解爲 RTCP 傳輸交互控制的信令,RTP 傳輸實際的媒體數據。

RTP 在視頻監控、視頻會議、IP 電話上有普遍的應用,由於視頻會議、IP 電話的一個重要的使用體驗:內容實時性強。

對比與上述 3 種或實際是 2 種協議,RTP 和它們有一個重要的區別就是默認是使用 UDP 協議來傳輸數據,而 RTMP 和 HTTP 是基於 TCP 協議傳輸。爲何 UDP 能作到如此實時的效果呢?關於 TCP 和 UDP 差異的分析文章一搜一大把,這裏不在贅述,簡單歸納:

UDP:單個數據報,不用創建鏈接,簡單,不可靠,會丟包,會亂序;

TCP:流式,須要創建鏈接,複雜,可靠 ,有序。

實時音視頻流的場景不須要可靠保障,所以也不須要有重傳的機制,實時的看到圖像聲音,網絡抖動時丟了一些內容,畫面模糊和花屏,徹底不重要。TCP 爲了重傳會形成延遲與不一樣步,如某一截內容由於重傳,致使 1 秒之後纔到,那麼整個對話就延遲了 1 秒,隨着網絡抖動,延遲還會增長成 2 秒、3 秒,若是客戶端播放是不加以處理將嚴重影響直播的體驗。

總結一下:在直播協議的選擇中,若是選擇是 RTMP 或 HTTP-FLV 則意味着有 2~5 秒的內容延遲,可是就打開延遲開,HTTP-FLV 要優於 RTMP。HLS 則有 5~7 秒的內容延遲。選擇 RTP 進行直播則能夠作到1秒內的直播延遲。但就目前所瞭解,各大 CDN 廠商沒有支持基於 RTP 直播的,因此目前國內主流仍是 RTMP 或 HTTP-FLV 。

流媒體服務器開源軟件

環境準備

原本我打算是在個人 我的博客 服務器上搭建的,最終仍是放棄了,由於以前的帶寬跟容量也不是很大,也正巧遇見了 騰訊雲 這幾天在搞活動就又購買了一臺服務器,之後關於後臺服務的項目也基本上在這臺部署了。

如下是我搭建以及測試的環境

搭建服務器環境

雲服務器: 騰訊雲

系統: centos

直播服務器: nginx

拓展模塊: nginx-http-flv-module (支持 rtmp、http-flv、http-hls 等)

若是 NGINX 要支持正則表達式,須要安裝 PCRE庫

若是 NGINX 要支持加密訪問,須要安裝 OpenSSL庫

若是 NGINX 要支持壓縮,須要安裝 zlib庫

測試環境:

電腦 : MAC

推流軟件: obs-studio

MAC 拉流軟件: VLC

Android 拉流軟件: 前幾天寫的一個 Android 播放器 ykplayer 正好供於拉流測試

HTML5 FLV 播放器: bilibili 開源的 flv.js

原本以前我是藉助 nginx-rtmp-module 來搭建的直播服務器(已成功),奈何它好像不支持 Http-flv 協議,因此替換成了 nginx-http-flv-module 模塊,它是基於 nginx-rtmp-module 模塊二次開發的,因此完美的繼承了 rtmp 模塊的全部功能。

服務器搭建

1. download nginx

# 經過 wget 命令下載
wget http://nginx.org/download/nginx-1.17.8.tar.gz
# 解壓
tar -zxvf nginx-1.17.8.tar.gz
複製代碼

2. download nginx-http-flv-module

提醒: 關於它的詳細信息能夠參考它的介紹

# 經過 wget 命令下載
wget https://github.com/winshining/nginx-http-flv-module/archive/v1.2.7.tar.gz
# 解壓
tar -zxvf v1.2.7.tar.gz
# 重命名
mv v1.2.7 nginx-http-flv-module
複製代碼

3. install nginx 須要的環境

若是在執行 configure 以後報 OpenSSL 、PCRE 、Zlib error 那麼就必須安裝它們

#安裝 openssl
yum install   openssl
#安裝 pcre
yum install 	pcre-devel
#安裝 zlib
yum install   zlib-devel
複製代碼

等它們安裝好了以後編譯 nginx

4. build nginx

在當前解壓 nginx 目錄中建立編譯 nginx 和 http-flv 腳本

#!/bin/sh
# ../ 表明當前目錄的上一級
HTTP_FLV_MODULE_PATH=../nginx-http-flv-module-1.2.7
OpenSSL_PATH=../openssl-1.1.1d
 #--prefix=./bin 表明編譯完成以後輸出的路徑地址
#--add-module 將拓展模塊添加到當前一塊兒編譯
./configure --prefix=./bin \
--add-module=$HTTP_FLV_MODULE_PATH \
--with-openssl=$OpenSSL_PATH \
--with-debug
 # 經過 make install 構建
make
make install
複製代碼

若是中途沒有報任何錯誤,而且輸出了咱們指定的 bin 目錄,那麼就表明成功了。以下圖所示:

5. 配置 nginx.conf

在當前目錄下輸入 vim bin/conf/nginx.conf 進行配置 rtmp、http 直播協議,我直接貼上個人配置

user root;
worker_processes  auto; #運行在Windows上時,設置爲1,由於Windows不支持Unix domain socket
#worker_processes  auto; #1.3.8和1.2.5以及以後的版本

#worker_cpu_affinity  0001 0010 0100 1000; #只能用於FreeBSD和Linux
worker_cpu_affinity  auto; #1.9.10以及以後的版本

error_log logs/error.log error;

#若是此模塊被編譯爲動態模塊而且要使用與RTMP相關的功
#能時,必須指定下面的配置項而且它必須位於events配置
#項以前,不然NGINX啓動時不會加載此模塊或者加載失敗

#load_module modules/ngx_http_flv_live_module.so;

events {
    worker_connections  4096;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    keepalive_timeout  65;

    server {
        listen       80;//自定義填寫 http 的端口

        location / {
        root   /root/nginx/nginx-http-flv-module-1.2.7/test/www; 
	 			index  index.html index.htm;//默認首頁
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

				location /flvjsplay {//測試地址
					root /root/nginx/flv.js-1.5.0;
					index index.html;//flv.js 測試播放首頁
				}

				location /flv {
            flv_live on; #打開HTTP播放FLV直播流功能
            chunked_transfer_encoding on; #支持'Transfer-Encoding: chunked'方式回覆
						#跨域
            add_header 'Access-Control-Allow-Origin' '*'; #添加額外的HTTP頭
            add_header 'Access-Control-Allow-Credentials' 'true'; #添加額外的HTTP頭
        }

	
        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }

            root /root/nginx/nginx-http-flv-module-1.2.7;
            add_header 'Cache-Control' 'no-cache';
        }

        location /dash {
            root /root/nginx/nginx-http-flv-module-1.2.7;
            add_header 'Cache-Control' 'no-cache';
        }

        location /stat {
            #push和pull狀態的配置
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            root /root/nginx/nginx-http-flv-module-1.2.7; #指定stat.xsl的位置
        }

        #若是須要JSON風格的stat, 不用指定stat.xsl
        #可是須要指定一個新的配置項rtmp_stat_format

        #location /stat {
        #    rtmp_stat all;
        #    rtmp_stat_format json;
        #}

        location /control {
            rtmp_control all; #rtmp控制模塊的配置
        }
    }
}

rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /root/nginx/nginx-http-flv-module-1.2.7;

rtmp {
    out_queue           4096;
    out_cork            8;
    max_streams         128;
    timeout             30s;
    drop_idle_publisher 30s;

    log_interval 5s; #log模塊在access.log中記錄日誌的間隔時間,對調試很是有用
    log_size     1m; #log模塊用來記錄日誌的緩衝區大小

    server {
        listen 1935;//自定義 rtmp 端口
       # server_name www.test.*; #用於虛擬主機名後綴通配

        application devyk {
            live on;
            gop_cache on; #打開GOP緩存,減小首屏等待時間
        }

        application hls {
            live on;
            hls on;
            hls_path /root/nginx/nginx-http-flv-module-1.2.7/hls;
        }

        application dash {
            live on;
            dash on;
            dash_path /root/nginx/nginx-http-flv-module-1.2.7/dash;
        }
    }
	
		#能夠有多個 server 配置
}

複製代碼

Nginx 配置文件詳解請看該篇文章

nginx-rtmp-module配置指令詳解

在根目錄輸入 bin/sbin/nginx -t , 如出現以下就說明配置成功。

6. 開啓 nginx 服務

#開啓服務
bin/sbin/nginx
 #中止服務
bin/sbin/nginx -s stop
 #重啓服務
bin/sbin/nginx -s reload
複製代碼

7. 網頁測試是否都顯示正常

  1. 直接在網頁上輸入: http://ip:port,若是出現以下,證實首頁和基本配置沒有問題了

  1. 直接在網頁輸入: http://ip:port/stat 如出現以下監控頁面,說明監控頁面一切正常。

如今服務器搭建完成,下面能夠進入測試環節了。

rtmp 推流

咱們直接用開源 obs-studio 軟件進行推流,據說不少遊戲主播也用該款推流軟件。

推流源設置:

如上圖所示,證實已經推流成功了,下面咱們就來測試拉流。

拉流

flv 在 Html5 上播放

注意: 其它播放也是以下格式,這裏只是以 Html 舉例說明:

例子:

假設在http配置塊中的listen配置項是:

http {
    ...
    server {
        listen 8080; #不是默認的80端口
        ...

        location /live {
            flv_live on;
        }
    }
}
複製代碼

rtmp配置塊中的listen配置項是:

rtmp {
    ...
    server {
        listen 1935; #也能夠不是默認的1935端口
        ...

        application myapp {
            live on;
        }
    }
}


複製代碼

而且發佈的流的名稱是mystream,那麼基於 HTTP-FLV 的播放url是:

http://ip:8080/flv?port=1935&app=myapp&stream=mystream

複製代碼

播放器這裏選擇 bilibili 開源的 flv.js , 既然咱們已經有服務器了,那就直接把 flv.js 項目部署在服務器上吧

  1. 安裝 npm
#安裝 npm
yum install npm
#檢查是否安裝成功,若有輸出證實安裝成功
npm --version

複製代碼
  1. 直接下載 flv.js 到服務器上
#經過 wget 下載
wget https://github.com/bilibili/flv.js/archive/v1.5.0.tar.gz
#解壓
tar -zxvf v1.5.0.tar.gz

複製代碼
  1. 安裝

進入 flv.js 根目錄直接輸入 npm install 命令,安裝完成以後會出現一個 node_modules 模塊

  1. 安裝生成工具

仍是在當前根目錄下安裝,輸入以下命令:

npm install -g gulp

複製代碼
  1. 包裝和最小化 js 放入 dist 文件夾中
#輸入以下命令
gulp release

複製代碼

這一步執行完成以後會生成以下文件:

  1. 修改 demo 提供的播放頁面

將 demo 中 2 個文件(.ccs,.js) copy 到 dist 文件下,並修改 html 中 flv.js 路徑,以下所示:

最後將 dist 文件夾重命名 flvjsplay

  1. 部署

nginx.conf 配置網頁加載路徑:

location /flvjsplay {//測試地址
					root /root/nginx/flv.js-1.5.0;
					index index.html;#flv.js 測試播放首頁
				}

複製代碼

修改了配置文件須要在 nginx 根目錄輸入以下指令,對 nginx 服務器重啓:

#從新啓動
bin/sbin/nginx -s reload
複製代碼
  1. chrome 加載播放

左邊是拉流,右邊是推流

能夠看到首屏加載速度仍是比較快延遲在 2-5s 之間,畫面延遲有點高跟我服務器和網絡有關。

VLC rtmp 拉流播放

VLC 點擊文件->打開網絡輸入 rtmp 拉流地址點擊播放

//配置rtmp 拉流格式
//ip:host
//rtmpPost:rtmp 服務的端口
//appname 配置在rtmp application 的名稱
//streamname:推流的時候填寫的密碼
rtmp://ip:rtmpPort/appname/streamname
複製代碼

左邊是拉流,右邊是推流

http-hls 播放

播放格式:

http://ip:port/hls/streamname.m3u8
複製代碼

由於筆者不是作 H5 開發的,因此對瀏覽器播放 HLS 直播流兼容性不是太清楚,我就直接使用 video 標籤在我電腦上用 chrome 瀏覽器測試, 結果是播放不出來的,查了資料好像說是原生 video 標籤僅支持 MP四、WebM、Ogg 格式,那這怎麼辦呢?其實能夠直接使用開源項目來解決的,好比 video.jsvideojs-contrib-hls 等,我這裏直接使用的是 videojs-contrib-hls ,目前測試在 Android 瀏覽器、PC 谷歌瀏覽器 、IOS 微信、IOS Safari 瀏覽器 均已成功,下面是 Html 代碼,以下所示:

<html>
    <head>
        <meta charset="utf-8" />
        <title>Player</title>
        <link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
    </head>
 
    <body>
        <video id="video" class="video-js vjs-default-skin" controls autoplay="autoplay" width="640" height="320" data-setup='{}'>
          //換成你本身的直播連接
            <source src="http://ip:8082/hls/live1.m3u8" type="application/x-mpegURL" />
        </video>
 
        <script src="https://unpkg.com/video.js/dist/video.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-hls/5.12.1/videojs-contrib-hls.min.js"></script>
    </body>
</html>
複製代碼

注意:在這兒使用的 js 等資源皆是在線的一些支持。若須要在項目中使用,最好下載到本地使用

爲了測試方便,我也直接把該 Html 代碼部署到了雲服務器中,nginx.conf 配置以下:

location /hlsplay {
    root /root/nginx/nginx-http-flv-module-1.2.7/hls;
    index hlsplay.html; //指定首頁,也就是咱們播放的頁面,hlsplay.html 就是上面代碼。
}
複製代碼

重啓 nginx 服務器以後,直接輸入 http://ip:port/hlsplay 就能夠播放了,測試效果以下圖:

VLC rtmp 、flv.js Http-Flv 、android rtmp 三端同時拉流測試

總結

到這裏您已經成功搭建直播服務器了,雖說該篇文章沒有敲任何的代碼,也許你會說沒有學到什麼,可是搭建服務器和部署一套簡易直播環境這個過程也都是值得咱們做爲一個移動或者前端開發者學習的。

參考

感謝

相關文章
相關標籤/搜索