視頻直播(一)CentOS 7上安裝nginx與nginx-RTMP


## 00 直播的技術點是什麼?什麼是RTMP?


疫情降臨,帶動了一大批網課APP。


在線教育的賽道又添了一把火。


那在線直播的技術點有什麼?通過什麼技術棧實現呢?


目前我們常用的直播通訊協議有幾個:RTMP、HLS、HTTP-FLV,RTMP主要是PC端,HLS則是蘋果公司基於 HTTP 的流媒體傳輸協議,也兼容Android、H5,所以現在手機端基本都是用HLS。


直播分爲推流和拉流兩個過程,推就是我們向服務器推送數據流,拉就是從服務器上拉取數據流到本地來。


今天我們主要講解如何部署Nginx服務器,並配置視頻模塊(nginx-rtmp-module),來搞定視頻流和實時流的推拉。


噹噹,有請今天的主角RTMP登場。


RTMP是什麼?其全稱Routing Table Maintenance Protocol,即實時消息協議,是一種高性能協議。


用於在基於Flash的平臺技術之間通過Internet傳輸數據,音頻和視頻。最初由Macromedia開發,現在由Adobe擁有。


Nginx RTMP是基於Nginx的媒體流媒體,具有RTMP,HLS和MPEG-DASH實時流媒體。Nginx RTMP模塊具有很多功能,包括H264 / AAC支持,HTTP回調支持,用於記錄音頻/視頻的HTTP控制模塊等。


在本章中,我們將使用最新的CentOS 7服務器,安裝nginx和rtmp模塊的配置,以及按需創建RTMP實時流和視頻。


## 01 我們要做些什麼?


1、安裝依賴項;


2、下載帶有其他軟件包和RTMP模塊的Nginx;


3、編譯Nginx並從源代碼安裝;


4、將Nginx配置爲服務;


5、配置Nginx RTMP模塊;


6、設置第一個RTMP實時流。


## 02 下載軟件包


首先,我們將從源代碼構建Nginx Web服務器,所以需要安裝所需的所有軟件包依賴項,包括開發工具,EPEL存儲庫和其他軟件包。


    # 安裝CentOS的“開發工具”

    sudo yum -y groupinstall 'Development Tools'

    

    # 添加EPEL存儲庫

    sudo yum -y install epel-release

    

    # 安裝nginx依賴項

    sudo yum install -y  wget git unzip perl perl-devel perl-ExtUtils-Embed libxslt libxslt-devel libxml2 libxml2-devel gd gd-devel pcre-devel GeoIP GeoIP-devel


然後,我們將下載帶有其他依賴項的nginx源代碼,包括pcre,zlib和OpenSSL。


    cd /usr/local/src

    

    # 下載Nginx 1.14.0並將其解壓縮

    wget https://nginx.org/download/nginx-1.14.0.tar.gz

    

    # 解壓nginx

    tar -xzvf nginx-1.14.0.tar.gz

    

    # 下載pcre

    wget https://ftp.pcre.org/pub/pcre/pcre-8.42.zip

    

    # 解壓pcre

    unzip pcre-8.42.zip

    

    # 下載zlib

    wget https://www.zlib.net/zlib-1.2.11.tar.gz

    

    # 解壓zlib

    tar -xzvf zlib-1.2.11.tar.gz

    

    # 下載openssl

    wget https://www.openssl.org/source/openssl-1.1.0h.tar.gz

    

    # 解壓openssl

    tar -xzvf openssl-1.1.0h.tar.gz

    

重頭戲來了。


    # 克隆nginx-RTMP模塊

    git clone https://github.com/sergey-dryabzhinsky/nginx-rtmp-module.git

    

    # 刪除多餘文件

    rm -f *.tar.gz *.zip

    

    # 查看目錄下文件

    ls -lah

    

## 03 編譯安裝nginx及RTMP模塊


    cd nginx-1.14.0/

    

