< Back to blog

How to install & tune Nginx with RTMP module and start streaming through FFmpeg with QuickSync on CentOS.

Kirill Suverov
Written byKirill Suverov
Photo by Adi Goldstein
Photo by Adi Goldstein on Unsplash

About Nginx

Nginx is an open-source web server with a lot of functions. It can be used as a load balancer, reverse proxy, mail proxy, HTTP cache, and more. In this article, we will consider Nginx as a video streaming tool. In this case, we will install compile and tune Nginx using RTMP (Real Time Messaging Protocol) module, which is mainly used for streaming video and audio streams from web cameras over the internet.

If you are facing Nginx the first time and you want to install it with RTMP module on CentOS, this tutorial is for you.

Step 1. Preparation

Before we start Nginx installation, we need to install some packages dependencies for its clear work:

sudo yum -y groupinstall 'Development Tools'
sudo yum -y install epel-release
sudo yum install openssl-devel
sudo yum install -y pcre-devel

Step 2. Installation

After installing related attributes, we need to download Nginx archive from Nginx official website: https://nginx.org/download/ (you can choose the version you want) and extract it on your CentOS machine. In this example we have chosen version 1.14.0:

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

Next, you need to clone Nginx RTMP module using git:

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

Then, go to ‘nginx-1.14.0’ directory and configure Nginx with parameters below:

cd nginx-1.14.0/./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 --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-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_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 --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_realip_module --with-stream_ssl_preread_module --with-compat --add-module=../nginx-rtmp-module --with-debug

After configuring Nginx, you need to make and install it:

sudo make
sudo make install

To check Nginx version and installed modules use:

nginx -V

Step 3. Tuning Nginx

After installing, create the module link to the Nginx directory:

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

If Nginx is going to use any folders, you need to create Nginx-user and group and change the owner and group of these folders to Nginx:

sudo useradd -r -d /var/cache/nginx/ -s /sbin/nologin -U nginx
chown -R nginx:nginx <path-to-folder-which-nginx-uses>

As we are going to run Nginx as a service, we need to create nginx.service file along this path /usr/lib/systemd/system/ with the following content (copy text below to your nginx.service file):

[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

After all these steps, you can finally start Nginx:

sudo service nginx start

If you want Nginx to run every time with system starting, you can enable it:

sudo systemctl enable nginx

Step 4. RTMP configuration

You can find Nginx working configuration in /etc/nginx/nginx.conf.

If you want to create a configuration for the RTMP module, you need to add it to nginx.conf file.

For a live streaming example:

#user  nobody;
worker_processes  1;#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;#pid        logs/nginx.pid;events {
    worker_connections  1024;
}# RTMP configuration
rtmp {
    server {
        listen 1935; # Standard port
        chunk_size 8192;
        # Application configuration
        application origin_ffmpeg_1 {
            live on;
            record off;
            meta copy;
            exec ffmpeg -i rtmp://localhost:1935/origin_ffmpeg_1/$name <parameters/libs/modules> rtmp://localhost:1935/live_ffmpeg_1/$name_1;
        }        application live_ffmpeg_1 {
            live on;
            record off;
        }
    }
}

After you have changed anything in nginx.conf file, to apply your changes you always need to restart Nginx:

sudo systemctl restart nginx

That how we successfully completed Nginx installation & tuning with RTMP module on CentOS machine.

Step 5. Installing MSDK

Now we need to install Intel MediaSDK to build ffmpeg with QuickSync. First of all, you need to clone Intel MediaSDK from github:

git clone https://github.com/Intel-Media-SDK/MediaSDK.git msdk

After that, you have to go to the cloned project directory and build it:

cd msdk/ && mkdir build && cd build && cmake .. && make

After building MSDK in msdk/build/__bin/release there will appear libmfx.pc file, which is needed for building FFmpeg with QuickSync. You need to return to your working directory (where msdk folder is located) and export PKG_CONFIG_PATH to folder with libmfx.pc file:

export PKG_CONFIG_PATH=./msdk/build/__bin/release

Step 6. Installing FFmpeg

Now, you can clone FFmpeg project:

git clone https://github.com/FFmpeg/FFmpeg.git ffmpeg
cd ffmpeg

When you clone FFmpeg, you need to configure it using the options below:

./configure — enable-libmfx — enable-nonfree

After successful configuration, you can see h264_qsv option in logs. It means, that FFmpeg found QuickSync and configured with it. Now you can make and install FFmpeg:

sudo make && sudo make install

