Nginx RTMP with Flask - nginx

I have followed along the documentation/tutorial on how to set up the config file for RTMP streaming from here: https://www.nginx.com/blog/video-streaming-for-remote-learning-with-nginx/ and it is pretty straight forward. However, I am not sure how I can have my backend built on Flask to redirect the stream to some HLS/DASH video player that is embedded in an HTML template that is sent in response to a client that requested for a specific HTTP endpoint. The tutorial shows how to view locally in a VLC media player but not how to embed it in an HTML file that gets sent to the client. How would I go about doing this? For reference, I am hosting my website on Heroku that is set up with its Nginx buildpack from here, https://github.com/heroku/heroku-buildpack-nginx, and I am not sure if I need to have Heroku install additional dependencies to set up an RTMP server and listen for a stream.

Use the HLS protocol (HTTP Live Streaming).
Nginx knows how to render HTTP perfectly. So, you just need to create and update the playlist and fragments of the HLS stream, as well as monitor the removal of old fragments. To do this, there is a nginx-rtmp-hls module. It is located in the hls directory, but it is not collected by default since requires the libavformat library included in the ffmpeg package. To build nginx with HLS support, you need to add this module explicitly during configuration:
./configure --add-module=/path/to/nginx-rtmp-module --add-module=/path/to/nginx-rtmp-module/hls
To generate HLS, just specify the following directives:
application myapp {
live on;
hls on;
hls_path /tmp/hls;
hls_fragment 5s;
}
And finally, in the http {} section, configure the return of everything related to HLS:
location /hls {
root /tmp;
}
To show stream in browser create html page with such content (example):
<video width="600" height="300" controls="1" autoplay="1" src="http://example.com/hls/mystream.m3u8"></video>
Update 1:
You attached link on Nginx setup tutorial, so i'm referencing on their "Compiling NGINX with the RTMP Module" step with changes related to HLS module:
$ cd /path/to/build/dir
$ git clone https://github.com/arut/nginx-rtmp-module.git
$ git clone https://github.com/nginx/nginx.git
$ cd nginx
$ ./auto/configure --add-module=../nginx-rtmp-module --add-module=../nginx-rtmp-module/hls
$ make
$ sudo make install

Related

How to do reverse DNS lookup in Nginx

I have Nginx configuration where I want to allow a DNS name as I cant be certain on IP address.
{
satisfy any;
allow www.domain.com; // want to achieve this
}
With Nginx we cant achieve this.
Looked at this https://github.com/flant/nginx-http-rdns as a solution.
This module says it does reverse lookup but it didnt work and repo is very old and well maintained.
Another alternative is to use a shell script and do a dig or host on IP address but we dont want to use shell script with Nginx.
Alternate solution is to use a side car to do the DNS resolution and to add allow/deny rules.
If this still works you'll need to compile it for the same version of nginx that is installed. If you're using nginx from a repo then dynamically compile it and see if the following helps:
Download nginx src matching installed version and extract it.
$ cd nginx-1.x.x
$ ./configure --with-compat --add-dynamic-module=/path/to/nginx_module
$ make modules
make modules should result in a nginx module that you need to copy to /usr/lib/nginx/modules/ and load it with load_module modules/modulename.so in your nginx.conf.

How to make Nginx HLS application pull RTMP on request

This is my situation: I want to use Nginx to serve streams over HTTP using HLS. The thing is, I want the HLS streams to be generated/started when I get a request for them.
I can successfully achieve this behavior with RTMP, as I have the following config file
application myApp {
live on;
exec_pull myScript.sh $app $name;
exec_kill_signal term;
}
In my myScript.sh file I have something like this:
ffmpeg -i sourceLink.m3u8 -codec copy -bsf:a aac_adtstoasc -f flv rtmp://localhost/$APP/$NAME;
So that when I request rtmp://myAddress/myApp/someLink it works perfectly.
However, I want to stream HLS instead of RTMP. I have seen other solutions that do this by having an application that starts the RTMP module and pushes it to the HLS application. However, what I want is that when I recieve a request for an HLS stream THEN the RTMP is started (which starts the FFmpeg), and as soon as the requests for the stream are over the RTMP stops receiving requests and thus stops the FFmpeg.
Here is my config file with what I have tried so far:
application myHLSApp {
live on;
pull rtmp://localhost:1935/myApp/someLink name=test static;
# 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;
}
My main objective is to start the FFmpeg in myScript.sh ONLY when it is needed to then stream that incoming file as HLS from my machine. Any ideas?
Thanks a lot for the help!

Upload file to Nginx with cURL