使用以下參數配置nginx


    ./configure --prefix=/etc/nginx \

            --sbin-path=/usr/sbin/nginx \

            --modules-path=/usr/lib64/nginx/modules \

            --conf-path=/etc/nginx/nginx.conf \

            --error-log-path=/var/log/nginx/error.log \

            --pid-path=/var/run/nginx.pid \

            --lock-path=/var/run/nginx.lock \

            --user=nginx \

            --group=nginx \

            --build=CentOS \

            --builddir=nginx-1.14.0 \

            --with-select_module \

            --with-poll_module \

            --with-threads \

            --with-file-aio \

            --with-http_ssl_module \

            --with-http_v2_module \

            --with-http_realip_module \

            --with-http_addition_module \

            --with-http_xslt_module=dynamic \

            --with-http_image_filter_module=dynamic \

            --with-http_geoip_module=dynamic \

            --with-http_sub_module \

            --with-http_dav_module \

            --with-http_flv_module \

            --with-http_mp4_module \

            --with-http_gunzip_module \

            --with-http_gzip_static_module \

            --with-http_auth_request_module \

            --with-http_random_index_module \

            --with-http_secure_link_module \

            --with-http_degradation_module \

            --with-http_slice_module \

            --with-http_stub_status_module \

            --http-log-path=/var/log/nginx/access.log \

            --http-client-body-temp-path=/var/cache/nginx/client_temp \

            --http-proxy-temp-path=/var/cache/nginx/proxy_temp \

            --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \

            --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \

            --http-scgi-temp-path=/var/cache/nginx/scgi_temp \

            --with-mail=dynamic \

            --with-mail_ssl_module \

            --with-stream=dynamic \

            --with-stream_ssl_module \

            --with-stream_realip_module \

            --with-stream_geoip_module=dynamic \

            --with-stream_ssl_preread_module \

            --with-compat \

            --with-pcre=../pcre-8.42 \

            --with-pcre-jit \

            --with-zlib=../zlib-1.2.11 \

            --with-openssl=../openssl-1.1.0h \

            --with-openssl-opt=no-nextprotoneg \

            --add-module=../nginx-rtmp-module \

            --with-debug;

            

編譯並安裝:


    sudo make;sudo make install;

    

安裝完成後,我們需要創建一個新的symlink模塊目錄,創建一個新的nginx用戶和組,並創建一個新的nginx緩存目錄。


    # 創建軟連接

    sudo ln -s /usr/lib64/nginx/modules /etc/nginx/modules

    

    # 創建nginx系統用戶和組

    sudo useradd -r -d /var/cache/nginx/ -s /sbin/nologin -U nginx

    

    # 創建一個新的Nginx緩存目錄“/var/cache/nginx”,並將目錄所有者更改爲“nginx”用戶和組

    mkdir -p /var/cache/nginx/

    chown -R nginx:nginx /var/cache/nginx/

    

    # 測試nginx配置和已安裝的nginx版本

    nginx -t

    nginx -V

    

展示內容如下:


    [root@hostone nginx-1.14.0]# nginx -t

    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

    nginx: configuration file /etc/nginx/nginx.conf test is successful

    [root@hostone nginx-1.14.0]# nginx -V

    nginx version: nginx/1.14.0 (CentOS)

    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) 

    built with OpenSSL 1.1.0h  27 Mar 2018

    TLS SNI support enabled

    configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --build=CentOS --builddir=nginx-1.14.0 --with-select_module --with-poll_module --with-threads --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-stream_ssl_preread_module --with-compat --with-pcre=../pcre-8.42 --with-pcre-jit --with-zlib=../zlib-1.2.11 --with-openssl=../openssl-1.1.0h --with-openssl-opt=no-nextprotoneg --add-module=../nginx-rtmp-module --with-debug

    

Nginx Web服務器已安裝在啓用了RTMP模塊的CentOS 7上。


接下來,我們爲nginx配置服務。


## 04 配置nginx服務


在systemd服務目錄中創建一個新的nginx服務文件。


    cd /lib/systemd/system/

    vim nginx.service


配置如下;


    [Unit]

    Description=nginx - high performance web server

    Documentation=https://nginx.org/en/docs/

    After=network-online.target remote-fs.target nss-lookup.target

    Wants=network-online.target

    

    [Service]

    Type=forking

    PIDFile=/var/run/nginx.pid

    ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf

    ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf

    ExecReload=/bin/kill -s HUP $MAINPID

    ExecStop=/bin/kill -s TERM $MAINPID

    

    [Install]

    WantedBy=multi-user.target



顯示如下,說明啓動成功。


    [root@hostone system]# systemctl enable nginx

    Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.


## 05 配置Nginx RTMP模塊


在這裏,我們爲RTMP模塊單獨創建一個conf文件。


進入nginx目錄,備份原來的conf,創建新的nginx 配置文件。


    cd /etc/nginx/

    mv nginx.conf nginx.conf.asli

    vim nginx.conf



