使用Nginx搭建流媒體伺服器

Naylor發表於2024-12-03

目錄
  • 什麼是流媒體伺服器
  • Nginx如何實現流媒體伺服器
  • 為Nginx安裝nginx-http-flv-module
    • 概述
    • 流程
    • 操作步驟
  • 配置流媒體伺服器
  • 使用OBS推流
  • 使用VLC拉RTMP
  • 使用flv.js拉流
  • 使用jls.js拉m3u8
  • 總結
  • 引用

什麼是流媒體伺服器

流媒體伺服器(Streaming Media Server)是一種用於儲存和傳輸音訊、影片、直播等媒體內容的伺服器軟體。它透過網路將媒體檔案實時傳輸給使用者,而不需要使用者先下載完整檔案。流媒體伺服器支援按需播放、實時廣播等功能,常見的使用場景包括線上影片、音訊點播、直播影片等。

影片流媒體資料傳輸往往對流媒體伺服器編解碼能力和協議轉換有要求,因為不同的編碼格式和不同的協議適用的場景不同。例如,RTMP協議延遲低,但是web瀏覽器不支援,需要將其轉為HLS或者是FLV才能進行播放。

Nginx如何實現流媒體伺服器

Nginx作為web伺服器的一種,本身關注點在靜態資源代理、正反向代理方面,實現作為流媒體伺服器使用是依賴“外掛”來擴充套件。例如:nginx-rtmp-module外掛和nginx-http-flv-module外掛。

為Nginx安裝nginx-http-flv-module

概述

nginx中的模組雖然就是類似外掛的概念,但是它無法像VsCode那樣輕鬆的安裝擴充套件。針對像 nginx-http-flv-module 這樣的 nginx 模組,僅能透過重新編譯 nginx 原始碼的方式完成“外掛的安裝”。

nginx-http-flv-module 基於 nginx-rtmp-module 二次開發,擁有 nginx-rtmp-module 全部的功能,同時具備HTTP-FLV播放,這個功能就很Nice,有了這個就可以實現在瀏覽器中觀看直播,針對推送端無需額外的配置,一個直播流推送到流媒體伺服器,直接可以輸出多種流,包括:rtmp、hls、flv,rtmp用於在桌面應用程式中播放,hls和flv用於在瀏覽器中播放,當然hls也可以在桌面應用程式中播放,在瀏覽器播放方式中flv的畫面延遲明顯由於hls。

需要注意的是 nginx-http-flv-module 要求nginx的版本大於等於1.2.6。由於nginx-http-flv-module包含了 nginx-rtmp-module 模組,所以不可將 nginx-http-flv-module 和 nginx-rtmp-module 同時編譯,當我們編譯完 nginx-http-flv-module 之後,其實就已經擁有了 nginx-rtmp-module 的完整功能。

流程

  • 檢視當前nginx 的版本(假設安裝位置為:/usr/local/nginx)
  • 下載當前版本nginx的原始碼
  • 下載 nginx-http-flv-module 模組原始碼
  • 重新編譯nginx並追加nginx-http-flv-module
  • 將新編譯好的 nginx 可執行檔案複製到當前nginx安裝目錄(/usr/local/nginx/sbin)

操作步驟

使用如下命令檢視當前已經安裝的nginx的版本


[root@bogon sbin]# ./nginx -V nginx version: nginx/1.18.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017 TLS SNI support enabled configure arguments: --prefix=/usr/local/nginx --with-http_dav_module --with-http_stub_status_module --with-http_addition_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre --with-http_ssl_module --with-http_gzip_static_module


  • V:小v僅列印版本號,大V既列印版本號,也列印擴充套件資訊,這裡要使用大V

  • 拿到版本號的目的是待會要下載該版本的原始碼

  • 注意儲存列印內容中的 arguments 後面的內容,後面編譯會用到

下載 nginx 原始碼和 nginx-http-flv-module 的原始碼,示例程式碼如下:


wget http://nginx.org/download/nginx-1.18.0.tar.gz tar -zxvf nginx-1.18.0.tar.gz git clone https://github.com/winshining/nginx-http-flv-module.git


進入nginx原始碼目錄,使用如下命令重新編譯nginx:


