nginx push rtmp stream to ffmpeg - nginx

On my Raspberry Pi with camera module, I try to setup a web-based streaming platform. I want to preview the stream in my browser and use CGI scripts to start/stop broadcasting to youtube (,...).
This is how I did the streaming setup so far:
Nginx puts up an RTMP application webcam. This is where I'll send the camera and audio stream usig ffmpeg. It publishes the stream as HLS for the web preview. It's also pushing the stream to another application source. That's where I want to (occasionally) hook up another ffmpeg process for broadcasting to youtube (,...) RTMP end points.
I initiate the stream using ffmpeg like this:
ffmpeg -loglevel debug -f v4l2 -framerate 15 -video_size 1280x720 -input_format h264 -i /dev/video0 -f alsa -i hw:2 -codec:v copy -g 15 -codec:a aac -b:a 128k -ar 44100 -strict experimental -f flv "rtmp://localhost:1935/webcam/hhart"
So far everything works fine. I can preview the HLS stream using a video.js viewer on my website (also served by nginx).
Now I want to start another ffmpeg process for broadcasting to my youtube channel, hooked up to the source application like this:
ffmpeg -loglevel debug -f flv -listen 1 -i rtmp://localhost:1935/source/hhart -c copy 'rtmp://a.rtmp.youtube.com/live2/<KEY>'
(in the final setup, launching and killing this process will be done via CGI scripts)
This is what ffmpeg returns:
Opening an input file: rtmp://localhost:1935/source/hhart.
[flv # 0x2032480] Opening 'rtmp://localhost:1935/source/hhart' for reading
[rtmp # 0x2032a10] No default whitelist set
[tcp # 0x20330f0] No default whitelist set
and then... nothing happens. There's no stream coming in at Youtube studio, but there are no error messages either.
Some other tests I did:
from the webcam application, push directly to the Youtube RTMP => that works! (but it's not what I want, because I want the HLS stream to be online always, but the broadcasting only when I'm going live.)
from VLC display the stream at rtmp://localhost:1935/source/hhart => similar to ffmpeg, there's no error message, the progress bar keeps loading.
So I have the impression that there is something going on, but there's no actual data transmitted.
RTMP section in nginx.conf:
rtmp {
server {
listen 1935;
chunk_size 4000;
application webcam {
live on;
hls on;
hls_path /Services/Webcam/HLSStream;
hls_fragment 3;
hls_playlist_length 60;
#deny play all;
push rtmp://localhost:1935/source/;
#push rtmp://a.rtmp.youtube.com/live2/<KEY>;
}
application source {
live on;
record off;
}
}
}
Of course, I may be totally on the wrong track, so any suggestions how I can realize my requirements in a better way, are welcome!

OK, I recompiled nginx with --with-debug and that got me to a solution.
Rather than pushing the stream to another application, I have to push the stream to an RTMP address on another port, and there the second ffmpeg process can pick it up. And it seems to be better to use 127.0.0.1 instead of localhost.
Like this:
rtmp {
server {
listen 1935;
chunk_size 4000;
application webcam {
live on;
hls on;
hls_path /Services/Webcam/HLSStream;
hls_fragment 3;
hls_playlist_length 60;
#deny play all;
push rtmp://127.0.0.1:1936/test/; # ADDED
record off;
}
}
}
Launching the broadcast to youtube:
ffmpeg -loglevel debug -f flv -listen 1 -i rtmp://127.0.0.1:1936/test/ -c copy -f flv 'rtmp://a.rtmp.youtube.com/live2/<KEY>'
Now my HLS stream is always online, and I can control broadcasting to youtube by launching/killing the second ffmpeg process.

Related

How to convert cctv footage to h265 for streaming and recording in nginx-rtmp module?

I am using the nginx-rtmp-module here to pull an rtsp stream from a camera on local network and convert it to rtmp. This rtmp stream is then converted to hls and made available for livestreaming. It is also being recorded in 5 min segments. (these things can all be seen in the nginx.conf below).
I want to change the video codec to h265 to save storage space, since each 5 min video is ~230mb, and using opencv and python, I was able to get <100mb per 5 min video using h265, so I know there is a lot of space for storage saving.
How can I change the codec of the stream to h265?
I have tried installing libx265-dev and setting -vcodec libx265, however this tells me flv is an invalid container and I'm getting nowhere with finding a valid container for streaming + recording.
My nginx.conf:
rtmp {
server {
listen 1935; # Listen on standard RTMP port
application relay {
live on;
hls on;
hls_path /tmp/hls;
hls_fragment 15s;
exec_static /usr/bin/ffmpeg -i rtsp://test:test#192.168.100.10:8554/fhd -vcodec copy -f flv rtmp://localhost:1935/relay/fhd;
# record block
record video;
record_path /tmp/hls;
record_unique on;
record_interval 5m;
}
}
}
The RTMP protocol does not have support for the h.265 codec. There is no standard way to do this.

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!

NGINX RTMP Live Streaming Input/output error using on_publish to access external microservice

Nginx.conf
rtmp {
server {
listen 1935;
chunk_size 4000;
application stream {
live on;
#exec ffmpeg -i rtmp://localhost:1935/stream/$name -codec copy -f flv rtmp://$name-live-encoder/play;
on_publish http://<hostName>:<port>/auth/validate;
exec ffmpeg -re -i rtmp://localhost:1935/stream/$name -codec copy -bsf:v h264_mp4toannexb -f mpegts udp://live-${name}-udp-encoder-service.rtmp-live-test:3555;
}
}
}
Incoming RTMP stream : rtmp://host:port/stream/ksptv?secret=234rfghi4e
Microservice : http://HOSTNAME/auth/validate?name=ksptv&secret=234rfghi4e ==> will return 201 if the secret Key matches with channel or 403 if it doesnt match ..
when the RTMP is getting streamed , the stream is exited with I/O error
input rtmp stream logs
rtmp://rtmpHOST/stream/qptv-ind1?secret=hYn4cyWW56WdAhLussHkUw==:
Input/output error [AVIOContext # 0x2291f00] Statistics: 199663 bytes
read, 0 seeks
The on_publish is not processing or hitting the microservice when using as below
on_publish http://<hostName>:<port>/auth/validate;
But when I implement on_publish with localhost/auth and have server block defined in nginx.conf with location /auth {return 201} , rtmp streaming is successful
Can you please help me to understand why on_publish is not working with external url/api.

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.

HLS using Nginx RTMP Module not working

So I installed NGINX and the RTMP MODULE on my mac in the usr/local/nginx location. RTMP stream works fine just not the HLS version. Here is my config file:
events {
worker_connections 1024;
}
rtmp {
server {
listen 1936;
chunk_size 4000;
application small {
live on;
# Video with reduced resolution comes here from ffmpeg
}
# video on demand
application vod {
play /var/flvs;
}
application vod2 {
play /var/mp4s;
}
# Many publishers, many subscribers
# no checks, no recording
application videochat {
live on;
# The following notifications receive all
# the session variables as well as
# particular call arguments in HTTP POST
# request
# Make HTTP request & use HTTP retcode
# to decide whether to allow publishing
# from this connection or not
on_publish http://localhost:8080/publish;
# Same with playing
on_play http://localhost:8080/play;
# Publish/play end (repeats on disconnect)
on_done http://localhost:8080/done;
# All above mentioned notifications receive
# standard connect() arguments as well as
# play/publish ones. If any arguments are sent
# with GET-style syntax to play & publish
# these are also included.
# Example URL:
# rtmp://localhost/myapp/mystream?a=b&c=d
# record 10 video keyframes (no audio) every 2 minutes
record keyframes;
record_path /tmp/vc;
record_max_frames 10;
record_interval 2m;
# Async notify about an flv recorded
on_record_done http://localhost:8080/record_done;
}
# HLS
# For HLS to work please create a directory in tmpfs (/tmp/hls here)
# for the fragments. The directory contents is served via HTTP (see
# http{} section in config)
#
# Incoming stream must be in H264/AAC. For iPhones use baseline H264
# profile (see ffmpeg example).
# This example creates RTMP stream from movie ready for HLS:
#
# ffmpeg -loglevel verbose -re -i movie.avi -vcodec libx264
# -vprofile baseline -acodec libmp3lame -ar 44100 -ac 1
# -f flv rtmp://localhost:1935/hls/movie
#
# If you need to transcode live stream use 'exec' feature.
#
application hls {
live on;
hls on;
hls_path /tmp/hls;
}
# MPEG-DASH is similar to HLS
application dash {
live on;
dash on;
dash_path /tmp/dash;
}
}
}
# HTTP can be used for accessing RTMP stats
http {
server {
listen 8080;
# This URL provides RTMP statistics in XML
location /stat {
rtmp_stat all;
# Use this stylesheet to view XML as web page
# in browser
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 /path/to/stat.xsl/;
}
location /hls {
# Serve HLS fragments
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
}
location /dash {
# Serve DASH fragments
root /tmp;
add_header Cache-Control no-cache;
}
}
}
I am using the hls application to stream to. When I view the stream located at rtmp://ip:1936/hls/test i can see it fine. When I try and view http://ip:1936/hls/test.m3u8 I cannot see it. I created a folder in this location for hls /usr/local/nginx/tmp/hls. Im wondering if this is in the right place as nothing is being created in the folder? Could it be permission issues?
I am using OBS to stream which uses x246 encoding video but not sure if it's AAC for audio.
A similar issue is being had here: https://groups.google.com/forum/#!topic/nginx-rtmp/dBKh4akQpcs
but no answer :(.
Any help is appreciated. Thanks.
you content for HLS is over port 8080 and rtmp is over 1936
meaning that rtmp://ip:1936/hls/test
or http://ip:8080/hls/test.m3u8
I got it fixed by changing to recording, with the following settings:
next to that, I also changed what JPhix mentioned.
seeing your config, but you place files under /tmp folder not under /usr/local/nginx (full path). If problem persists , an good strategy is start with one application with all of codecs (hls,mpeg-dash) ( like the config examples in github ).
P.D: this module is only for h264 and aac

Resources