I'm investigating observed latency when streaming HLS generated from an RTMP stream. I notice on the /stat
dashboard that in the time column, no matter how few variants I generate, there is always a ~6 second difference between the time on the RTMP stream and the HLS variants.
Any idea if there is a config that would allow for shorter delta between the RTMP input and the HLS fragment being output? In all my testing I am seeing a consistent 6 second difference.
I've tried running the container on SSD and normal hard drives and there is no difference. This makes me wonder if there is some setting in ffmpeg or nginx itself that is causing this?
When using SSD drives, I am getting ~15-18 second latency between broadcast and playback. I'm assuming if I can reduce this 6 second delay, that could drop playback latency below 10 seconds.
daemon off;
error_log /dev/stdout error;
worker_processes auto;
events {
worker_connections 1024;
}
rtmp_auto_push on;
rtmp {
server {
listen 1935;
application live {
live on;
record off;
}
application stream {
live on;
# 4:3 Aspect Ratio -> Observed Latency: 12s - 15s
exec ffmpeg -i rtmp://localhost/stream/$name -async 1 -vsync -1
-c:v libx264 -b:v 123k -minrate 123k -maxrate 123k -bufsize 61k -vf "scale=234:-2,format=yuv420p,drawtext=text=234p @24fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 24 -sc_threshold 0 -tune zerolatency -profile:v baseline -level 3 -f flv rtmp://localhost/hls/$name_234p
-c:v libx264 -b:v 129k -minrate 129k -maxrate 129k -bufsize 65k -vf "scale=240:-2,format=yuv420p,drawtext=text=240p @24fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 24 -sc_threshold 0 -tune zerolatency -profile:v baseline -level 3 -f flv rtmp://localhost/hls/$name_240p
-c:v libx264 -b:v 523k -minrate 523k -maxrate 523k -bufsize 261k -vf "scale=432:-2,format=yuv420p,drawtext=text=432p @30fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 30 -sc_threshold 0 -tune zerolatency -profile:v high -level 4 -f flv rtmp://localhost/hls/$name_432p
-c:v libx264 -b:v 290k -minrate 290k -maxrate 290k -bufsize 145k -vf "scale=360:-2,format=yuv420p,drawtext=text=360p @24fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 24 -sc_threshold 0 -tune zerolatency -profile:v baseline -level 3 -f flv rtmp://localhost/hls/$name_360p
-c:v libx264 -b:v 645k -minrate 645k -maxrate 645k -bufsize 323k -vf "scale=480:-2,format=yuv420p,drawtext=text=480p @30fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 30 -sc_threshold 0 -tune zerolatency -profile:v high -level 4 -f flv rtmp://localhost/hls/$name_480p
-c:v libx264 -b:v 929k -minrate 929k -maxrate 929k -bufsize 464k -vf "scale=576:-2,format=yuv420p,drawtext=text=576p @30fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 30 -sc_threshold 0 -tune zerolatency -profile:v high -level 4 -f flv rtmp://localhost/hls/$name_576p
-c:v libx264 -b:v 1452k -minrate 1452k -maxrate 1452k -bufsize 726k -vf "scale=720:-2,format=yuv420p,drawtext=text=720p @30fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 30 -sc_threshold 0 -tune zerolatency -profile:v high -level 4 -f flv rtmp://localhost/hls/$name_720p;
# Original -> Observed Latency: 12s - 15s
#exec ffmpeg -i rtmp://localhost/stream/$name -async 1 -vsync -1
# -c:v libx264 -b:v 145k -minrate 145k -maxrate 145k -bufsize 73k -vf "scale=234:-2,format=yuv420p,drawtext=text=234p @24fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 24 -sc_threshold 0 -tune zerolatency -profile:v baseline -level 3 -f flv rtmp://localhost/hls/$name_234p
# -c:v libx264 -b:v 576k -minrate 576k -maxrate 576k -bufsize 288k -vf "scale=240:-2,format=yuv420p,drawtext=text=240p @24fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 24 -sc_threshold 0 -tune zerolatency -profile:v baseline -level 3 -f flv rtmp://localhost/hls/$name_240p
# -c:v libx264 -b:v 730k -minrate 730k -maxrate 730k -bufsize 365k -vf "scale=432:-2,format=yuv420p,drawtext=text=432p @30fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 30 -sc_threshold 0 -tune zerolatency -profile:v high -level 4 -f flv rtmp://localhost/hls/$name_432p
# -c:v libx264 -b:v 704k -minrate 704k -maxrate 704k -bufsize 352k -vf "scale=360:-2,format=yuv420p,drawtext=text=360p @24fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 24 -sc_threshold 0 -tune zerolatency -profile:v baseline -level 3 -f flv rtmp://localhost/hls/$name_360p
# -c:v libx264 -b:v 896k -minrate 896k -maxrate 896k -bufsize 448k -vf "scale=480:-2,format=yuv420p,drawtext=text=480p @30fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 30 -sc_threshold 0 -tune zerolatency -profile:v high -level 4 -f flv rtmp://localhost/hls/$name_480p
# -c:v libx264 -b:v 1408k -minrate 1408k -maxrate 1408k -bufsize 704k -vf "scale=576:-2,format=yuv420p,drawtext=text=576p @30fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 30 -sc_threshold 0 -tune zerolatency -profile:v high -level 4 -f flv rtmp://localhost/hls/$name_576p
# -c:v libx264 -b:v 1856k -minrate 1856k -maxrate 1856k -bufsize 928k -vf "scale=720:-2,format=yuv420p,drawtext=text=720p @30fps:fontsize=24:[email protected]:box=1:[email protected]:boxborderw=8:fontfile=/usr/share/DejaVuSansMono.ttf:x=(w-tw)/2:y=th" -preset ultrafast -crf 28 -g 30 -r 30 -sc_threshold 0 -tune zerolatency -profile:v high -level 4 -f flv rtmp://localhost/hls/$name_720p;
}
application hls {
live on;
wait_key on;
hls on;
hls_path /opt/data/hls; # Mount point (preferrably on an SSD drive since I/O intensive)
hls_nested on;
hls_fragment 1s;
hls_playlist_length 6s;
hls_fragment_slicing aligned;
# 4:3 Aspect Ratio
hls_variant _234p BANDWIDTH=122653,AVERAGE-BANDWIDTH=122653,RESOLUTION=234x312,FRAME-RATE=24,CODECS="avc1.42001e";
hls_variant _240p BANDWIDTH=129024,AVERAGE-BANDWIDTH=129024,RESOLUTION=240x320,FRAME-RATE=24,CODECS="avc1.42001e";
hls_variant _432p BANDWIDTH=522547,AVERAGE-BANDWIDTH=522547,RESOLUTION=432x576,FRAME-RATE=30,CODECS="avc1.420028";
hls_variant _360p BANDWIDTH=290304,AVERAGE-BANDWIDTH=290304,RESOLUTION=360x480,FRAME-RATE=24,CODECS="avc1.42001e";
hls_variant _480p BANDWIDTH=645120,AVERAGE-BANDWIDTH=645120,RESOLUTION=480x640,FRAME-RATE=30,CODECS="avc1.420028";
hls_variant _576p BANDWIDTH=928973,AVERAGE-BANDWIDTH=928973,RESOLUTION=576x768,FRAME-RATE=30,CODECS="avc1.420028";
hls_variant _720p BANDWIDTH=1451520,AVERAGE-BANDWIDTH=1451520,RESOLUTION=720x960,FRAME-RATE=30,CODECS="avc1.420028";
# Original
#hls_variant _234p BANDWIDTH=145000,AVERAGE-BANDWIDTH=145000,RESOLUTION=234x416,FRAME-RATE=24,CODECS="avc1.42001e";
#hls_variant _240p BANDWIDTH=576000,AVERAGE-BANDWIDTH=576000,RESOLUTION=240x427,FRAME-RATE=24,CODECS="avc1.42001e";
#hls_variant _432p BANDWIDTH=730000,AVERAGE-BANDWIDTH=730000,RESOLUTION=432x768,FRAME-RATE=30,CODECS="avc1.420028";
#hls_variant _360p BANDWIDTH=704000,AVERAGE-BANDWIDTH=704000,RESOLUTION=360x640,FRAME-RATE=24,CODECS="avc1.42001e";
#hls_variant _480p BANDWIDTH=896000,AVERAGE-BANDWIDTH=896000,RESOLUTION=480x853,FRAME-RATE=30,CODECS="avc1.420028";
#hls_variant _576p BANDWIDTH=1408000,AVERAGE-BANDWIDTH=1408000,RESOLUTION=576x1024,FRAME-RATE=30,CODECS="avc1.420028";
#hls_variant _720p BANDWIDTH=1856000,AVERAGE-BANDWIDTH=1856000,RESOLUTION=720x1280,FRAME-RATE=30,CODECS="avc1.420028";
}
}
}
http {
server {
listen 80;
sendfile off;
tcp_nopush on;
aio on;
directio 512;
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /opt/data;
add_header 'Cache-Control' 'no-cache';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length';
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;
}
}
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet static/stat.xsl;
}
location /static {
alias /www/static;
}
location = /crossdomain.xml {
root /www/static;
default_type text/xml;
expires 24h;
}
}
}