I have a nginx-rtmp server for real time hls streaming with three rtmp stream running. Right now all the hls are streaming are at 3-4mbps, is there any i can restrict the outbound data transfer rate to 1-2mpbs using directives in nginx.
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
notify_method get;
live on;
hls on;
hls_path /nginx/hls/;
hls_fragment 3;
hls_playlist_length 60;
drop_idle_publisher 10s;
meta copy;
hls_variant _low BANDWIDTH=166000;
hls_variant _mid BANDWIDTH=244000;
}
}
}
http {
sendfile off;
tcp_nopush on;
directio 512;
default_type application/octet-stream;
server {
listen 8080;
location / {
add_header 'Cache-Control' 'no-cache';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
if ($request_method = 'OPTIONS') {
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/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /nginx/hls/;
#root /nginx/;
}
}
}
Thanks in advance
Related
I'm using nginx-rtmp module to capture RTMP streams from my cameras and transmit them to further systems.
Generally my setup is working fine and generating .m3u8 files properly. For example:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:23
#EXT-X-TARGETDURATION:50
#EXT-X-DISCONTINUITY
#EXTINF:49.957,
verification-23.ts
But the fragments that are generated are always 50s as you can see on the above example.
This is causing more than 50s delay in playback that I would like to avoid.
I tried to decrease Nginx parameters to, for example 3s for fragment and 15s for playlist:
hls_fragment 3s;
hls_playlist_length 15s;
but it didn't work. .m3u8 files were still generated with #EXTINF:49.957.
Is it possible to decrease the delay with Nginx configuration? Or it might be some kind of additional configuration on the cameras?
My current nginx.conf file:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 768;
}
rtmp {
server {
listen 1935;
chunk_size 2000;
application live {
live on;
hls on;
hls_path /tmp/hls;
hls_fragment 50s;
hls_playlist_length 60s;
deny play all;
}
}
}
http {
sendfile off;
tcp_nopush on;
directio 512;
default_type application/octet-stream;
server {
server_name stream.mydomain.pl;
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 /tmp;
}
# Certbot configuration
# ...
}
This is my setup:
I have a webpage which uses dash.js to view a live stream. The live stream is coming from my computer which is running OBS and NGINX. This works without a problem except when I call up the webpage within the first 30 seconds (or so) after the stream has started.
I tell dash to open up index.mpd on my computer, but only when it's available. In pseudo code:
START: If index.mpd is available
initialize stream and view it
Else
go to START
End
As soon as index.mpd is available, this means there's also a video/audio chunk available so it should be able to start playing. But it stalls instead (grey screen with rotating pin wheel). This probably has to do with the fact the settings ask for a 20 second buffer and a video/audio chunk is 8.3 seconds. (BTW, I have no idea why those chunks are 8.3 seconds - I could not find a setting anywhere in OBS or NGINX that reflects those 8.3 seconds)
The problem is, it never stops stalling (is it trying to buffer? I don't know). Even when all chunks are available and NGINX starts FIFO-ing the chunks. It never recovers from the stall.
Only when I open the page at a time when the entire buffer is available (which, again for some unknown reason, is about 30 seconds instead of the 20 I have set it to) will it start (dis)playing the stream.
Here is the complete NGINXG.conf:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
interleave on;
meta on;
session_relay on;
max_connections 1500;
record_path recordings;
record_suffix all-%d-%b-%y-%T.flv;
push rtmp://localhost/dash;
}
application dash {
live on;
dash on;
dash_nested on;
dash_cleanup on;
dash_fragment 5s;
dash_playlist_length 20s;
dash_path temp/tmp_dash;
}
}
}
http {
keepalive_timeout 60;
send_timeout 10;
keepalive_requests 10;
client_body_timeout 10;
sendfile on;
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"';
access_log logs/access.log main;
server {
listen 8050;
server_name localhost;
access_log logs/host.access.log main;
add_header Strict-Transport-Security "max-age=63072000;";
index index.php index-nginx.html index.html index.htm;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root site;
}
location / {
location ~* \.m3u8$ {
add_header Cache-Control no-cache;
}
try_files $uri $uri/ =404;
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Strict-Transport-Security' 'max-age=31536000';
add_header 'X-Content-Type-Options' "nosniff" 'always';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 1728000;
# add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
root site;
index index.php index.html index-nginx.html index.htm index.m3u8 index.mpd;
}
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root site;
}
location /tmp_dash {
alias temp/tmp_dash;
autoindex on;
autoindex_localtime on;
autoindex_exact_size off;
expires -1;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length';
}
types {
application/dash+xml mpd;
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
text/html html;
}
}
}
}
And here's the HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="http://cdn.dashjs.org/latest/dash.all.min.js"></script>
<script>
window.addEventListener( "load", init );
var XMLHttp;
var streamActive = false;
var url = "/tmp_dash/stream/index.mpd";
function init(){
XMLHttp = new XMLHttpRequest();
XMLHttp.onreadystatechange = function() {
if( XMLHttp.readyState == 4
if( XMLHttp.status == 200 ) {
// Index.mpd exists
if( ! streamActive ) {
player = dashjs.MediaPlayer().create();
player.initialize( document.querySelector( "#videoPlayer" ), url, true);
}
} else if( XMLHttp.status == 404 ) {
setTimeout( checkStreamReady, 5000 ); // Check again in 5 seconds
}
}
}
checkStreamReady();
}
function checkStreamReady() {
XMLHttp.open( "GET", url, true );
XMLHttp.send();
}
</script>
</head>
<body>
<div id="videocontainer">
<video id="videoPlayer" controls></video>
</div>
</body>
</html>
so I've configured my nginx server on azure to the point that i can in fact connect to it and stream but there is one issue i don't have the .m3u3 file in my hls directory, I'm streaming to this server via obs here is my nginx config
I found some old thread with this error but i've added user root; to file and still nothing
anyone know why it's not working
user root;
worker_processes auto; events {
worker_connections 1024;
}
# RTMP configuration
rtmp {
server {
listen 1935 ; # Listen on standard RTMP port
chunk_size 4000;
application show {
live on;
# Turn on HLS
hls on;
hls_path /mnt/hls/;
hls_fragment 3;
hls_playlist_length 60;
# disable consuming the stream from nginx as rtmp
deny play all;
}
}
}
http {
sendfile off;
tcp_nopush on;
# aio on;
directio 512;
default_type application/octet-stream;
server {
listen 8080;
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 /nginx/;
}
}
}
this is my nginx.conf using Ubuntu 18.04../usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
application live {
live on;
interleave on;
record off;
hls on;
hls_path /mnt/hls;
hls_fragment 6s;
hls_playlist_length 60s;
deny play all;
dash on;
dash_path /mnt/dash;
dash_fragment 3s;
}
}
}
http {
sendfile off;
tcp_nopush on;
directio 512;
default_type application/octet-stream;
server {
listen 8080;
location / {
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;
}
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
text/html html;
application/dash+xml mpd;
}
root /mnt/;
}
}
}
OBS Stream setting :
server add : rtmp://[ip-addr]/live
stream key : stream
i've tried live stream using android (larix broadcaster app), with this connection setting,
server add : rtmp//{ip-addr]:1935/live/stream
stram key : stream
and at my website, i've added playerjs.js and use this inside index.html
<section class="wrapper style1">
<div class="inner">
<div class="video">
<div class="video-wrapper">
<iframe width="100%" height="100%" src="playerjs.html?file=http://[ip-addr]:8080/hls/stream.m3u8" type="text/html" frameborder="0" allowfullscreen></iframe>
</div>
</div>
</div>
</section>
i'm running my server with apache2 on port:80, php, mySql..while Nginx on port:8080 to serve livestream HLS
.m3u8 will generated automaticly inside /mnt/hls
Application name define inside rtmp ..>> application live (i named it "live"), you may named it you like..while stream key, you define by yourself via streamer (OBS, Larix etc...) >> rtmp:/{ip-addr]:1935/live/stream ( i named "stream"). nginx will pull that stream name and put inside mnt/hls/ and create .m3u8 file, devide clips into 60s playlist, and load every clips by 6s fragment..
thats why i like nginx :) and still going smooth .. hope this would help
I have a fairly basic lit-html app that works locally when it's not build.
However when I build it using polymer build using the following config:
{
"entrypoint": "index.html",
"shell": "src/school-home.js",
"sources": [
"src/**.js",
"package.json"
],
"extraDependencies": [
"node_modules/#webcomponents/webcomponentsjs/bundles/**"
],
"builds": [
{"preset": "es6-bundled"}
]
}
This results in a successful build but for some reason I keep getting an error:
I just don't get why it doesn't work. This like the basics of the basics yet it doesn't get found?
Aside: I use nginx for windows since I want to test E2E with my developed APIs.
An additional issue is that I keep getting CORS error for my API calls even though they are on the exact same location?!!
Please help.
Edit:
My NGINX config:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include cors-settings.conf;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 8000;
server_name localhost;
location /school {
root /html/ing-school;
try_files $uri $uri/ $uri.html /index.html;
}
location ~ ^/(api|login|logout) {
proxy_pass http://localhost:8080;
proxy_set_header Connection "";
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested- With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content- Range';
}
}
location /ws {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
I have had no issues in live-streaming to the server, but I am trying to add VOD functionality with some difficulty. The record_path "/mnt/film/" is not being created or written to by the server, even if I create the directory before running the server.
I have tried adding a user with root permissions, but this did not seem to help. The weird thing is that error logs are not being created as well, but it writes to the "/mnt/hls" path with no problems whatsoever.
user nginx root;
worker_processes auto;
error_log logs/error.log debug;
events {
worker_connections 1024;
}
# RTMP configuration
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
# Turn on HLS
hls on;
hls_path /mnt/hls/;
hls_fragment 3;
hls_playlist_length 60;
# record stream to folder /film/
record all;
record_path /mnt/film/;
# disable consuming the stream from nginx as rtmp
deny play all;
}
}
}
http {
sendfile off;
tcp_nopush on;
default_type application/octet-stream;
server {
listen 8080;
location /hls {
# 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/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /mnt/;
}
}
server {
listen 8384;
# vod caches
vod_metadata_cache metadata_cache 256m;
vod_response_cache response_cache 128m;
# vod settings
vod_mode local;
vod_segment_duration 2000; # 2s
vod_align_segments_to_key_frames on;
#file handle caching / aio
open_file_cache max=1000 inactive=5m;
open_file_cache_valid 2m;
open_file_cache_min_uses 1;
open_file_cache_errors on;
aio on;
location /vod/ {
alias mnt/film/;
vod hls;
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Expose-Headers' 'Server,range,Content-Length,Content-Range';
add_header 'Access-Control-Allow-Methods' 'GET, HEAD, OPTIONS';
add_header 'Access-Control-Allow-Origin' '*';
expires 100d;
}
}
}
I am just trying to get some files to show up in the "record_path" directory defined in the nginx.conf above.
Thanks
Have you checked hls_cleanup directive ? By default the feature is on. In this mode nginx cache manager process removes old HLS fragments and playlists from HLS directory.
https://github.com/arut/nginx-rtmp-module/wiki/Directives#hls_cleanup