配置如下:


    worker_processes  auto;

    events {

        worker_connections  1024;

    }

    

    # RTMP configuration

    rtmp {

        server {

            listen 1935; # Listen on standard RTMP port

            chunk_size 4000;

    

    # Define the Application

            application show {

                live on;

                # Turn on HLS

                hls on;

                hls_path /mnt/hls/;

                hls_fragment 3;

                hls_playlist_length 60;

                # disable consuming the stream from nginx as rtmp

                deny play all;

            }

    

        }

    }

    

    http {

        sendfile off;

        tcp_nopush on;

        aio on;

        directio 512;

        default_type application/octet-stream;

    

        server {

            listen 8080;

    

            location / {

                # Disable cache

                add_header 'Cache-Control' 'no-cache';

    

                # CORS setup

                add_header 'Access-Control-Allow-Origin' '*' always;

                add_header 'Access-Control-Expose-Headers' 'Content-Length';

    

                # allow CORS preflight requests

                if ($request_method = 'OPTIONS') {

                    add_header 'Access-Control-Allow-Origin' '*';

                    add_header 'Access-Control-Max-Age' 1728000;

                    add_header 'Content-Type' 'text/plain charset=UTF-8';

                    add_header 'Content-Length' 0;

                    return 204;

                }

    

                types {

                    application/dash+xml mpd;

                    application/vnd.apple.mpegurl m3u8;

                    video/mp2t ts;

                }

    

                root /mnt/;

            }

        }

    }


接着,我們需要爲HLS配置創建一個新目錄,並且我們已經定義了Web根目錄在'/mnt'目錄中。


    mkdir -p /mnt/hls

    chown -R nginx:nginx /mnt/hls

    

    

    nginx -t

    systemctl restart nginx

    

出現報錯:


    Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.

    

使用命令查看報錯信息:


    # 查看nginx運行狀態

    systemctl status nginx

    

信息如下:


    Feb 16 12:29:58 hostone nginx[29459]: nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use)

    Feb 16 12:29:59 hostone nginx[29459]: nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use)

    Feb 16 12:29:59 hostone nginx[29459]: nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use)

    Feb 16 12:30:00 hostone nginx[29459]: nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use)

    Feb 16 12:30:00 hostone nginx[29459]: nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use)

    Feb 16 12:30:01 hostone systemd[1]: nginx.service: control process exited, code=exited status=1

    Feb 16 12:30:01 hostone nginx[29459]: nginx: [emerg] still could not bind()

    Feb 16 12:30:01 hostone systemd[1]: Failed to start nginx - high performance web server.

    Feb 16 12:30:01 hostone systemd[1]: Unit nginx.service ente

    

明顯是8080端口被佔用,換下conf中的端口。


    # 查看8081端口是否被佔用

    lsof -i:8081

    

如果沒有lsof命令,可以使用netstat或者yum install  lsof 安裝一下。


更換8080端口爲8081端口:


    vim /etc/nginx/nginx.conf


重啓nginx服務,並查看運行狀態:


    systemctl restart nginx

    systemctl status nginx


展示內容如下:


    [root@hostone nginx]# systemctl restart nginx

    [root@hostone nginx]# systemctl status nginx

    ● nginx.service - nginx - high performance web server

       Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)

       Active: active (running) since Sun 2020-02-16 12:36:25 CST; 28s ago

         Docs: https://nginx.org/en/docs/

      Process: 29628 ExecStop=/bin/kill -s TERM $MAINPID (code=exited, status=0/SUCCESS)

      Process: 29632 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)

      Process: 29631 ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)

     Main PID: 29633 (nginx)

       CGroup: /system.slice/nginx.service

               ├─29633 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf

               ├─29635 nginx: worker process

               └─29636 nginx: cache manager process

    

    Feb 16 12:36:25 hostone systemd[1]: Stopped nginx - high performance web server.

    Feb 16 12:36:25 hostone systemd[1]: Starting nginx - high performance web server...

    Feb 16 12:36:25 hostone nginx[29631]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

    Feb 16 12:36:25 hostone nginx[29631]: nginx: configuration file /etc/nginx/nginx.conf test is successful

    Feb 16 12:36:25 hostone systemd[1]: Failed to read PID from file /var/run/nginx.pid: Invalid argument

    Feb 16 12:36:25 hostone systemd[1]: Started nginx - high performance web server.


