Skip to content

Instantly share code, notes, and snippets.

@benhartwich
Last active April 14, 2022 09:43
Show Gist options
  • Save benhartwich/beea3fa512ea586e4001c8e9b337da96 to your computer and use it in GitHub Desktop.
Save benhartwich/beea3fa512ea586e4001c8e9b337da96 to your computer and use it in GitHub Desktop.
Nginx RMTP with HLS variants
user www-data;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
rtmp {
server {
listen 1935;
chunk_size 4000;
# TV mode: one publisher, many subscribers
application src {
# enable live streaming
live on;
# record first 1K of stream
#record all;
#record_path /var/www/cam;
#record_max_size 1K;
# append current timestamp to each flv
#record_unique on;
# publish only from localhost
allow publish 127.0.0.1;
deny publish all;
exec ffmpeg -i rtmp://127.0.0.1/src/$name -async 1 -vsync -1
-c:v libx264 -c:a aac -b:v 256k -b:a 32k -vf "scale=480:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://127.0.0.1/hls/$name_low
-c:v libx264 -c:a aac -b:v 768k -b:a 96k -vf "scale=720:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://127.0.0.1/hls/$name_mid
-c:v libx264 -c:a aac -b:v 1024k -b:a 128k -vf "scale=960:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://127.0.0.1/hls/$name_high
-c:v libx264 -c:a aac -b:v 1920k -b:a 128k -vf "scale=1280:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://127.0.0.1/hls/$name_hd720
-c copy -f flv rtmp://127.0.0.1/hls/$name;
#allow play all;
}
application hls {
# publish only from localhost
allow publish 127.0.0.1;
deny publish all;
live on;
interleave on;
hls on;
hls_path /var/www/hls/live;
hls_fragment 5;
hls_playlist_length 10m;
hls_nested on; # create a new folder for each stream
hls_fragment_slicing aligned;
hls_continuous on;
#deny play all;
# Instruct clients to adjust resolution according to bandwidth
hls_variant _low BANDWIDTH=288000; # Low bitrate, sub-SD resolution
hls_variant _mid BANDWIDTH=448000; # Medium bitrate, SD resolution
#hls_variant _high BANDWIDTH=1152000; # High bitrate, higher-than-SD resolution
hls_variant _hd720 BANDWIDTH=2048000; # High bitrate, HD 720p resolution
hls_variant _src BANDWIDTH=4096000; # Source bitrate, source resolution
}
}
}
http {
include /etc/nginx/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"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
keepalive_timeout 60;
aio on;
directio 512;
client_max_body_size 8M;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 5s;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
gzip on;
gzip_disable "msie6";
gzip_http_version 1.1;
gzip_vary on;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types *;
add_header X-XSS-Protection "1; mode=block"; #Cross-site scripting
add_header X-Frame-Options "SAMEORIGIN" always; #clickjacking
add_header X-Content-Type-Options nosniff; #MIME-type sniffing
client_body_buffer_size 128k;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
fastcgi_buffers 256 4k;
fastcgi_buffer_size 32k;
fastcgi_send_timeout 600s;
fastcgi_read_timeout 600s;
# webp support
map $http_accept $webp_ext {
default "";
"~*webp" ".webp";
}
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;
server {
listen 80;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server_name hls.xy.de;
autoindex on;
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 /var/www/hls/live;
}
}
server {
listen 443 ssl;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server_name hls.xy.de;
ssl_certificate /etc/letsencrypt/live/hls.xy.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hls.xy.de/privkey.pem;
autoindex on;
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 /var/www/hls/live;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment