nginx-rtmp-module icon indicating copy to clipboard operation
nginx-rtmp-module copied to clipboard

Simple redirect (publisher)

Open lossius30 opened this issue 10 years ago • 61 comments

Hello,

I would make a simple redirect (to other server) when a user begins broadcasting.

The problem is that a "push xxx", the stream is redirected to all those push servers, when my goal is to redirect the user to a single server.

When the user start broadcast, i try to redirected with a header Location: rtmp://x.x.x.x/app/test

nginx.conf : rtmp { server { listen 1935; ping 30s; notify_method post;

        application app {
            live on;
            notify_update_timeout 15s;
            on_publish http://x.x.x.1/publishStart;
        }
    }
}

The script located at http://x.x.x.1/publishStart make some stuff and end with an header Location: rtmp://x.x.x.2/app/test

The following error occur, nginx-error.log: 2015/07/04 14:17:38 [error] 27994#0: *35 notify: push 'test' to 'rtmp://x.x.x.x:1935/app/test', client: x.x.x.x, server: 0.0.0.0:1935 2015/07/04 14:17:38 [error] 27994#0: relay: no address

Any help would be appreciated

Thanks

lossius30 avatar Jul 04 '15 12:07 lossius30

Check location url:

  • must contain IP, not domain
  • no spaces between header key and value -- "Location:rtmp://123.45.6.7/app/stream"

sergey-dryabzhinsky avatar Jul 05 '15 06:07 sergey-dryabzhinsky

Thanks for your answer.

I tried Location:rtmp://123.45.6.7/app/stream and Location:rtmp://123.45.6.7/app/stream/ but always the same result

2015/07/04 14:17:38 [error] 27994#0: *35 notify: push 'test' to 'rtmp://x.x.x.x/app/stream', client: x.x.x.x, server: 0.0.0.0:1935 2015/07/04 14:17:38 [error] 27994#0: relay: no address

lossius30 avatar Jul 05 '15 09:07 lossius30

What version nginx and rtmp module you running?

Can you switch rtmp log to debug level for test?

error_log /var/log/nginx/rtmp-error.log debug;

And after testing look for lines like these:

2015/07/05 20:02:40 [info] 31912#0: *1 notify: publish 'localhost/publish-redirect.php', client: x.x.x.x, server: 0.0.0.0:1935
... skip ...
2015/07/05 20:02:40 [debug] 31912#0: *1 notify: HTTP retcode: 3xx
2015/07/05 20:02:40 [debug] 31912#0: *1 notify: publish redirect received
2015/07/05 20:02:40 [error] 31912#0: *1 notify: push 'test/path' to 'rtmp://127.0.0.1/rtmp-slow', client: x.x.x.x, server: 0.0.0.0:1935
2015/07/05 20:02:40 [info] 31912#0: *1 relay: create push name='test/path' app='' playpath='' url='127.0.0.1/rtmp-slow', client: x.x.x.x, server: 0.0.0.0:1935
2015/07/05 20:02:40 [debug] 31912#0: relay: create remote context

To test rtmp redirect I wrote simple php script: publish-redirect.php

<?php
header("HTTP/1.0 302 Publish Here");
header("Location: rtmp://127.0.0.1/rtmp-slow");

No other output is generated.

And add it into application section:

        application rtmp {
            live on;

... skip ...

            on_publish http://localhost/publish-redirect.php;

... more lines ...

      }

sergey-dryabzhinsky avatar Jul 05 '15 17:07 sergey-dryabzhinsky

Thank you ! I will test this tomorrow, i come back after testing :)

lossius30 avatar Jul 05 '15 20:07 lossius30

Update:

  • nginx uses POST in notify request by default, script should get in $_POST:
array (
    'call' => 'publish',
    'app' => 'rtmp',           // only with https://github.com/arut/nginx-rtmp-module/pull/649
    'name' => 'test/path',
    'type' => 'live'
)
  • I publish stream with ffmpeg:
ffmpeg -f alsa -i pulse -f v4l2 -framerate 15 -video_size 640x360 -i /dev/video0 \
 -c:v libx264 -threads 0 -pix_fmt yuv420p -g 20 -profile:v main -b:v 500k \
 -tune zerolatency -movflags +faststart \
 -c:a libfdk_aac -b:a 64k -ar 44100 -cutoff 19000 -ac 1 \
 -f flv "rtmp://nginx-domain-name app=rtmp playpath=test/path live=1 timeout=0 buffer=0"

sergey-dryabzhinsky avatar Jul 05 '15 20:07 sergey-dryabzhinsky

Hello, thank you again for your answer.