## 06 設置第一個RTMP實時流


在本章中,我們將使用OBS軟件從本地計算機廣播服務器上的MP4視頻產生的RTMP流。


編輯nginx的conf文件,


    vim /etc/nginx/nginx.conf

    

將以下內容粘貼至rtmp { ... }中


     # RTMP video on demand for mp4 files

        application vod {

            play /mnt/mp4s;

        }


        # RTMP stream using OBS

        application stream {

            live on;

        }

 

創建一個新目錄“mp4s”來存儲所有視頻,並將所有者更改爲nginx用戶組:    


    mkdir -p /mnt/mp4s

    chown -R nginx:nginx /mnt/mp4s


測試並重啓nginx:

    

    nginx -t

    systemctl restart nginx

    

## 07 測試


終於全部配置安裝完成,我們來測試下,使用VLC、OBS來播放器測試RTMP視頻流和實時流。


首先下載VLC、OBS軟件。


VLC視頻播放器官方地址:https://www.videolan.org/。


OBS(Open Broadcaster Software)官方下載地址:https://obsproject.com/welcome。


上傳個視頻到剛纔nginx的RTMP模塊vod定義的文件夾/mht/mp4s,我們的視頻名叫001.mp4(自己隨便找個)。


在本地計算機上打開VLC應用。


使用VLC,打開這個視頻,路徑爲【媒體】->【打開網絡串流】->rtmp://ip:1935/vod/001.mp4。


遇到了問題,播放流連接不通。


首先想的是,是不是防火牆有問題,從本地telnet了一下,果然不通,但檢查了下服務器,並不是防火牆問題。


然後看了下nginx的運行狀態,發下有一行錯誤被我忽略了。


    Feb 16 13:07:11 hostone systemd[1]: Failed to read PID from file /var/run/nginx.pid: Invalid argument


回到添加nginx服務的系統目錄中


    cd /usr/lib/systemd/system

    vi nginx.service 

    

需要註釋掉這一行。


    # PIDFile=/run/nginx.pid

    

重新添加服務


    # 重新加載系統服務配置

    systemctl daemon-reload

    

    # 重啓nginx

    systemctl restart nginx

    

    # 查看nginx狀態

    systemctl status nginx

    

如下:


    [root@hostone system]# systemctl status nginx

    ● nginx.service - nginx - high performance web server

       Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)

       Active: active (running) since Sun 2020-02-16 13:10:03 CST; 18s ago

         Docs: https://nginx.org/en/docs/

      Process: 30808 ExecStop=/bin/kill -s TERM $MAINPID (code=exited, status=0/SUCCESS)

      Process: 30812 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)

      Process: 30811 ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)

     Main PID: 30814 (nginx)

       CGroup: /system.slice/nginx.service

               ├─30814 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf

               ├─30815 nginx: worker process

               └─30816 nginx: cache manager process

    

    Feb 16 13:10:03 hostone systemd[1]: Stopped nginx - high performance web server.

    Feb 16 13:10:03 hostone systemd[1]: Starting nginx - high performance web server...

    Feb 16 13:10:03 hostone nginx[30811]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

    Feb 16 13:10:03 hostone nginx[30811]: nginx: configuration file /etc/nginx/nginx.conf test is successful

    Feb 16 13:10:03 hostone systemd[1]: Started nginx - high performance web server.


已經沒有那行錯誤了。


但是搞了半天發現防火牆端口開了還是不行,忽然想到是不是雲服務器廠商限制了。


找到了提供這臺機器的小夥伴,一問之下果然如此。太坑了。


用VLC重新打開rtmp://ip:1935/vod/001.mp4。


視頻流播放OK了,如圖:



接下來是實時直播流。


需要用到OBS直播軟件。


安裝完成OBS,打開後,添加場景,添加顯示器捕獲,點擊【設置】,如圖


 

    

推流設置如下:


    

    

地址爲剛纔nginx中配置的stream,rtmp://ip:1935/stream。


然後返回主頁面,點擊右下角【開始推流】、【開始錄製】。


打開VLC,還是打開網絡串流,將串流地址同樣換爲rtmp://ip:1935/stream。


可以看到,直播開始了。


不過延遲有點嚴重,大概在3秒左右;而且圖像傳輸會在某一剎那失真,估計受帶寬影響較大。


明天研究下HLS,web及直播聊天室的創建。







本文分享自微信公衆號 - 架構師之殤(ysistrue)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章