All,
I'm trying to upload a local file to my remote Nginx server via cURL. I have built Nginx from source with the upload module and the DAV module. At the bottom of the Nginx page, there is an example form to upload a file. I'm not sure how I would implement the form, and (several) Google searches have returned little helpful information about uploading directly to Nginx via cURL.
Current tech stack:
Nginx
Green Unicorn
Flask
Of all the different avenues I've tried, the following is the one that seems the most appropriate for the task.
curl -X POST -F "image=#example.gif" http://54.226.64.199/upload
However, the response is underwhelming.
I've tried --uploade-file as well, the response is a 405. From what I've read, upload only accepts a POST command, not PUT, hence why I get a 405.
I don't need a full solution (would be great!), only pointing in the right direction.
Any help is appreciated. Thanks
EDIT: sorry wanted to include part of my .conf
location /upload {
upload_store /tmp;
#upload_pass #none;
upload_store_access all:rw;
upload_cleanup 400 404 499 500-505;
}
You can do this by specifying filename into URL, without using any external module :
location ~ "/upload/([0-9a-zA-Z-.]*)$" {
alias /storage/www/upload/$1;
client_body_temp_path /tmp/upload_tmp;
dav_methods PUT DELETE MKCOL COPY MOVE;
create_full_put_path on;
dav_access group:rw all:r;
}
And use : curl -T example.gif http://54.226.64.199/upload/example.gif

Streaming from a webcam through Nginx to videojs without flash

Has anyone managed to use ffmpeg to stream from a webcam, and then serve this using nginx to a page running videojs. I can't believe this isn't possible without using flash.
I'd like a pure html5 solution without any flash, and I've tried using rtmp.
I can pick up the rtmp stream using vlc, I've got the page with videojs working, but I can't work out how to link it all up. I'm doing this from a rpi3, so have been using the hardware encoder,
ffmpeg -f video4linux2 -i /dev/video0 -c:v h264_omx -c:a copy -b:v 1500k rtmp://localhost/hls/movie
Here was the rtmp nginx setup, I'd compiled it as a module into nginx(module on git hub);
rtmp {
server {
listen 1935;
ping 30s;
notify_method get;
application hls {
live on;
# sample HLS
hls on;
hls_path /tmp/hls;
}
}
}
Thanks
Ok, tried 3 methods, using rasbian stretch on a Pi+ over wireless, with a logitech C270 webcam for use as a baby monitor;
Rtmp
ffserver
motion
Rmtp worked slowly but uses flash, so was unacceptable
I couldn't get ffserver to work at all and it's being deprecated ffserver deprecation notice.
Motion worked fine, good resolution and frame rate, as well as low latency.
Just adding this to try and stop other people trying other solutions before hitting one that worked for me anyway.

Can I use Clojure with nginx?

This is a follow up to my question here. I've set up a home server (just my other laptop running ubuntu and nginx) and I want to serve clojure files.
I am asking help for understanding how this process works. I am sorry at this point I am confused and I think I need to start over. I am asking a new question because I want to use nginx not lein ring server, as suggested in the answer for that question.
First I started a project guestbook with leiningen and I ran lein ring server and I see "Hello World" at localhost:3000. As far as I understand this has nothing to do with nginx!
How does nginx enter in this process? At first I was trying to create a proxy server with nginx and that worked too, but I did not know how serve clojure files with that setup.
This is what I have in my nginx.conf file adapted from this answer:
upstream ring {
server 127.0.0.1:3000 fail_timeout=0;
}
server {
root /home/a/guestbook/resources/public;
# make site accessible from http://localhost
server_name localhost;
location / {
# first attempt to serve request as file
try_files $uri $uri/ #ring;
}
location #ring {
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_pass http://ring;
}
location ~ ^(assets|images|javascript|stylesheets|system)/ {
expires max;
add_header Cache-Control public;
}
}
So I want to use my domain example.com (not localhost); how do I go about doing this?
EDIT
As per #noisesmith's comment I will opt to go with lein uberjar option. As explained here, it appears very easy to create one:
$ lein uberjar
Unpacking clojure-1.1.0-alpha-20091113.120145-2.jar
Unpacking clojure-contrib-1.0-20091114.050149-13.jar
Compiling helloworld
[jar] Building jar: helloworld.jar
$ java -jar helloworld.jar
Hello world!
Can you also direct me to the right documentation about how I can use this uberjar with nginx?
Please try Nginx-Clojure module. You can run clojure Ring handlers with Nginx without any Java Web Server, eg. Jetty.
For starters, don't use lein to run things in production. You can use lein uberjar to create a jar file with all your deps ready to run, and java -jar to run the app from the resulting jar. There is also the option of running lein ring uberwar to create a war archive to be run inside tomcat, which provides some other conveniences (like log rotation and integration with /etc/init.d as a service etc. on most Linux systems).
nginx sits in front of your app, on port 80. It will serve up the content by proxying your app. This is useful because nginx has many capabilities (especially regarding security) that you then don't need to implement in your own app, including optional integration with https and selinux integration. Using nginx in front of your app also prevents you from needing to run java as root (typically only the root user can use port 80). Furthermore you can let nginx serve static assets directly, rather than having to serve them from your app.

Resources