I'm stupid, i didn't check nginx version, i use 1.2.4....

I compile nginx 1.9.2 and try again !

lossius30 avatar Jul 06 '15 15:07 lossius30

THANK YOU VERY MUCH

it's been several days that I was looking to solve the problem ... A BEER 4 YOU :)

However, the behavior is not what I expected, I thought the redirect would send the stream to the new address, but the server creates a relay A to Server B, if A nginx server is stopped, the stream is interrupted.

And the notifications (publish, publish_done etc...) are triggered to server A and server B.

After going through all the documentation and probably the internet, I think it is impossible to make a real redirection with this rtmp module.

It's a shame we do not know what relay may consumes (bandwidth, processor, ram...), I imagine that with 1,000 or more users, server A is bound to be overloaded at one time or another ...

lossius30 avatar Jul 06 '15 16:07 lossius30

Ah, you need the nginx to send rtmp-redirect command to clients and publisher? Not to relay incoming streams.

For now it should be done by client-side I think. Something like back-end notify handler to cometh/websocket + cometh/websocket/js command-to-flash handler on client.

sergey-dryabzhinsky avatar Jul 06 '15 17:07 sergey-dryabzhinsky

sorry for my explanation, I'm French, i will try to explain more clearly.

My goal is to do some sort of load balancing : one ingest server treat new connections and find available slot on server #X, then i start ffmpeg process on many other servers who connect on the ingest server to output via HLS and other formats & treatments.

Step by step for the broadcaster :

  1. Connect to hello.mydomain.com
  2. hello.mydomain.com search for available slot
  3. hello.mydomain.com redirect broadcaster to server A, B, C...

It's like twitch.tv, but not for gamers :)

Thank you if you can help again !

lossius30 avatar Jul 06 '15 19:07 lossius30

The problem with

header("HTTP/1.0 302 Publish Here"); header("Location: rtmp://127.0.0.1/rtmp-slow");

Is the first nginx server continue to handle the stream after redirecting, so the stream is "duplicated" and dependent of main ingest server, if the main ingest server die, all the streams die :s

lossius30 avatar Jul 06 '15 19:07 lossius30

@lossius30 I wish to do the same thing, unfortunately nginx-rtmp doesn't do that as far as I know. It will only relay as you've found out. Unless I've missed something.

VackerSimon avatar Jul 06 '15 20:07 VackerSimon

Yes, nginx-rtmp don't send RTMP redirect command, just pass stream through self.

If ffmpeg support such thing - may be it is possible to patch nginx-rtmp to support RTMP-redirect. If redirecting is supported by RTMP protocol.

sergey-dryabzhinsky avatar Jul 06 '15 20:07 sergey-dryabzhinsky

Update: Adobe FMS 3 have this:

application.redirectConnection(clientObj, url[, description[, errorObj]])

Rejects a connection and provides a redirect URL. You must write logic in the 
NetConnection.onStatus() handler that detects redirection and passes the new connection URL to the 
NetConnection.connect() method.

And it passes data to client:

Property Value
info.code "NetConnection.Connect.Rejected"
info.description The value passed in the description parameter; if no value is passed in the parameter, the default value is "Connection failed"
info.ex.code 302
info.ex.redirect The new connection URL
info.level "Error"

Now the question is how to simulate this, and will ffmpeg, FMLE and others support such thing.

sergey-dryabzhinsky avatar Jul 06 '15 21:07 sergey-dryabzhinsky

And don't forget about HLS/DASH clients - they need to be redirected too.

sergey-dryabzhinsky avatar Jul 06 '15 21:07 sergey-dryabzhinsky

You can try this branch of my fork: https://github.com/sergey-dryabzhinsky/nginx-rtmp-module/tree/add-publisher-redirect-support

It's not tested and experimental. Trying to send onStatus like FMS do. HLS/DASH redirect not supported, just RTMP.

Compile nginx with that version of module, add new option to config:

notify_send_redirect = 1;

And try to redirect stream.

sergey-dryabzhinsky avatar Jul 07 '15 13:07 sergey-dryabzhinsky

@sergey-dryabzhinsky thank you, i will test this, i don't need to redirect viewers or ffmpeg stream, because the redirect will be performed only when the publisher connect, i try and come back :)

lossius30 avatar Jul 07 '15 18:07 lossius30

Hi, after a long week I can finally try your branch of the module.

I tried to compile but an error occured : line 1059 and 1061 (unused var) In function ‘ngx_rtmp_live_data’: /nginx-rtmp-module/ngx_rtmp_live_module.c:1059:37: error: unused variable ‘msg_type’ [-Werror=unused-variable]