After installing FFmpeg, check FFmpeg installed components: --enable-libmfx means that QuickSync installed successfully:

QuickSync installed successfully
QuickSync installed successfully

Step 7. Installing Media Driver

If you don’t have Media Driver (iHD_drv_video.so) installed on your computer or your driver version is not suitable to run FFmpeg (you can go to step 8, and if it has problem with a driver, return to step 7), you need to build it because it is necessary to run FFmpeg. First of all, you need to install master branches of Libva and GmmLib from github.

After that, you need to clone Intel Media Driver project from github:

git clone https://github.com/intel/media-driver.git

Then, you need to go to the driver’s folder, create a folder for a build, and make it:

cd media-driver && mkdir build && cd build/ && cmake .. && make

Finally, you will get iHD_drv_video.so file and now you need to specify LIBVA environmental variables:

export LIBVA_DRIVERS_PATH=/path/to/iHD_drv_video.so/
export LIBVA_DRIVERS_NAME=iHD

Step 8. Launch FFmpeg through Nginx

Now you can move on to integrate FFmpeg into Nginx. You need to edit your nginx.conf file and use FFmpeg with QuickSync as executing command. In this example I will add some parameters for transcoding and dump all FFmpeg logs to /home/tmp (Nginx is owner and group of tmp folder — step 3):

rtmp {
    server {
        listen 1935; # Standard port
        chunk_size 8192;
        # Application configuration
        application origin_qsv_1 {
            live on;
            record off;
            meta copy;
            exec ffmpeg -hwaccel qsv -c:v h264_qsv -i rtmp://localhost:1935/origin_qsv_1/$name -map 0 -c:v h264_qsv -profile:v baseline -preset medium -b:v 1000K -f flv -c:a copy -f flv rtmp://localhost:1935/live_qsv_1/$name_1 2>>/home/tmp/ffmpeg_1;
        }        application origin_qsv_2 {
            live on;
            record off;
            meta copy;
            exec ffmpeg -hwaccel qsv -c:v h264_qsv -i rtmp://localhost:1935/origin_qsv_2/$name -map 0 -c:v h264_qsv -profile:v baseline -preset medium -b:v 1000K -f flv -c:a copy -f flv rtmp://localhost:1935/live_qsv_2/$name_2 2>>/home/tmp/ffmpeg_2;
        }        application live_qsv_1 {
            live on;
            record off;
        }
        application live_qsv_2 {
            live on;
            record off;
        }
    }
}

Save and exit.

After this, you can launch broadcasting using Nginx. Choose the stream you want to transcode and start:

ffmpeg -re -i /path/to/stream/stream.mp4 -map 0 -c copy -f flv rtmp://localhost/origin_qsv_1/mystream

*NB:* You can vary both the number of parallel sessions and the number of outputs for each session. Here is an example to add one more output:

ffmpeg -re -i /path/to/stream/stream.mp4 -map 0 -c copy -f flv rtmp://localhost/origin_qsv_1/mystream -map 0 -c copy -f flv rtmp://localhost/origin_qsv_2/mystream

*P.S.* If you have a driver’s problem, please return to step 7. If you have already completed step 7, and the problem is not solved, add LIBVA_DRIVERS_PATH to nginx.conf file (make sure that Nginx has permissions to use iHD driver from the directory where it is located):

env LIBVA_DRIVERS_PATH=/path/to/iHD/driver;

Step 9. Visual check that transcoding works in broadcasting

Before launching the transcoding, you can run FFplay to see, what will be in your output. For this, you need to choose the output you want to see and add it to FFplay. For example, you want to see output stream from 1st application (instead of $name variable you need to substitute the name of your output stream from launching FFmpeg, for example, mystream):

ffplay -v debug rtmp://localhost:1935/live_qsv_1in1_1/mystream_1_750

After starting FFplay, you will see something like this:

After starting FFplay
After starting FFplay

This means, that FFplay is waiting for the data. You can start streaming like we did in step 7:

ffmpeg -re -i /path/to/stream/stream.mp4 -map 0 -c copy -f flv rtmp://localhost/origin_qsv_1/mystream

After that, FFplay starts playback the transcoded stream, if everything is ok:

big buck bunny stream
big buck bunny stream

big_buck_bunny stream from https://peach.blender.org/

And in ffmpeg logs (which we have sent to /home/tmp), when you open of logs file, you will see something like this:

in ffmpeg logs
in ffmpeg logs

It means, that FFmpeg with QuickSync is working correctly and is transcoding your stream before broadcast.