1

I have a public IP to which I want my clients to send their WebRTC RTP stream to.

The client will know the codecs and to which ports to send the stream to.

I am trying to do as barebones of an implementation as possible, but so much details seem to be missing.

All Google searches points be to using some kind of server for this, such as Janus gateway, which is acceptable if required, but I don't see why would I need this, as the only requirement for me is to make the browser send RTP stream to predefined IP and port.

I have created an working setup using Janus gateway, then copied the SDPs used so I could use them withing a setup without Janus.

    navigator.mediaDevices.getUserMedia({audio: true, video: true}).then(function (stream) {
        let videoElement = document.getElementById("my-video");
        videoElement.srcObject = stream;


        var peerConnection = new RTCPeerConnection({iceServers: []});

        peerConnection.onnegotiationneeded = function() {
            console.log("onnegotiationneeded");


            peerConnection.createOffer({offerToReceiveAudio: false, offerToReceiveVideo: false}).then(function (offer) {
                peerConnection.setLocalDescription(offer);

                console.log("setRemoteDescription");


                peerConnection.setRemoteDescription({
                    type: 'answer',
                    sdp: `v=0
o=mozilla...THIS_IS_SDPARTA-74.0.1 1586270943313087 1 IN IP4 192.168.1.5
s=VideoRoom 1234
t=0 0
a=group:BUNDLE 0 1
a=msid-semantic: WMS janus
m=audio 9 UDP/TLS/RTP/SAVPF 109
c=IN IP4 192.168.1.5
a=recvonly
a=mid:0
a=rtcp-mux
a=ice-ufrag:uuIW
a=ice-pwd:bW5IdRMw2iMhH5wLiC+2u3
a=ice-options:trickle
a=fingerprint:sha-256 6E:5C:B0:6A:56:78:54:93:AB:6D:21:7E:B7:B3:F9:80:5C:0D:00:F0:D8:52:8E:BA:F1:87:C4:A7:37:38:CB:46
a=setup:active
a=rtpmap:109 opus/48000/2
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=msid:janus janusa0
a=ssrc:849691919 cname:janus
a=ssrc:849691919 msid:janus janusa0
a=ssrc:849691919 mslabel:janus
a=ssrc:849691919 label:janusa0
a=candidate:1 1 udp 2013266431 192.168.1.5 60526 typ host
a=end-of-candidates
m=video 9 UDP/TLS/RTP/SAVPF 126
c=IN IP4 192.168.1.5
a=recvonly
a=mid:1
a=rtcp-mux
a=ice-ufrag:uuIW
a=ice-pwd:bW5IdRMw2iMhH5wLiC+2u3
a=ice-options:trickle
a=fingerprint:sha-256 6E:5C:B0:6A:56:78:54:93:AB:6D:21:7E:B7:B3:F9:80:5C:0D:00:F0:D8:52:8E:BA:F1:87:C4:A7:37:38:CB:46
a=setup:active
a=rtpmap:126 H264/90000
a=fmtp:126 profile-level-id=42e01f;packetization-mode=1
a=rtcp-fb:126 ccm fir
a=rtcp-fb:126 nack
a=rtcp-fb:126 nack pli
a=rtcp-fb:126 goog-remb
a=rtcp-fb:126 transport-cc
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:6/inactive http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=msid:janus janusv0
a=ssrc:3452602418 cname:janus
a=ssrc:3452602418 msid:janus janusv0
a=ssrc:3452602418 mslabel:janus
a=ssrc:3452602418 label:janusv0
a=candidate:1 1 udp 2013266431 192.168.1.5 60526 typ host
a=end-of-candidates`
                })
            });
        };

        let tracks = stream.getTracks();
        for(var i = 0; i < tracks.length; i++) {
            peerConnection.addTrack(tracks[i]);
        }

    });

Here I initialize the webcam feed, create an RTCPeerConnection without ICE servers as documented here and add all tracks.

I setup a listener to onnegotiationneeded callback where when negotiation is needed I create an offer with offerToReceiveAudio and offerToReceiveVideo set to false on the RTCPeerConnection, and after it has been created I set the created offer as RTCPeerConnections local description.

After this I set predefined SDP as remoteDescription.

The SDP has been copied from Janus session, it contains ICE attribute such as ice-ufrag, ice-pwd and ice-options, and if I delete them, I get error regarding Invalid description.

The SDP also contains STUN(?) candidates and removing them makes no difference.

After running this the browser connects to the STUN candidate, but as this is not necessary as the server is run on public IP, the request fails..

Which steps should be taken to make a minimal setup where the browser sends RTP to predefined host/port on predefined codec?

halfer
  • 19,824
  • 17
  • 99
  • 186
Pasi Matalamäki
  • 1,843
  • 17
  • 14
  • You will have to generate your own ice candidates based on where to connect and ignore the ice candidates generated by peer connection. More on ice check step 2 - https://temasys.io/webrtc-ice-sorcery/ – Karthik Apr 07 '20 at 15:48
  • I've skimmed through this article but it is too vague for me to understand. I checked Mozillas resources regarding SDP and found out about using 'host candidate', which was already done, just the IP was wrong. Now I have updated it to be localhost, but the ice connection still fails with error 'ICE failed, add a STUN server and see about:webrtc for more details' I updated the question to reflect this updated SDP – Pasi Matalamäki Apr 07 '20 at 19:39

1 Answers1

2

I might be misunderstanding the question, but I don't believe this is possible Pasi.

The browser will only send video when

  • ICE goes to connected. You need to respond to those messages
  • DTLS handshake, which then exports the keying material and initializes SRTP
  • Then everything is sent over SRTP.

You could easily build this with existing building blocks though! If you don't want to run a full WebRTC implementation, you could stitch existing libraries together like pion/ice pion/dtls and pion/srtp

In the long run you will probably be better served by running something like Janus. There are lots of hidden details you will end up hitting that WebRTC solves for you :)

Sean DuBois
  • 3,972
  • 1
  • 11
  • 22
  • I think most of this comes from not understanding everything correctly. After trying the gateway solutions janus/kurento, they just seem heavyweight for my requirements. I am trying to make a web client publish to RTMP server, therefore I am using ffmpeg to encode the RTP stream to the RTMP server.. These details really helped me understand what would be required to ditch the gateway. Is the ICE and using secure connection a nessacity? Some sources such as the linked SO post says that ICE isn't a requirement. Hmm.. I really need to dig deeper. Thanks. – Pasi Matalamäki Apr 08 '20 at 12:22
  • I made some searches and it is true that SRTP is the only transport available on webrtc, which is sensible, as security is key on communication. ffmpeg seems to be able to understand SRTP stream if the I could do the DTLS handshake on first hand – Pasi Matalamäki Apr 08 '20 at 12:26
  • 1
    You could do something like https://github.com/pion/example-webrtc-applications/tree/master/twitch I am happy to answer more questions in https://pion.ly/slack also! I will be a little slow getting back to these, I answer stuff on SO as my last thing of the day :) – Sean DuBois Apr 09 '20 at 06:29
  • Thank you for these great resources, these really helped me fulfill gaps between my webrtc knowledge! The project requirements changed a little after more problems were introduced due to the RTMP gateway. – Pasi Matalamäki Apr 12 '20 at 13:04
  • @SeanDuBois Can you please share any quick example or starting place within pion webrtc to look for on using by stitching pion/ice pion/dtls and pion/srtp or even pion/srtp if keys are pre-established – Chakradhar K Dec 17 '20 at 11:12