I have an encoder that outputs an HLS stream and I wanted NGINX to receive it.
I was unable to find a single page with complete step-by-step instructions so hopefully you find this useful.
- For NGINX to accept an incoming HLS stream, you will need a 3rd-party module and, AFAIK, Arut's nginx-ts-module is only game in town. Click the green "Code" button and select "Download ZIP": https://github.com/arut/nginx-ts-module and decompress it.
- Follow the following steps from: https://www.vultr.com/docs/how-to-compile-nginx-from-source-on-centos-7
- Summary:
Become root and enter:yum check-update || sudo yum update -y
yum groupinstall -y 'Development Tools' && yum install -y vim
yum install -y epel-release
yum install -y perl perl-devel perl-ExtUtils-Embed libxslt libxslt-devel libxml2 libxml2-devel gd gd-devel GeoIP GeoIP-devel
- Navigate to http://nginx.org/en/download.html and download the latest "Mainline" NGINX source code. Version 1.19.6 was the latest on 2021-Jan-5:
wget http://nginx.org/download/nginx-1.19.6.tar.gz && tar zxvf nginx-1.19.6.tar.gz
- NGINX depends on PCRE, zlib and OpenSSL libraries as per the NGINX compiling instructions: https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/#sources All the instructions I found online, recommend downloading the latest source code of those libraries and linking them to the NGINX build, however, this failed for me with the make error:
/bin/ld: ../pcre-8.44/.libs/libpcre.a(libpcre_la-pcre_compile.o): relocation R_X86_64_32S against hidden symbol `_pcre_OP_lengths' can not be used when making a shared object
/bin/ld: ../pcre-8.44/.libs/libpcre.a(libpcre_la-pcre_config.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
/bin/ld: ../pcre-8.44/.libs/libpcre.a(libpcre_la-pcre_exec.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
/bin/ld: ../pcre-8.44/.libs/libpcre.a(libpcre_la-pcre_fullinfo.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
/bin/ld: ../pcre-8.44/.libs/libpcre.a(libpcre_la-pcre_jit_compile.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
/bin/ld: ../pcre-8.44/.libs/libpcre.a(libpcre_la-pcre_study.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
/bin/ld: ../zlib-1.2.11/libz.a(deflate.o): relocation R_X86_64_32S against hidden symbol `_length_code' can not be used when making a shared object
/bin/ld: ../zlib-1.2.11/libz.a(inflate.o): relocation R_X86_64_32S against hidden symbol `zcfree' can not be used when making a shared object
/bin/ld: ../zlib-1.2.11/libz.a(inftrees.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/bin/ld: ../zlib-1.2.11/libz.a(trees.o): relocation R_X86_64_32S against hidden symbol `_length_code' can not be used when making a shared object
/bin/ld: ../zlib-1.2.11/libz.a(zutil.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/bin/ld: ../zlib-1.2.11/libz.a(crc32.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
/bin/ld: ../zlib-1.2.11/libz.a(inffast.o): relocation R_X86_64_32S against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
make[1]: *** [nginx-1.19.6/nginx] Error 1
make[1]: Leaving directory `/root/nginx-1.19.6'
make: *** [build] Error 2
I tried adding -fPIC to various places but I was unsuccessful. I wasn't able to get the following solutions to work: https://serverfault.com/a/831233
https://stackoverflow.com/questions/48599572
Instead, I installed the dev libraries from CentOS and EPEL with:yum -y install zlib-devel pcre-devel openssl-devel
- Navigate into the NGINX source directory, make sure it's properly extracted and look through the "configure" options
cd ~/nginx-1.19.6; ls
./configure --help
- I figured I should try to compile NGINX similar to how EPEL's NGINX binary is compiled. I suggest installing the EPEL NGINX for reference and for the install scripts to create the nginx user, group, ...
Install NGINX and then run the following command to see it's compiled options:yum -y install nginx
nginx -V
nginx version: nginx/1.16.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.1.1c FIPS 28 May 2019 (running with OpenSSL 1.1.1g FIPS 21 Apr 2020)
TLS SNI support enabled
configure arguments: --prefix=/usr/share/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 --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_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_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' - I modified this output to install the compiled version into a new directory: /opt/dave
Change PREFIX, paths and BUILDDIR to suite your needs:
./configure --prefix=/opt/dave/usr/share/nginx \
--sbin-path=/opt/dave/usr/sbin/nginx \
--modules-path=/opt/dave/usr/lib64/nginx/modules \
--conf-path=/opt/dave/etc/nginx/nginx.conf \
--error-log-path=/opt/dave/var/log/nginx/error.log \
--pid-path=/opt/dave/var/run/nginx.pid \
--lock-path=/opt/dave/var/run/nginx.lock \
--http-log-path=/opt/dave/var/log/nginx/access.log \
--http-client-body-temp-path=/opt/dave/var/lib/nginx/tmp/client_body \
--http-proxy-temp-path=/opt/dave/var/lib/nginx/tmp/proxy \
--http-fastcgi-temp-path=/opt/dave/var/lib/nginx/tmp/fastcgi \
--http-uwsgi-temp-path=/opt/dave/var/lib/nginx/tmp/uwsgi \
--http-scgi-temp-path=/opt/dave/var/lib/nginx/tmp/scgi \
--user=nginx \
--group=nginx \
--build=CentOS \
--builddir=nginx-1.19.6 \
--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 \
--with-http_perl_module=dynamic \
--with-mail=dynamic \
--with-mail_ssl_module \
--with-stream=dynamic \
--with-stream_ssl_module \
--with-google_perftools_module \
--with-stream_realip_module \
--with-stream_geoip_module=dynamic \
--with-stream_ssl_preread_module \
--with-compat \
--with-openssl-opt=no-nextprotoneg \
--with-debug \
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' \
--with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' \
--add-dynamic-module=../nginx-ts-module-master - If configure runs without error then build and install it:
make
make install
- I renamed the new NGINX to differentiate it from the EPEL installed NGINX:
cd /opt/dave/usr/sbin
mv nginx nginx-1.19.6
- NGINX will fail if the following directory isn't created:
mkdir -p /opt/dave/var/lib/nginx/tmp/media
chown -R nginx.nginx /opt/dave/var/lib/nginx - Backup the existing conf file:
cd /opt/dave/etc/nginx
cp nginx.conf{,.bak}
- Use the following nginx.conf file to test HLS ingest:
load_module /opt/dave/usr/lib64/nginx/modules/ngx_http_ts_module.so;
worker_processes 1;
events {
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 2935;
server_name localhost;location / {
root html;
}
location /publish/ {
ts;
ts_hls path=/opt/dave/var/lib/nginx/tmp/media/hls segment=10s;
client_max_body_size 0;
}
location /play/ {
types {
application/x-mpegURL m3u8;
application/dash+xml mpd;
video/MP2T ts;
video/mp4 mp4;
}
alias /opt/dave/var/lib/nginx/tmp/media/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
- Test the newly compiled NGINX binary:
/opt/dave/usr/sbin/nginx-1.19.6
- Send a test from the same or another computer to NGINX with ffmpeg (either compile ffmpeg from source or use the following instructions taken from https://linuxize.com/post/how-to-install-ffmpeg-on-centos-7/):
yum localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-7.noarch.rpm
yum -y install ffmpeg
ffmpeg -re -i <Filename>.mp4 -bsf:v h264_mp4toannexb -c copy -f mpegts http://<FQDN or IP of NGINX>:<Port>/publish/<User-defined name> > /dev/null 2>&1 < /dev/null - To restart ffmpeg if it crashes and to prevent it from outputting to the console use the following (taken from: https://stackoverflow.com/a/16527559):
#!/bin/bash
while [ true ]; do
ffmpeg -re -i <Filename>.mp4 -bsf:v h264_mp4toannexb -c copy -f mpegts http://<FQDN or IP of NGINX>:<Port>/publish/<User-defined name> > /dev/null 2>&1 < /dev/null
sleep 0.1
done - View the replublished HLS stream with VLC:
http://<FQDN or IP of NGINX>:<Port>/play/hls/<User-defined name>/index.m3u8 - If you're happy with it all, you may wish to make the new NGINX a service and start on boot.
Alternatively, if you're not interested in the above steps, there seems to be a 3rd-party pre-compiled package of the nginx-ts-module here: https://centos.pkgs.org/7/getpagespeed-x86_64/nginx-module-ts-1.18.0.0.1.1-2.el7.gps.x86_64.rpm.html
There also seems to be a Docker image here: https://hub.docker.com/r/2chat/nginx-ts-docker
No comments:
Post a Comment