RTP Forwarding, ffmpeg SDP

5,841 views
Skip to first unread message

Geige V

unread,
Jun 15, 2016, 4:38:08 PM6/15/16
to meetecho-janus
Hello,

I'm very new to Janus and programming in general, but with all these awesome resources I'm having a blast working with Janus --- thanks!

My goal is to forward RTP data from a user in the the videoroom plugin to the nginx rtmp module and use ffmpeg to convert the RTP data to RTMP or HLS.
Using past forum posts and the API docs, I have managed to accomplish the first part of this and am successfully forwarding RTP data to my server using
this command :

 curl -H "Content-Type: application/json" -X POST -d '{"body":{"request":"rtp_forward","publisher_id":2186766636,"room":1234,"host":"127.0.0.1","audio_port":5000,"video_port":5002,"secret":"adminpwd"},"janus":"message","apisecret" : "janusrocks","transaction":"o4vup0qoomd"}'

The part that is stumping me is the SDP file, which even after a decent amount of research, I still have an admittedly limited understanding of. From forum posts, I gather that the SDP is usually sent at the beginning of a stream so that something like FFMPEG understands what it is receiving; however, the rtp forward feature does not send this so I need to create my own. The one I'm using, janus.sdp, is listed below:

v=0
o=- 0 0 IN IP4 127.0.0.1
s=RTP Video
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 56.15.102
m=video 5002 RTP/AVP 100

a=rtpmap:100 VP8/90000
a=fmtp:100 packetization-mode=1


I have this file stored in the /var/sdp directory that nginx has access to. In the actual nginx-rtmp module, I have the following code that uses this sdp file:

application rtcapp {
                        live on;
                        record off;

                        exec_pull ffmpeg -i /var/sdp/janus.sdp -vcodec libx264 -acodec libmp3lame rtmp://localhost/live;

                }


Hopefully I am on the right track and not doing anything egregiously silly. Perhaps this question is more appropriate for a nginx-rtmp or ffmpeg forum, but I have found significantly more posts here that are related to my question. If someone could let me know if I'm on the right track, offer some tips, or direct me to some helpful docs, I would greatly appreciate it.

Again, thanks so much to everyone involved with this project. I have learned so much about WebRTC and network programming just in the last month because of great open source projects like this.

Geige V

unread,
Jun 15, 2016, 8:21:27 PM6/15/16
to meetecho-janus
I managed to get it working by switching the nginx command to this:

exec_pull ffmpeg -i /var/sdp/janus.sdp -vcodec libx264 -acodec libmp3lame -f -flv rtmp://127.0.0.1:1935/rtcapp/str

Very choppy though, if anyone has any ffmpeg suggestions to make the stream smoother, please let me know!

Lorenzo Miniero

unread,
Jun 16, 2016, 4:50:46 AM6/16/16
to meetecho-janus
Not sure what I can suggest here: others have shared their ffmpeg scripts on the group, so searching around will probably help you. Not sure if adding a -re to make it realtime will help. You may have to play with bitrate and/or resolution/framerate settings, in case the one ffmpeg is trying to encode are too heavy for the machine. I'm not an expert on that though, sorry.

L.

Амнон Исраэли

unread,
Jun 16, 2016, 2:11:27 PM6/16/16
to meetecho-janus
If you want to deal with realtime, so encoder have to encode frame as fast as they arrive.
I don't know if ffmpeg got logic where/when to drop frames if they fill all of your memory
You may try to add light h264 modes like:
-preset veryfast/ultrafast, -tune zerolatency, slice-thread mode

Geige V

unread,
Jun 18, 2016, 12:17:47 AM6/18/16
to meetecho-janus
Thank you for the suggestions. Turned out the culprit was llibsrtp. I forgot to follow this line in the Janus installation guide:

If your distro ships a pre-1.5 version of libsrtp, it may be better to uninstall that version and install 1.5 manually. In fact, 1.4.x is known to cause several issues with WebRTC.

After uninstalling the 1.4.x version and upgrading to 1.5, the stream worked perfectly. I also managed to get the audio working. If anyone is interested, the sdp file and nginx rtmp/ffmpeg command I used are listed below:

v=0
o=- 0 0 IN IP4 127.0.0.1
s=RTP Video
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 56.15.102
m=audio 5006 RTP/AVP 111
a=rtpmap:111 OPUS/48000/2
m=video 5008 RTP/AVP 100
a=rtpmap:100 VP8/90000
a=fmtp:100 packetization-mode=1

And the nginx-rtmp config....