./configure --prefix=/usr/local/nginx --with-http_dav_module --with-http_stub_status_module --with-http_addition_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre --with-http_ssl_module --with-http_gzip_static_module --add-module=/home/cml/nginx-http-flv-module make


  • 使用configure 配置編譯環境
  • 將上面 儲存的“arguments 後面的內容”作為configure 的第一個引數
  • 第二個引數為 --add-module=/home/cml/nginx-http-flv-module ,即新增一個模組,模組原始碼位置是 /home/cml/nginx-http-flv-module
  • 使用make命令執行編譯編譯

編譯成功後,在 objs中會有一個 名為nginx的可執行檔案,這個就是編譯好的nginx了, 裡面包含已經安裝的功能和新增加的nginx-rtmp-module,將這個可執行檔案複製到當前安裝目錄(/usr/local/nginx/sbin)中就可以了。

注意複製之前需要停止nginx,否則會報當前檔案繁忙,無法覆蓋的錯誤。

透過如下命令驗證安裝是否正常:


nginx -V


若列印的資訊中包含nginx-http-flv-module,說明安裝好了。

配置流媒體伺服器

當安裝好了 nginx-http-flv-module 之後,就可以建立流媒體應用了。所謂的建立流媒體應用其實就是編寫 nginx 的配置檔案,如果需要建立一個名為 live 的流媒體應用,那麼可以在 nginx.conf 中做如下配置



#以下內容放可在 nginx.conf 的最後,rtmp 配置塊為頂級配置塊
rtmp_auto_push on ;

rtmp {
   server {
        listen 1935; #監聽的埠
        notify_method get;
        chunk_size 4000;
        application live { #rtmp推流請求路徑
            live on;
            # 新增 hls 支援
            hls on;
            hls_path /usr/local/nginx/html/hls;
            hls_fragment 3;
            hls_playlist_length 60;

            # 允許從任何源push 流
            allow publish  all ;
            # 允許從任何地方來播放流
            allow play all;
            # 20s內沒有push,就斷開連線
            drop_idle_publisher 20s ;
        }
 }
}

  • listen 1935:指定流媒體伺服器的執行埠
  • live :為流媒體應用的應用的名稱,也即流媒體應用的唯一標識
  • live on : 新增直播的支援
  • hls_path:指定生成的m3u8檔案的位置

之後就是建立http-flv端點和hls端點了,目的是讓直播流可以在http協議上面傳輸直播畫面。
若不建立,將僅可以使用rtmp協議拉流,即rtmp://ip:1935/live/stream_no;若建立了就可以使用hls或者flvjs來拉流播放了。

建立http-flv端點和hls端點同樣是編輯nginx.conf來實現,如下示例配置:



 server {
        listen  82;
        server_name  rtmpserver;

        # 建立hls端點
        location /hls {
            add_header 'Access-Control-Allow-Origin' '*' ;
            add_header 'Access-Control-Allow-Credentials' 'true' ;
            types {
                application/vnd.apple.mpegurl m3u8 ;
                video/mp2t ts;
            }
            alias /usr/local/nginx/html/hls;
            expires -1 ;
            add_header 'Cache-Control' 'no-cache';
        }

        # 建立 flv 端點
        location /flv {
                flv_live on ;
                chunked_transfer_encoding on;
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Credentials' 'true';
        }
    }



  • listen 82 :指定 hls端點和flv端點的監聽埠,此埠可以自定義,針對hls端點和flv端點可以分開設定不同的監聽埠
  • hls端點的標識為 hls,此標識可以自定義,拉流的時候會用到
  • alias:指定m3u8檔案的訪問路徑,需要和 "建立流媒體應用"中的hls_path配置保持一致
  • flv端點的標識為flv,此標識可以自定義,拉流的時候會用到

使用OBS推流

OBS 是非常成熟的軟體了,安裝參考官網:https://obsproject.com/

假設約定的推拉流地址為 rtmp://192.168.1.115:1935/live/room-1

設定直播流來源為 影片採集裝置 和 瀏覽器,其中影片採集裝置就是筆記本的攝像頭,瀏覽器為OBS內建瀏覽器並開啟 https://time.is/zh/ 這個網址。最終的直播畫面就是兩個採集終端的畫面疊加在一起,底部是一個網址,網頁中有一個時鐘,頂部是攝像頭。