So i opened the file, commented the line and started new compilation, another error occured : /nginx-rtmp-module/ngx_rtmp_stat_module.c: In function ‘ngx_rtmp_stat_live’: /nginx-rtmp-module/ngx_rtmp_stat_module.c:524:41: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]

But for this, i was unable to fix the error for (rn = 0; rn < rctx->rec.nelts; ++rn, ++recctx) {

i think rn is signed and rec.nelts is unsigned, but do you know what to do ?

Thanks

lossius30 avatar Jul 12 '15 09:07 lossius30

Seems you are using 'master' branch, not 'add-publisher-redirect-support'.

sergey-dryabzhinsky avatar Jul 12 '15 17:07 sergey-dryabzhinsky

Hello,

I tried with the add-publisher-redirect-support branch, but the result is the same.

Commands : cd ~/build/nginx git clone -b add-publisher-redirect-support git://github.com/sergey-dryabzhinsky/nginx-rtmp-module.git wget http://nginx.org/download/nginx-1.9.2.tar.gz tar xzf nginx-1.9.2.tar.gz cd nginx-1.9.2

./configure --prefix=/home/oneill/bin/nginx --error-log-path=/home/oneill/logs/nginx-error.log --http-log-path=/home/oneill/logs/nginx.log --user=oneill --group=www-data --add-module=/home/oneill/build/nginx/nginx-rtmp-module --with-http_ssl_module

make

Result : /home/oneill/build/nginx/nginx-rtmp-module/ngx_rtmp_live_module.c: In function ‘ngx_rtmp_live_data’: /home/oneill/build/nginx/nginx-rtmp-module/ngx_rtmp_live_module.c:1059:37: error: variable ‘msg_type’ set but not used [-Werror=unused-but-set-variable] cc1: all warnings being treated as errors make[1]: *** [objs/addon/nginx-rtmp-module/ngx_rtmp_live_module.o] Error 1 make[1]: Leaving directory `/home/oneill/build/nginx/nginx-1.9.2' make: *** [build] Error 2

lossius30 avatar Jul 13 '15 15:07 lossius30

I fixed the first error in ngx_rtmp_live_module.c @ 1059

Then retry make, new error : /home/oneill/build/nginx/nginx-rtmp-module/ngx_rtmp_relay_module.c: In function ‘ngx_rtmp_relay_create_connection’: /home/oneill/build/nginx/nginx-rtmp-module/ngx_rtmp_relay_module.c:504:5: error: value computed is not used [-Werror=unused-value] cc1: all warnings being treated as errors make[1]: *** [objs/addon/nginx-rtmp-module/ngx_rtmp_relay_module.o] Error 1 make[1]: Leaving directory `/home/oneill/build/nginx/nginx-1.9.2' make: *** [build] Error 2

So i opened the file ngx_rtmp_relay_module.c @ 504 : ngx_cpymem(&rs->app, &rctx->app, sizeof(rctx->app));

but i was unable to fix the error, i think this is the last, but i can't do anything, any idea ?

Thanks

lossius30 avatar Jul 13 '15 15:07 lossius30

What system you are using? Compiler, version, CFLAGS? It's like your build environment treat all warnings like errors.

sergey-dryabzhinsky avatar Jul 13 '15 19:07 sergey-dryabzhinsky

my dedicated server run under Debian Wheezy x64, compilers : ii g++ 4:4.7.2-1 amd64 GNU C++ compiler ii g++-4.7 4.7.2-5 amd64 GNU C++ compiler ii gcc 4:4.7.2-1 amd64 GNU C compiler ii gcc-4.7 4.7.2-5 amd64 GNU C compiler

it's an fresh and up to date install, and i didn't configured anything to treat all warnings as errors... i don't know what the fuck is happening !

Thank you again for your patience and your help, it's really appreciated :D

lossius30 avatar Jul 14 '15 00:07 lossius30

Try to unset vars before build:

unset CFLAGS CXXFLAGS LDFLAGS
export CFLAGS="-O2 -pipe"
export LDFLAGS="-Wl,--as-needed"
CFLAGS="${CFLAGS}" CORE_LINK="${LDFLAGS}" ./configure ... long line of enabled modules ...
make -j2

And maybe nginx-1.9 is too fresh. Try 1.8 version.

sergey-dryabzhinsky avatar Jul 14 '15 02:07 sergey-dryabzhinsky

If you have a bespoke client/publisher app this could check for available slots on a server and then return the publisher/client url to be used.

pdashford avatar Jul 14 '15 05:07 pdashford

@sergey-dryabzhinsky do you know if chat could be added to the rtmp module?

pdashford avatar Jul 14 '15 05:07 pdashford

@paulashford1975 Please open new issue about that.

sergey-dryabzhinsky avatar Jul 14 '15 08:07 sergey-dryabzhinsky

hi :)

