We can build a Streaming Server that supports adaptive bitrate feature using Nginx. For this, we need to use nginx-rtmp-module
and also build the Nginx from source. This tutorial will help you to build a streaming server from scratch.
Check Prerequisite
- Ubuntu Server. I tried to build this streaming server in Ubuntu 20.04, but I believe that you can also build this in Ubuntu 18.04 with no problem.
Get Sudo Privileges
Before starting, make sure that we have no permission issue on the installation & configuration.
sudo su
Install Nginx Dependencies
To build Nginx from source, we need some dependencies. Run this command to install them
apt update && apt install build-essential git libpcre3-dev libssl-dev zlib1g-dev
Download Nginx Source Code
Before you download the Nginx source code, you can visit http://nginx.org/en/download.html to see the Nginx version available now. After that you can download them by running this command:
wget http://nginx.org/download/nginx-<version>.tar.gz
Now, the latest stable version is 1.20.2
, so for me, I will download the nginx-1.20.2
version
wget http://nginx.org/download/nginx-1.20.2.tar.gz
Extract the downloaded file
tar -zxvf nginx-1.20.2.tar.gz
You will get a folder named nginx-1.20.2
Download RTMP Module
We need 3rd party RTMP module to build this streaming server, you can visit the Github here: https://github.com/arut/nginx-rtmp-module. Now, the latest version is 1.22.2
, run this command to clone the latest version of the module.
wget https://codeload.github.com/arut/nginx-rtmp-module/tar.gz/refs/tags/v1.2.2
Extract the downloaded file
tar -zxvf v1.2.2
You will get a folder named nginx-rtmp-module-1.2.2
. Make sure this folder is at the same location with the nginx-1.20.2
folder.
Build & Install Nginx
Go to the nginx-1.20.2
folder
cd nginx-1.20.2
After that, we configure the nginx and put in the nginx-rtmp-module
to nginx
./configure \ --prefix=/etc/nginx \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --pid-path=/run/nginx.pid \ --sbin-path=/usr/sbin/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_stub_status_module \ --with-http_realip_module \ --with-file-aio \ --with-threads \ --with-stream \ --add-module=../nginx-rtmp-module-1.2.2
After that, run this command to build & install the nginx
make && make install
To verify the installation, you can check the Nginx version
nginx -V
Streaming Server Configuration
First, move our work directory to the Nginx configuration folder
cd /etc/nginx
Backup the default Nginx configuration file
mv nginx.conf nginx.conf.old
Create a new configuration file
nano nginx.conf
Add this configuration to the configuration file
user www-data;
worker_processes auto;
worker_rlimit_nofile 8192;
pid /run/nginx.pid;
rtmp_auto_push on;
events {
worker_connections 4096;
}
rtmp {
server {
listen 1935;
chunk_size 4096;
max_message 1M;
application streaming {
live on;
hls on;
hls_nested on;
hls_path /etc/nginx/live;
hls_fragment 6s;
hls_playlist_length 30s;
}
}
}
http {
server {
listen 8080;
root /etc/nginx;
location /live {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
add_header Cache-Control no-cache;
}
}
}
This is a simple streaming server configuration that receives rtmp video feed on port 1935
(default rtmp port) with /streaming
path, transcode them to HLS inside /etc/nginx/live
folder, and then the http
block read the m3u8
and ts
file inside /etc/nginx/live
folder and serve them on port 8080
.
Some values you can modify:
max_message 1M
, this is the size of 1 chunk of rtmp feed video. You need to increase this value especially if you have4k
or more rtmp feed video.hls_fragment 6s
, this is tell the Nginx to divide the rtmp video to6s
hls fragment video. This mean each of the.ts
video will have6s
duration. If you want a smaller fragment, you can change it to3s
.hls_playlist_length 30s
, this will affect theindex.m3u8
created by the Nginx. This is the length of 1 playlist defined in theindex.m3u8
. Now, because thehls_playlist_length
is30s
and thehls_fragment
is6s
, then theindex.m3u8
will contain 5.ts
video. If you want you video to be more realtime, change this value to18s
paired with smallerhls_fragment 3s
.
After the configuration is done, make sure that there is no error in the configuration by running this command
nginx -t
Create Systemd File
To make Nginx easier to manage, we can build a systemd file. First, create a new file in systemd folder:
nano /lib/systemd/system/nginx.service
And then copy & paste this config to the file
[Unit]
Description=Nginx Custom From Source
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Reload the systemd
systemctl daemon-reload
Enable Nginx service so it will auto start when the server boot
systemctl enable nginx
Now you can control Nginx using systemd, just like this:
service nginx start
service nginx reload
service nginx stop
service nginx restart
Start your Nginx
service nginx start
Create Logrotate File
Logrotate is useful for rotating the Nginx log so it will not write on a single file continuously. First, create a new file on logrotate folder
nano /etc/logrotate.d/nginx
Copy & Paste this code
/var/log/nginx/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 0640 root root
sharedscripts
prerotate
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
run-parts /etc/logrotate.d/httpd-prerotate; \
fi \
endscript
postrotate
invoke-rc.d nginx rotate >/dev/null 2>&1
endscript
}
Check the Streaming Server
You can try to feed the streaming server using FFmpeg or OBS. In my case, I’m using OBS. Direct the rtmp output to rtmp://<your-server-ip>/streaming
, for the stream key i will use avengers
in this tutorial just like this image below. And then start the stream.
And then, check the hls video using VLC by pointing the network URL to http://<your-server-ip>:8080/live/<stream key>/index.m3u8
just like the image below.
If the video is running well, then your basic streaming server is installed successfully!
Adaptive Bitrate Configuration
Now the advance part. If you want just a simple streaming server, then this step is not mandatory. This is where we add the adaptive bitrate feature to our streaming server. First, we must install FFmpeg.
apt install ffmpeg
Go back to nginx directory
cd /etc/nginx
After that, we must modify the rtmp
block on the nginx.conf
file. First, open the configuration file
nano nginx.conf
Change the rtmp
block to this code below
rtmp {
server {
listen 1935;
chunk_size 4096;
max_message 1M;
application streaming {
live on;
exec ffmpeg -i rtmp://localhost/streaming/$name
-c:a aac -b:a 32k -c:v libx264 -b:v 128K -f flv rtmp://localhost/hls/$name_low
-c:a aac -b:a 64k -c:v libx264 -b:v 256k -f flv rtmp://localhost/hls/$name_mid
-c:a aac -b:a 128k -c:v libx264 -b:v 512K -f flv rtmp://localhost/hls/$name_hi;
}
application hls {
live on;
hls on;
hls_path /etc/nginx/live;
hls_nested on;
hls_fragment 6s;
hls_playlist_length 30s;
hls_variant _low BANDWIDTH=160000;
hls_variant _mid BANDWIDTH=320000;
hls_variant _hi BANDWIDTH=640000;
}
}
}
This configuration will trigger FFmpeg to transcode all rtmp feed that comes in /streaming
path to 3 rtmp stream with different bitrate and feed them to /hls
path. And then the nginx will save each variant inside /etc/nginx/live
folder as well as create master playlist file named <stream key>.m3u8
.
Now your streaming server will adapt to the user’s available bandwidth based on the BANDWIDTH
directive. You can add or reduce the variant and set the BANDWIDTH
threshold based on your need.
After the configuration is done, make sure that there is no error in the configuration by running this command
nginx -t
After that, reload the nginx
service nginx reload
Check the Adaptive Bitrate Streaming Server
You can once again check your streaming server by feeding the video via OBS just like before and viewing them from VLC. But this time, change the network url on the VLC to http://<your-server-ip>:8080/live/<stream key>.m3u8
just like image below.
Congratulation! Now you can build An Adaptive Bitrate Streaming Server Using Nginx.