Stream RTSP stream from IP camera via Kurento Media Server over WebRTC
<p>I have to create a WebRTC solution where I have multiple IP camera in a private network and have to stream the feeds to a mobile application outside the network. I am using Kurento Media Server to help me generate a WebRTC stream from the RTSP stream from the camera. I have installed KMS(Kurento Media Server) in the private network as well. </p>

<p>I followed a similar setup to <a href="https://github.com/lulop-k/kurento-rtsp2webrtc" rel="nofollow noreferrer">https://github.com/lulop-k/kurento-rtsp2webrtc</a> except for the fact that I created a pipeline with a PlayerEndpoint with the camera stream URI and a WebRTCEndpoint connected to it as shown below.</p>

<pre><code>function playCam(message){
  console.log("Message:" + JSON.stringify(message));
  var cam_url = message.cam_url;
  var sdpOffer = message.sdpOffer;
  getKurentoClient(function(error, kurentoClient) {

  console.log("Kurento client created.");
  kurentoClient.create('MediaPipeline', function(error, pipeline) {
  if (error) {
    console.log("Error: Creating Media Pipeline failed.");
    stop(pipeline);
    return;
  }

  console.log("Pipeline created.");
  pipeline.create("PlayerEndpoint", {uri: cam_url}, function(error, player){
      if(error) {
          console.log("Error: Creating PlayerEndpoint failed.");
          stop(pipeline);
          return;
        }

        console.log("PlayerEndpoint created.");
        pipeline.create("WebRtcEndpoint", function(error, webRtcEndpoint){

        remoteWebRtcEndpoint = webRtcEndpoint;
            console.log("WebRtcEndpoint created.");
            webRtcEndpoint.processOffer(sdpOffer, function(error, sdpAnswer){

                      sendSdpAnswer(sdpAnswer);

          for(var i = 0; i &lt; remoteCandidates.length; i++){
            addIceRemoteCandidate(remoteCandidates[i]);
          }

                      webRtcEndpoint.gatherCandidates(function(error) {
                          console.log("Gathering Ice candidates created.");
                    });
                });

                player.connect(webRtcEndpoint, function(error){
                    console.log("PlayerEndpoint--&gt;WebRtcEndpoint connection established");

                    player.play(function(error){
                        console.log("Player playing ...");
                    });
                });

        webRtcEndpoint.on('OnIceCandidate', function(event) {
            console.log(JSON.stringify(event));
            var candidate = kurento.getComplexType('IceCandidate')(event.candidate);
            sendIceCandidate(candidate);
          });
        });
      });
    });
  });
}
</code></pre>

<p>I used a web socket in the cloud to signal sdpOffer, sdpAnswer, iceCandidate messages.</p>

<p>At the client side I have the javascript implementation that uses a WebRTC Peer as shown below. </p>

<pre><code>var ws = new WebSocket(ws.url);
var webRtcPeer;
ws.onmessage = function(message) {
  var parsedMessage = JSON.parse(message.data);

  switch (parsedMessage.id) {
    case 'iceCandidate':
      webRtcPeer.addIceCandidate(parsedMessage.candidate)
      break;
    case 'sdpAnswer':
      webRtcPeer.processAnswer(parsedMessage.sdpAnswer);
      break;
    default:
      onError('Unrecognized message', parsedMessage);
  }
}

window.addEventListener('load', function(){
  var videoOutput = document.getElementById('videoOutput');
  var address = camera_rtsp_stream_url;
  var pipeline;

  function start() {
    var options = {
      remoteVideo : videoOutput,
      configuration: {
        iceServers:[
         { "url": turn_url,
           "username": uname,
           "credential": pass
         }
       ]
      }
    };

    webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options,
      function(error){
      webRtcPeer.generateOffer(onOffer);
      setIceCandidateCallbacks();
    });
  }

  function onOffer(error, sdpOffer){
    var message = {
      id : 'sdpOffer',
      name: 'peer',
      cam_url: address,
      sdpOffer : sdpOffer
    };
    sendMessage(message);
  }

});

function sendMessage(message) {
  var jsonMessage = JSON.stringify(message);
  ws.send(jsonMessage);
}

function setIceCandidateCallbacks(){
  webRtcPeer.on('icecandidate', function(candidate){
    candidate = kurentoClient.register.complexTypes.IceCandidate(candidate);

    var message = {
      id : 'iceCandidate',
      name: 'peer',
      iceCandidate : candidate
    };
    sendMessage(message);

  });

}
</code></pre>

<p>Still the feed is not working in page. However, the example in the git repo works perfect. Is there something I am missing. </p>

<p>Thanks in advance.</p>

<p>Edit:</p>

<p>This is my SDP Offer.</p>

<pre><code>v=0
o=- 62767501284085133 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:AoAe
a=ice-pwd:tp+DQSO/OTvBaDZYQOmb5Yxe
a=fingerprint:sha-256     14:03:6A:CB:9D:86:B5:57:09:30:97:D8:0A:0E:59:A2:0F:8D:5F:24:46:3E:14:C7:D3:23:B2:11:39:4C:61:33
a=setup:actpass
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:126 telephone-event/8000
m=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96 97 99 98
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:AoAe
a=ice-pwd:tp+DQSO/OTvBaDZYQOmb5Yxe
a=fingerprint:sha-256 14:03:6A:CB:9D:86:B5:57:09:30:97:D8:0A:0E:59:A2:0F:8D:5F:24:46:3E:14:C7:D3:23:B2:11:39:4C:61:33
a=setup:actpass
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=recvonly
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtpmap:101 VP9/90000
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 goog-remb
a=rtcp-fb:101 transport-cc
a=rtpmap:107 H264/90000
a=rtcp-fb:107 ccm fir
a=rtcp-fb:107 nack
a=rtcp-fb:107 nack pli
a=rtcp-fb:107 goog-remb
a=rtcp-fb:107 transport-cc
a=fmtp:107 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=101
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=107
a=rtpmap:98 rtx/90000
a=fmtp:98 apt=116
</code></pre>

<p>SDP Answer is as shown below:</p>

<pre><code>v=0
o=- 3687061549 3687061549 IN IP4 0.0.0.0
s=Kurento Media Server
c=IN IP4 0.0.0.0
t=0 0
a=msid-semantic: WMS
a=group:BUNDLE audio video
m=audio 1 UDP/TLS/RTP/SAVPF 111 0
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=mid:audio
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:111 opus/48000/2
a=rtpmap:0 PCMU/8000
a=setup:active
a=sendonly
a=rtcp-mux
a=fmtp:111 minptime=10;useinbandfec=1
a=ssrc:174718429 cname:user1410268339@host-e518075a
a=ice-ufrag:Y1e8
a=ice-pwd:rLobIsorf9OWA8VkEvGbJN
a=fingerprint:sha-256 EF:8B:94:E4:CF:2A:82:BD:2D:07:F6:35:B8:2A:4C:4A:7F:A5:8D:FE:06:5F:38:6C:E7:F8:10:07:3C:11:E1:28
m=video 1 UDP/TLS/RTP/SAVPF 100
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=mid:video
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=setup:active
a=sendonly
a=rtcp-mux
a=ssrc:3344771 cname:user1410268339@host-e518075a
a=ice-ufrag:Y1e8
a=ice-pwd:rLobIsorf9OWA8VkEvGbJN
a=fingerprint:sha-256 EF:8B:94:E4:CF:2A:82:BD:2D:07:F6:35:B8:2A:4C:4A:7F:A5:8D:FE:06:5F:38:6C:E7:F8:10:07:3C:11:E1:28
</code></pre>