rtmp {
        server {
                listen 1935;
                chunk_size 4096;

                application live {
                        live on;
                        record off;
                }


                application rtcapp {
                        live on;
                        record off;
exec_pull ffmpeg -i /var/sdp/janus.sdp -ar 44100 -vcodec libx264 -acodec libmp3lame -f flv rtmp://127.0.0.1:1935/rtcapp/str;
                }
        }       
}




Thanks for the help! Hopefully somebody finds this code useful.

Cheers,
Geige


Alex Y

unread,
Sep 23, 2016, 5:00:27 AM9/23/16
to meetecho-janus
Hi! This code is totally useful, thanks.

But I have a small problem here. Your output is "rtmp://127.0.0.1:1935/rtcapp/str" which means only one stream at a time. nginx-rtmp says we can use "rtmp://127.0.0.1:1935/rtcapp/$name" instead, but what goes into $name variable from janus? For now, it seems like just "rtmp://127.0.0.1:1935/rtcapp" works. I can watch RTMP stream with rtmp://127.0.0.1:1935/rtcapp/roomName and rtmp://127.0.0.1:1935/rtcapp/publisherName - both works. It even works with random $name: "rtmp://127.0.0.1:1935/rtcapp/ashegu23ed".

My goal is several concurrent streams at one server:

So how to achieve that with Janus?


Another problem (but not so important ATM) is, when I start playing RTMP stream, player needs ~30 second before it actually starts playing. There wasn't issue when RTMP input is OBS. But if input is Janus SDP, there is issue. But I didn't digged into this yet, maybe it's not janus related.


суббота, 18 июня 2016 г., 12:17:47 UTC+8 пользователь Geige V написал:

Alex Y

unread,
Sep 23, 2016, 11:51:13 AM9/23/16
to meetecho-janus
Ok, I think I got it. Will try it tomorrow. Please correct me if I wrong or we can do it simpler. If we need many concurrent WebRTC -> RTMP streams available, our app must use many pairs of ports for this. So algorhitm is:
  1. User starts some stream. Our app of course notified about these fact.
  2. Our app gets 2 random free ports from server. Let's say server gives "12315" and "23212".
  3. Our app creates sdp-file for current stream. Let's say streamer name is "alex". So app would create /var/sdp/alex.sdp file containing ports "12315" and "23212" (and another settings of course).
  4. Then our app sends to Janus "rtp_forward" request containing these ports.
  5. Nginx-rtmp command would be something like "exec_pull /usr/local/sbin/ffmpeg -analyzeduration 100M -probesize 1M -protocol_whitelist file,udp,rtp -i /var/sdp/$name.sdp -ar 44100 -vcodec libx264 -acodec libfdk_aac -profile:v baseline -tune zerolatency -f flv rtmp://localhost/rtc2rtmp/$name;"

So, if we have 100 publishers, we need 200 free ports on server, and there will be 100 sdp files.


It's totally possible to implement, but please tell me there is more simple way to achieve my goal :)


пятница, 23 сентября 2016 г., 17:00:27 UTC+8 пользователь Alex Y написал:

Geige V

unread,
Sep 24, 2016, 12:25:43 PM9/24/16
to meetecho-janus
Hey Alex, glad it was useful. This sounds pretty similar to the question Lorenzo helped me out with Here.

Rather than having 100 sdp files stored, I believe you can have a dynamic file that updates based on the ports you send it. 


Cheers,
Geige

Alex Y

unread,
Sep 25, 2016, 4:36:39 AM9/25/16
to meetecho-janus
It works well. As I wrote, 1 sdp file per 1 stream. Random ports. I'm not sure how I can have one dynamic file if there is many concurrent streams? Imagine they start simultaneously. Okay we can update that file with every stream's start, but what happens when someone will watch RTMP stream? nginx-rtmp will execute ffmpeg ("exec_pull..." line from above post). And it will work but only last written to our dynamic sdp file.

Thanks anyway, my goal is reached with N files, but I'm ready to discuss that :)

воскресенье, 25 сентября 2016 г., 0:25:43 UTC+8 пользователь Geige V написал:

m...@riff.tv

unread,
Apr 24, 2017, 1:26:08 PM4/24/17
to meetecho-janus
Hi Alex,

I'm working on a use case similar to yours. How did you get Janus to notify your app of new streams (#1 in your algorithm: "Our app of course notified about these fact.")? 

I'm hoping to set up a Node app that manages ports / SDP files, but can't figure out how to get Janus to send the needed notifications.

Thanks so much.

Alex Y

unread,
Apr 25, 2017, 11:15:42 AM4/25/17
to meetecho-janus
Hi!

It's simple — when user successfully published stream, we can catch this event in browser — and notify our server-side app with ajax for example.

вторник, 25 апреля 2017 г., 1:26:08 UTC+8 пользователь m...@riff.tv написал:
Reply all
Reply to author
Forward
0 new messages