@paulashford1975 by app you mean program used to broadcast like open broadcaster software ? if you mean that, no i don't have, and i don't want the users have to change app url each time. They select the closest server and that's all

@sergey-dryabzhinsky I installed nginx 1.8.0, unsetted vars, compiled again and this time, the installation is good, but when i try to redirect the stream to server B, this is the same as nginx rtmp module by arut, the publish command is triggered on server B but if i stop nginx of server B, the stream continue, if i stop nginx of server A, the stream is disconnected.

Do you how twitch work ? did they use the relay method ?

lossius30 avatar Jul 14 '15 13:07 lossius30

And what in debug log? There must be line: notify: send 302 redirect for stream 'blahblah' to new location 'some-rtmp-url'

sergey-dryabzhinsky avatar Jul 14 '15 14:07 sergey-dryabzhinsky

yep forgot to add log entry !

Server A : 2015/07/14 16:30:10 [info] 28948#0: *1 client connected '89.91.146.92' 2015/07/14 16:30:10 [info] 28948#0: *1 connect: app='app' args='' flashver='FMLE/3.0 (compatible; FMSc/1.0)' swf_url='rtmp://dev-rbx.lossius.ovh/app' tc_url='rtmp://dev-rbx.lossius.ovh/app' page_url='' acodecs=0 vcodecs=0 object_encoding=0, client: 89.91.146.92, server: 0.0.0.0:1935 2015/07/14 16:30:10 [info] 28948#0: *1 createStream, client: 89.91.146.92, server: 0.0.0.0:1935 2015/07/14 16:30:10 [info] 28948#0: *1 publish: name='test' args='' type=live silent=0, client: 89.91.146.92, server: 0.0.0.0:1935 2015/07/14 16:30:10 [info] 28948#0: *1 notify: publish 'dev-rbx.lossius.ovh/publishStart', client: 89.91.146.92, server: 0.0.0.0:1935 2015/07/14 16:30:10 [error] 28948#0: *1 notify: push 'test' to 'rtmp://5.135.155.223/app/test', client: 89.91.146.92, server: 0.0.0.0:1935 2015/07/14 16:30:10 [info] 28948#0: *1 relay: create push name='test' app='' playpath='' url='5.135.155.223/app/test', client: 89.91.146.92, server: 0.0.0.0:1935

Server B : 2015/07/14 16:32:58 [info] 1867#0: *1 client connected '91.121.160.63' 2015/07/14 16:32:58 [info] 1867#0: *1 connect: app='app' args='' flashver='LNX.11,1,102,55' swf_url='' tc_url='rtmp://5.135.155.223/app' page_url='' acodecs=3575 vcodecs=252 object_encoding=0, client: 91.121.160.63, server: 0.0.0.0:1935 2015/07/14 16:32:58 [info] 1867#0: *1 createStream, client: 91.121.160.63, server: 0.0.0.0:1935 2015/07/14 16:32:58 [info] 1867#0: *1 publish: name='test' args='' type=live silent=0, client: 91.121.160.63, server: 0.0.0.0:1935 2015/07/14 16:32:58 [info] 1867#0: *1 notify: publish 'dev-rbx-i01.lossius.ovh/publishStart', client: 91.121.160.63, server: 0.0.0.0:1935 2015/07/14 16:33:13 [info] 1867#0: *1 notify: update 'dev-rbx-i01.lossius.ovh/publishUpdate', client: 91.121.160.63, server: 0.0.0.0:1935 2015/07/14 16:33:16 [info] 1867#0: *1 disconnect, client: 91.121.160.63, server: 0.0.0.0:1935 2015/07/14 16:33:16 [info] 1867#0: *1 deleteStream, client: 91.121.160.63, server: 0.0.0.0:1935 2015/07/14 16:33:16 [info] 1867#0: *1 notify: publish_done 'dev-rbx-i01.lossius.ovh/publishDone', client: 91.121.160.63, server: 0.0.0.0:1935

89.91.146.92 is ip of publisher, 91.121.160.63 is the ip of server A

lossius30 avatar Jul 14 '15 14:07 lossius30

Did you set notify_send_redirect = 1; in server A config? Did you send 302 http code in notify response?

sergey-dryabzhinsky avatar Jul 14 '15 15:07 sergey-dryabzhinsky