How To Setup Nginx For HLS Video Streaming On Centos 7
Tags: linux, devops, webdev
Published: 2019-02-13 21:26:31

---
title: How To Setup Nginx For HLS Video Streaming On Centos 7
published: true
description: How to live stream videos with Nginx
tags: #Linux #Devops #webdevelopment
---

## Introduction

HLS stands for HTTP live streaming. It’s an HTTP based media streaming protocol developed by Apple. Unlike UDP based protocols like RTP it can’t be blocked by firewalls that only allow HTTP traffic. It can  be delivered by HTTP servers such as Nginx and can distributed through CDNs. 

The default install of  Nginx doesn’t come complied with an HLS module;  but there’s an open source [Nginx module](https://github.com/arut/nginx-rtmp-module) that supports HLS.  We would need to compile Nginx from source and add the module during compilation.

This tutorial shows you how to install Nginx and use it as a video live streaming server.

## Prerequisites

To follow along with this tutorial please ensure the following are present on the target machine:

* git, wget, gcc, gcc-c++, perl, gd, gd-devel, perl-ExtUtils-Embed, geoip, geoip-devel and tar 
* A non root user with sudo capabilities

If you don’t have the build utilities you would need to install them. Run this to do so:

```
$ sudo yum update
$ sudo yum install epel-release
$ sudo yum install git wget gcc gcc-c++ tar gd gd-devel perl-ExtUtils-Embed geoip geoip-devel
```
## Step 1 -  Download and Compile Nginx With It’s Dependencies
We need to download the dependency libraries for Nginx;  including the open sorce [nginx-rtmp]( https://github.com/arut/nginx-rtmp-module) module used to provide Nginx with HLS capabilities. First off we download the [PCRE](http://pcre.org/) module required by Nginx [Core](https://nginx.org/en/docs/ngx_core_module.html) and [Rewrite](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html) modules. Run this to do so:

```
 $    wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.42.tar.gz
 $   tar -zxf pcre-8.42.tar.gz
 $   rm -rf pcre-8.42.tar.gz
 $   cd pcre-8.42
 $   ./configure
 $   make
 $   sudo make install
 $   cd
```
Next we download the [zlib](www.zlib.net) module required by the [Nginx Gzip module](https://nginx.org/en/docs/http/ngx_http_gzip_module.html) of nginx and install it. Run this to do so:

```
$ wget http://zlib.net/zlib-1.2.11.tar.gz
$ tar -zxf zlib-1.2.11.tar.gz
$ rm -rf zlib-1.2.11.tar.gz
$ cd zlib-1.2.11
$ ./configure
$ make
$ sudo make install
$ cd 
```
Up next, we download the [openssl module](http://www.openssl.org) required by the [Nginx SSL module](https://nginx.org/en/docs/http/ngx_http_ssl_module.html). Run this to do so:

```
$ wget http://www.openssl.org/source/openssl-1.0.2q.tar.gz
$ tar -zxf openssl-1.0.2q.tar.gz
$ rm -rf openssl-1.0.2.tar.gz
$ cd openssl-1.0.2q
$ ./config
$ make
$ sudo make install
$ cd
```
We then download the open source [nginx-rtmp](https://github.com/arut/nginx-rtmp-module)  module  from its github repository. To do that run:

```
$ git clone git://github.com/arut/nginx-rtmp-module.git
```
 Finally we download the Nginx source. We would be downloading the latest stable version, which as of this writing  is 1.14.2,  from [nginx.org] (http://www.nginx.org/en/download.html). Run this to do so:

```
$ wget https://nginx.org/download/nginx-1.14.2.tar.gz
$ tar zxf nginx-1.14.2.tar.gz
$ rm -rf nginx-1.14.2.tar.gz
$ cd nginx-1.14.2
```
Now that we have the necessary dependencies, we can compile Nginx. Now we need to configure the build options. This is done by running the  “./configure” script in the directory with a host of options for Nginx to compile. The options include the paths to the open source module, zlib module, pcre module and openssl module all previously downloaded and installed. We also need to specify which in built Nginx modules we want compiled. We run this to get the desired build option:

```
$ ./configure  --add-module=../nginx-rtmp-module \
--sbin-path=/usr/sbin/nginx \ 
--lock-path=/var/run/nginx.lock \
--conf-path=/etc/nginx/nginx.conf \
--pid-path=/run/nginx.pid \   
--with-pcre=../pcre-8.42 \    
--with-zlib=../zlib-1.2.11 \  
--with-openssl=../openssl-1.0.2q \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--user=nginx \                 
--group=nginx \                
--with-http_auth_request_module \
--with-http_degradation_module \
--with-http_geoip_module \     
--with-http_gunzip_module \    
--with-http_gzip_static_module \
--with-http_image_filter_module \
--with-http_mp4_module \
--with-http_perl_module \
--with-http_realip_module \
--with-http_secure_link_module \
--with-http_slice_module \
--with-http_ssl_module  \
--with-http_stub_status_module \
--with-http_v2_module \
--with-stream_ssl_module \
--with-stream \
--with-threads \
--prefix=/etc/nginx
```
Finally compile and build Nginx. 

```
$ make 
$ sudo make install
```
To check if it was installed properly run:

```
$ nginx -V #The output should be the Nginx version, compiler version, and configure script parameters.
```
We need to install the Nginx man pages, to do that run this:

```
$ sudo cp ~/nginx-1.14.2/man/nginx.8 /usr/share/man/man8
$ sudo gzip /usr/share/man/man8/nginx.8
```
Now we clean up the libraries previously downloaded. 

```
$ rm -rf nginx-1.14.2 nginx-rtmp-module openssl-1.0.2q pcre-8.42 zlib-1.2.11
```
## Step 2 – Setup and Configure Nginx

Now that the Nginx binary is installed in our search path, we need to setup an nginx user. To setup the nginx user, run:

```
$ sudo useradd --system --home /var/lib/nginx --shell /sbin/nologin --comment "nginx system user" nginx
``` 

We also need to create the directory where Nginx logs are stored and make user nginx the owner. For that we run:

```
$ sudo mkdir /var/log/nginx &&  sudo chown nginx:nginx /var/log/nginx 
```

With that done, it’s time to create the nginx systemd service unit file. It’s contents should be something like this:

```
  [Unit]
  Description=nginx - high performance web server
  Documentation=https://nginx.org/en/docs/
  After=network.target remote-fs.target nss-lookup.target
  Wants=network-online.target
        [Service]
  Type=forking
  PIDFile=/run/nginx.pid
  ExecStartPre=/usr/bin/rm -f /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
  KillSignal=SIGQUIT
  TimeoutStopSec=5
  KillMode=process
  PrivateTmp=true
     [Install]
  WantedBy=multi-user.target
 ```
We now paste the above contents in the nginx service file:
```
$ sudo vim  /lib/systemd/system/nginx.service   # You can replace vim with whichever editor you prefer
```
Now we reload systemctl daemon and start Nginx.

```
$ sudo systemctl daemon-reload
$ sudo systemctl start nginx
$ sudo systemctl enable nginx
```
Now we need to configure Nginx to stream videos. Our nginx.conf file; located in the /etc/nginx/ directory, should look like this:

```
user  nginx;
worker_processes  auto;
 server_tokens off;
events {
    worker_connections  1024;
}
# We need to setup an rmtp server to stream video from client devices
rtmp {
    server {
      listen 1935;
      chunk_size 4096;
      ping 30s;
      notify_method get;
      allow play all;
       # rmtp handler our clients connect to for live streaming, it runs on port 1935. It converts the stream to HLS and stores it on our server
   application app {
          live on;
          hls on;   
          hls_path /var/www/hls/live;
          hls_nested on;  # create a new folder for each stream
          record_notify on;
          record_path /var/www/videos;
          record all;
          record_unique on;
     }
    
    application vod {
       play /var/www/videos;
    }
 }
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    sendfile        on;
    tcp_nopush     on;
    keepalive_timeout  65;
    gzip  on;
    server {
        listen       80;
        server_name  _;
        location / {
            root   html;
            index  index.html index.htm;
        }
          # the http end point our web based users connect to see the live stream
          location /live {
            types {
                application/vnd.apple.mpegurl m3u8; 
             }
                 alias /var/www/hls/live;
                add_header Cache-Control no-cache;
       }
   }
```

We need to also create the directory where our video stream is stored.

```
 $ sudo mkdir -p /var/www/hls/live
```
Now we can restart nginx to reload the new configuration file.

```
$ sudo systemctl restart nginx

```

## Step 3- Stream and Publish Videos

Now to live stream videos from a client machine, assuming the client has the video stored locally and [ffmpeg](https://www.ffmpeg.org/) installed, we run this to publish to our server:

```
$ ffmpeg -i /path/to/video  -c:v h264 -c:a aac  -strict -2 -f flv rtmp://server_ip:1935/app/unique_stream_name     #the name of the stream has to be unique  

```
Our viewers can watch the video on [vlc media player](https://www.videolan.org/vlc/index.html) by streaming the url: ``http://server_ip/live/unique_stream_key/index.m3u8``. It is also possible to publish video from webcam from a Linux client machine by running:

```
$ ffmpeg -f video4linux2 -i /dev/video0 -c:v libx264 -an -f flv rtmp://server_ip:1935/app/unique_stream_name
```
From a mac book, it’s this way

```
$ ffmpeg -f avfoundation -framerate 30 -i "0" -c:v libx264 -an -f flv rtmp://server_ip:1935/app/unique_stream_name
```

## Conclusion
And thats how to setup HLS with Nginx. To go further we could write an application in our favorite programming language to handle user authentication and maybe store videos on a media server. The key thing is that our users can live stream videos with regular HTTP.