I've installed nginx with RTMP module on my linux server where I want it to receive a RTMP stream from Open Broadcaster Software, convert it to HLS and play it on my private website with some HTML5 player. Receiving the stream trough RTMP works, but the HLS stream doesn't seem to work. My current config is like so:
worker_processes 1;
events {
worker_connections 1024;
}
http {
#include mime.types;
#default_type application/octet-stream;
sendfile off;
#keepalive_timeout 65;
server {
listen 8080;
#server_name localhost;
#location / {
# root html;
# index index.html index.htm;
#}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root html;
#}
#*********************************************************************************************************************************
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
}
root /mnt/;
add_header Cache-Control no-cache;
# To avoid issues with cross-domain HTTP requests (e.g. during development)
#add_header Access-Control-Allow-Origin *;
}
#*********************************************************************************************************************************
}
}
rtmp {
server {
listen 1935;
chunk_size 4096;
application stream {
live on;
#record off;
hls on;
hls_path /mnt/hls;
#hls_fragment 6s;
}
}
}
To recieve the RTMP stream I use rtmp://ip/stream/streamname which works fine, for receiving HLS I try to use http://ip:8080/hls/streamname.m3u8 which gives me the .m3u8 file if I type it in a browser, but doesn't seem to work on the webpage when I try to play the file in a HTML5 player. I'm testing via these pages: https://videojs.github.io/videojs-contrib-hls/ and https://demo.theoplayer.com/test-hls-mpeg-dash-stream
Can anyone help me understand what I'm doing wrong?
It would help if you shared what type of console or network errors you get when testing your HLS stream on those pages.
It might provide some insight for you to troubleshoot. For example, you might be getting Access Control Allow Origin errors by accessing your stream from a different domain. Try uncommenting this line in your nginx.conf and reloading.
#add_header Access-Control-Allow-Origin *;
I also have a reference to "video/mp2t ts;" in my hls location block.
location /hls/ {
# Serve HLS fragments
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Origin' '*';
}
Cheers.
Ian
Under the line: #hls_fragment 6s;
Add the code: deny_play_all;
Apparently you can't play the hls or dash files if the rtmp stream can be played. I don't know why. It just worked for me.
nginx-1.21.1
location /hls/ {
# Serve HLS fragments
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
**root /tmp;** -> **alias /tmp;**
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Origin' '*';
}
Related
I'm trying to build a nginx-based maintenance mode application, that catches all requests to my applications and returns a predefined response as a 503.
I currently have applications requesting json responses as well as users accessing the pages with their browsers. So in case the request contains the header Accept: application/json, I want to respond with the content of a json file maintenance.json, otherwise with an html file maintenance.html.
My current nginx config looks like this:
server {
listen 8080;
root /usr/share/nginx/maintenance;
server_tokens off;
error_page 503 = #unavailable;
location ^~ / {
return 503;
}
location #unavailable {
set $maintenanceContentType text/html;
set $maintenanceFile /maintenance.html;
if ($http_accept = 'application/json') {
set $maintenanceContentType application/json;
set $maintenanceFile /maintenance.json;
}
default_type $maintenanceContentType;
try_files $uri $maintenanceFile;
}
}
For browser requests to any path this works out fine: "https://maintenance.my-domain.local/some-path". I get the response code and the html content.
But for requests with header Accept: application/json I get a 404 html page. And the nginx log shows [error] 21#21: *1 open() "/usr/share/nginx/maintenance/some-path" failed (2: No such file or directory), client: 10.244.2.65, server: , request: "GET /asd HTTP/1.1", host: "maintenance.my-domain.local".
It seems like json requests are ignoring my location for some reason. When I remove the directive to set the appropriate file and just always return the html this also works for json-requests.
Anyone any idea?
I'm not necessarily looking for a fix for this specific config, but rather for something that fits my needs of responding with different "error pages" based on the Accept header.
Thanks in advance!
EDIT: For some reason this now results in an HTTP 200 instead of a 503. Don't know what I changed..
EDIT2: Managed to fix a part of it:
server {
listen 8080;
root /usr/share/nginx/maintenance;
server_tokens off;
location ^~ / {
if ($http_accept = 'application/json') {
return 503;
}
try_files /maintenance.html =404;
}
error_page 503 /maintenance.json;
location = /maintenance.json {
internal;
}
}
With this config I now get the maintenance page when using the browser and the maintenance json, when defining the header Accept: application/json. The browser response code is 200 now though...
Ok, I found the solution to my problem.
# map the incoming Accept header to a file extension
map $http_accept $accept_ext {
default html;
application/json json;
}
server {
listen 8080;
root /usr/share/nginx/maintenance;
server_tokens off;
# return 503 for all incoming requests
location ^~ / {
return 503;
}
# a 503 redirects to the internal location `#maintenance`. the
# extension of the returned file is decided by the Accept header map
# above (404 in case the file is not found).
error_page 503 #maintenance;
location #maintenance {
internal;
try_files /maintenance.$accept_ext =404;
}
}
Key was the map on the top. I just added application/json there and mapped everything else to the html file by default. But you could add multiple other files/file types there of course.
I have an application written in Angular 8 that I'm serving on nginx. After the deployment I get an following error:
Failed to load resource: the server responded with a status of 404 ()
Additionally in the Dev Tools we can see such a message:
error: "404 Not Found404 Not Foundnginx/1.12.0
message: "Http failure response for https://myUrl/app/assets/config/endpoints.json: 404 OK
name: "HttpErrorResponse" ok: false status: 404 statusText:
"OK" url: "https://myUrl/app/assets/config/endpoints.json"
What I didn't understand why is the response stating "OK"? But it's not the main problem. The main problem is that I can't load this endpoints.json file neither access any file located under the assets dir.
When I directly go to the URI:
https://myUrl/app/someFile.png
then it's visible, but if I try to reach
https://myUrl/app/assets or https://myUrl/app/assets/logo.png
then i get an 404 error page.
It's served from a docker container and I saw that all files are there so the structure is as follows in
/usr/share/nginx/html/
-/
-index.html
-assets/
-------config/
-------------endpoints.json
-------images/
-------------logo.png
-polifills.js
-favicon.ico
The app was build with the --prod flag and the base href flag --base-href ./
As I see the favicon is loading and all the scripts in the main dir work fine. The problem is related to the assets dir...
Here are my files:
* nginx.conf
server {
listen 8888;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
}
Enpoints service (which is trying to get this endpoints.json
private enpoints$: Observable<Endpoint>;
private readonly ENDPOINT_URL = './assets/config/endpoints.json';
constructor(private http: HttpClient) {}
public loadEndpoints(): Observable<Endpoint> {
if (!this.enpoints$) {
this.enpoints$ = this.http.get<Endpoint>(this.ENDPOINT_URL).pipe(shareReplay(1));
}
return this.enpoints$;
}
Any suggestions?
Just figured it out. The issue was related to my nginx configuration.
I had to take the root path out of the location block so it's applicable to all locations. The official nginx pitfalls doc helped me here a lot.
Now my config file looks like that:
server {
listen 8888;
server_name localhost;
root /usr/share/nginx/html;
location / {
index index.html index.htm;
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
location /assets {
try_files $uri $uri/ /index.html;
}
}
Although I think the second block isn't needed at all. I have to check it, and will reply.
I have nginx php-fpm server for my website. I would like to use microcache for nginx. At first everything works fine. I get "hit" with curl command. Problem starts when I try to login. I tried everything but couldnt solve login problem.
I set "logged_in" cookie for 10 sec and at "cache config" I set "no-cache" for that cookie. It suppose to bypass caching while there is that cookie. I have "put" no-cache setting which is my login.
Also my website has exmple.org/?i=login so I don't now what's going on when I click login.
Main mage is cachable but login returns un-logged in main page and after refresh I became loged in user. and for logout, it logs me out but after refresh still I am loged in user. So I have no idea how to fix/bypass login process.
Server Config:
fastcgi_cache_path /usr/share/nginx/cache/fcgi levels=1:2 keys_zone=microcache:32m max_size=1024m inactive=3h;
fastcgi_cache_key $scheme$host$request_uri$request_method;
fastcgi_cache_use_stale updating error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
add_header X-Cache $upstream_cache_status;
server {
listen ip:80;
server_name example.org;
return 301 $scheme://www.example.org$request_uri;
}
server {
server_name www.example.org;
listen ip:80;
root /home/example/public_html;
index index.html index.htm index.php;
access_log /var/log/virtualmin/example.org_access_log;
error_log /var/log/virtualmin/example.org_error_log;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include /etc/nginx/example.d/cache.conf;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_cache microcache;
fastcgi_cache_key $scheme$host$request_uri$request_method;
fastcgi_cache_valid 200 301 302 30s;
#fastcgi_pass_header Set-Cookie;
#fastcgi_pass_header Cookie;
fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;
fastcgi_pass unix:/run/php/php5.6-fpm_example.sock;
fastcgi_index index.php;
include /etc/nginx/example.d/fastcgi.conf;
}
location ~* \.(jpg|jpeg|gif|css|png|js|woff|ttf|svg|ico|eot)$ {
access_log off;
log_not_found off;
expires max;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ /\. {
access_log off;
log_not_found off;
deny all;
}
include /etc/nginx/example.d/redirect.conf;
include /etc/nginx/example.d/rewrite.conf;
}
Cache Config (as include at server config):
#Cache everything by default
set $no_cache 0;
#Don't cache POST requests
if ($request_method = POST)
{
set $no_cache 1;
}
#Don't cache if the URL contains a query string
if ($query_string != "")
{
set $no_cache 1;
}
#Don't cache the following URLs
if ($request_uri ~* "/*login*|/*ajax*|/sistem/modul/login.php")
{
set $no_cache 1;
}
#Don't cache if there is a cookie called PHPSESSID
if ($http_cookie = "Logged_in")
{
set $no_cache 1;
}
EDIT: Actually after some inspections i am pretty sure that my problem is just with phpsessid. Every connection has phpsessid and nginx cache them too or completely ignore them by directives.
If i cache phpsesid and if login first with browser with admin account everyone has get admin logged in cache :D
I need a connections phpsessid should protected.
Its like nginx should clear phpsessid cookie at first and send php to fastcgi. and return of that php from fastcgi server nginx should attach same phpsessid which cleared at first.
Or its like cache php or everything without phpsessid cookie and when servering content from cache nginx should attach untouched, official phpsessid to them.
So with that way every visiter will have unique phpsessid and have cached content, which will resolve my login problems.
I can probably clear and set phpsessid. But i dont now how to save that unique/specific phpsessid and re-set it again.
Or may be its not even possible. I came up with theory and have no idea how to do :D
My nginx server if configured like this:
......
server {
# Status page
location /nginx_originserver {
stub_status on;
}
listen 80;
location ~ ^/1 {
proxy_pass http://10.10.52.126:1239;
proxy_cache api_cache;
}
......
}
In this case, when I browse http://localhost/1/thumbnail.jpg, the image file is cached. But when I change the proxy to a location which returns json like below and browse http://localhost/1/api_service, the json file is not cached, why just the image file is cached but not json, how to cache the json file?
location ~ ^/1 {
proxy_pass http://10.10.52.126:8090;
proxy_cache api_cache;
}
Did you try proxy_cache_valid 200 1d;:
location ~ ^/1 {
proxy_pass http://10.10.52.126:8090;
proxy_cache api_cache;
proxy_cache_valid 200 1d;
}
Link
I have developed video streaming application with RED5 media server(RTMP). Instead of RTMP need to stream live video through HTTP.
Any open source HTTP media server??
Is any open source server which supports both RTMP and HTTP ?
Thanks in advance.
Primarily, HTTP and RTMP are different protocols. You won't serve RTMP inside the HTTP. (Although you can do this for a tunneling solution).
Exist several ways to do HTTP Streaming. Such as HLS, DASH, Smooth and Progresive Download. If you need serve streaming to iOS (iPad, iPhone, Apple TV) you will need to use HLS.
As well as arcyqwerty said. Any HTTP server is able to serve HTTP Streaming. But you will need to prepare your media files and the manifest files before serving.
Here are some links very important for read about HLS (HTTP Live Streaming):
https://developer.apple.com/library/ios/documentation/networkinginternet/conceptual/streamingmediaguide/Introduction/Introduction.html
https://developer.apple.com/streaming/
http://features.encoding.com/http-live-streaming-hls/
https://datatracker.ietf.org/doc/html/draft-pantos-http-live-streaming-12
What about open source servers. I know these:
Flumotion: http://www.flumotion.net/
Gstreamer Server Streaming: http://cgit.freedesktop.org/gstreamer/gst-streaming-server/
Nginx HLS Module: http://nginx.org/en/docs/http/ngx_http_hls_module.html (Only Nginx Plus)
Or you can do like me and use GStreamer for segmenting and make manifest. And finaly I use the Nginx only to serve them.
I hope I helped you a little bit.
Any HTTP server that can serve files (apache, nginx, IIS, etc) can "stream" media over HTTP.
So if you want, you can keep RED5 for RTMP and set up an HTTP server to serve the same files.
You may want to look into Media streaming basics - HTTP vs RTMP for info about the protocols
Adding the nginx-rtmp module to nginx might be what you're looking for if you need a single-product solution
https://github.com/arut/nginx-rtmp-module
I use this and it works properly. (Ubuntu 12.04 TLS server)
Step by step:
sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev
wget http://nginx.org/download/nginx-1.6.0.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
tar -zxvf nginx-1.6.0.tar.gz
unzip master.zip
cd nginx-1.6.0
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master --with-http_flv_module --with-http_mp4_module
make
sudo make install
sudo /usr/local/nginx/sbin/nginx -s stop
sudo /usr/local/nginx/sbin/nginx
NGINX Config: (/usr/local/nginx/conf/nginx.conf)
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
chunk_size 4000;
# video on demand for flv files
application vod {
play /var/flvs;
}
# video on demand for mp4 files
application vod2 {
play /var/mp4s;
}
}
}
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"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name 192.168.52.16;
#charset koi8-r;
#access_log logs/host.access.log main;
# This URL provides RTMP statistics in XML
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
# XML stylesheet to view RTMP stats.
# Copy stat.xsl wherever you want
# and put the full directory path here
root /var/www/;
}
location /hls {
# Serve HLS fragments
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias /tmp/app;
expires -1;
}
# location /hds {
# f4f; # Use the HDS handler to manage requests
# # serve content from the following location
# alias /var/www/video;
# }
location /video {
mp4;
flv;
mp4_buffer_size 4M;
mp4_max_buffer_size 10M;
}
location / {
root html;
index index.html index.htm;
}
error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
}
Save the config file and:
sudo /usr/local/nginx/sbin/nginx -s stop
sudo /usr/local/nginx/sbin/nginx
Next...
Create two directories:
mkdir /var/flvs
mkdir /var/mp4s
You need copy an mp4 file to the mp4s directory. For example: sample.mp4
Finaly
sudo /usr/local/nginx/sbin/nginx -s stop
sudo /usr/local/nginx/sbin/nginx
Try:
rtmp://your_server_ip/vod2/sample.mp4
(suggest: you use the VLC media player)
or html code
<html>
<head>
<title>RTMP Video</title>
<!-- flowplayer javascript component -->
<script src="http://releases.flowplayer.org/js/flowplayer-3.2.12.min.js"></script>
</head>
<body>
<div id="player" style="width:644px;height:480;margin:0 auto;text-align:center">
<img src="images/background.jpg" height="480" width="644" /></div>
<script>
$f("player", "http://releases.flowplayer.org/swf/flowplayer-3.2.16.swf", {
clip: {
url: 'sample.mp4',
scaling: 'fit',
provider: 'hddn'
},
plugins: {
hddn: {
url: "swf/flowplayer.rtmp-3.2.13.swf",
// netConnectionUrl defines where the streams are found
netConnectionUrl: 'rtmp://your_server_ip:1935/vod2/'
}
},
canvas: {
backgroundGradient: 'none'
}
});
</script>
</body>
</html>