設定直播伺服器和推流碼:

  • 伺服器:即流媒體應用的地址,即 rtmp://192.168.1.115:1935/live
  • 推流碼:即當前推流唯一標識,可以隨意指定,保證推拉流地址一致即可,示例為: room-1

點選開始直播,OBS就開始向流媒體伺服器推流了。

此時就可以使用拉流客戶端拉取直播畫面了,同時hls_path 下將生成m3u8檔案,檔名稱為 room-1.m3u8。

使用VLC拉RTMP

VLC是非常成熟的軟體了,安裝參考官網。

VLC拉流使用rtmp進行,拉流地址為:


rtmp://192.168.1.115:1935/live/room-1

使用flv.js拉流

基於flv.js編寫一個影片播放器,新建一個html檔案,示例程式碼如下:

flvjs_player.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>FLV.js Example</title>
    <script src="https://cdn.jsdelivr.net/npm/flv.js@1.5.0/dist/flv.min.js"></script>
</head>
<body>
    <h1>FLV.js Player</h1>
    <video id="videoElement" width="640" height="360" controls></video>
    <button id="playButton">Click to Play Video</button>
    <script>
        // Check if the browser supports FLV.js
        if (flvjs.isSupported()) {
            var videoElement = document.getElementById('videoElement');
            var flvPlayer = flvjs.createPlayer({
                type: 'flv',
                url: 'http://192.168.1.115:82/flv?port=1935&app=live&stream=room-1'  // Replace with your FLV video URL
            });
            flvPlayer.attachMediaElement(videoElement);
            flvPlayer.load();
            // Play video on button click
            document.getElementById('playButton').addEventListener('click', function() {
                flvPlayer.play().catch(function(error) {
                    console.error('Error playing video:', error);
                });
            });
        } else {
            console.error('FLV.js is not supported in this browser.');
        }
    </script>
</body>
</html>


使用jls.js拉m3u8

基於hls.js編寫一個影片播放器,新建一個html檔案,示例程式碼如下:

m3u8_play.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HLS.js Example</title>
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
</head>
<body>
    <h1>HLS.js Player</h1>
    <video id="videoElement" width="640" height="360" controls></video>
    <script>
        var video = document.getElementById('videoElement');
       
        // 檢查瀏覽器是否支援 HLS.js
        if (Hls.isSupported()) {
            var hls = new Hls();
            // 載入並播放 .m3u8 檔案
            hls.loadSource('http://192.168.1.115:82/hls/room-1.m3u8');  // 替換為你的 .m3u8 URL
            hls.attachMedia(video);
           
            hls.on(Hls.Events.MANIFEST_PARSED, function() {
                video.play();  // 載入後自動播放
            });
            hls.on(Hls.Events.ERROR, function(event, data) {
                if (data.fatal) {
                    switch (data.fatal) {
                        case Hls.ErrorTypes.NETWORK_ERROR:
                            console.error("網路錯誤");
                            break;
                        case Hls.ErrorTypes.MEDIA_ERROR:
                            console.error("媒體錯誤");
                            break;
                        case Hls.ErrorTypes.OTHER_ERROR:
                            console.error("其他錯誤");
                            break;
                        default:
                            console.error("無法播放影片");
                            break;
                    }
                }
            });
        } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
            // 如果瀏覽器原生支援 HLS(例如 Safari),直接播放
            video.src = 'http://192.168.1.92:82/hls/room-1.m3u8';
            video.play();
        } else {
            console.error('HLS.js 不支援此瀏覽器');
        }
    </script>
</body>
</html>


總結

本文介紹了流媒體伺服器的特性及各種流媒體傳輸協議的適用場景,並詳細闡述了使用 nginx-http-flv-module 擴充套件Nginx作為流媒體伺服器的詳細步驟,並提供了在VLC,flv.js,hls.js下的流媒體拉流播放示例。

引用

https://www.cnblogs.com/Naylor/p/18427309

https://www.cnblogs.com/Naylor/p/18070157

https://www.cnblogs.com/Naylor/p/18070047

相關文章