5

i am creating one-to-one webrtc video chatroom and this code does not working and i wanna know why

function hasUserMedia(){
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
return !!navigator.getUserMedia; 
}

function hasRTCPeerConnection() {
window.RTCPeerConnection = window.RTCPeerConnection || 
window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
return !!window.RTCPeerConnection;
}



 function startPeerConnection(stream) {
 var configuration = {

    "iceServers": [{ "url": "stun:stun.1.google.com:19302" }]
 };
 yourConnection = new RTCPeerConnection(configuration);
 theirConnection = new webkitRTCPeerConnection(configuration);

 yourConnection.addStream(stream);
 theirConnection.onaddstream = function (e) {
     theirVideo.src = window.URL.createObjectURL(e.stream);
 };


 yourConnection.onicecandidate = function (event) {
    if (event.candidate){

   theirConnection.addIceCandidate(newRTCIceCandidate(event.candidate));
    }
  };

 theirConnection.onicecandidate = function (event) {
    if (event.candidate) {
        yourConnection.addIceCandidate(new 
  RTCIceCandidate(event.candidate));
    }
  };

    yourConnection.createOffer(function (offer) {
    yourConnection.setLocalDescription(offer);
    theirConnection.setRemoteDescription(offer);

    theirConnection.createAnswer(function (offer) {
        theirConnection.setLocalDescription(offer);
        yourConnection.setRemoteDescription(offer);
    });
    });
     }


    var yourVideo = document.querySelector("#face_cam_vid"),
    theirVideo = document.querySelector("#thevid"),
   yourConnection, theirConnection;

   if (hasUserMedia()) {
      navigator.getUserMedia({ video: true, audio: true }, function(stream) 
 {
        yourVideo.src = window.URL.createObjectURL(stream);
        if (hasRTCPeerConnection()) {
            startPeerConnection(stream);
        } else {
            alert("Sorry, your browser does not support WebRTC.");
        }
         }, function (error) {
         console.log(error);
        }
               );
     } else {
      alert("Sorry, your browser does not support WebRTC.");
    }

and this code is giving me a errors like thiserrors and as u see video is not displaying , i tried to create div (where video tag is) but it did not work anyway

if u can help my i will be glad here is my html

 <!DOCTYPE html>
 <html>

 <head>
 <title>
  Video Call
 </title>
 <meta charset="utf-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <link rel="stylesheet" type="text/css" media="screen" href="vidd.css" />
 <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
 <script src="/videof.js"></script>

 <script>var width = Math.max(window.screen.width, window.innerWidth);

    if(width <= 414){
        var faceCam = document.getElementById("face_cam");
        faceCam.style.width = "15%";
    }

    function smaller(){
        if(width <= 414){
            var size = document.getElementById("face_cam").style.width;
            if(size == "15%"){
                faceCam.style.width = "3%";
                faceCam.style.height = "3%";
                faceCam.style.borderRadius = "0px"
            }
            else if(size == "3%"){
                faceCam.style.width = "15%";
                faceCam.style.height = "30%";
                faceCam.style.borderRadius = "10px"
            }
        }

        else{
            var size = document.getElementById("face_cam").style.width;
            if(size == "30%"){
                faceCam.style.width = "3%";
                faceCam.style.height = "3%";
                faceCam.style.borderRadius = "0px"
            }
            else if(size == "3%"){
                faceCam.style.width = "30%";
                faceCam.style.height = "30%";
                faceCam.style.borderRadius = "10px";
            }
         }
        }


     var width = Math.max(window.screen.width, window.innerWidth);

     function smaller(){
        var size = document.getElementById("face_cam").style.height;
        if (size == "30%"){
            var frame = document.getElementById("face_cam");
            frame.style.height = "3%";
            frame.style.width = "4%";
            frame.borderRadius = "0px";
        }

        else{
            var frame = document.getElementById("face_cam");
            frame.style.height = "30%";
            frame.style.width = "30%";
        }
        }
         function BACKT(){ 
              window.location.href = "http://localhost:8000/"
        }

       </script>
       </head>

       <body>
      <div class="test_vc_field">
      <video id="thevid" autoplay></video>
     <div id="face_cam" onclick="smaller()" style="height: 30%; width: 30%">
     <video id="face_cam_vid" autoplay></video>
    </div>
    </div>
    <div class="nav">
   <button class="next">შემდეგი</button>
   <img src="next.png" class="next_icon">
    <button class="off" id="off">გათიშვა</button>
   <img src="shutdown.png" class="shd_icon">
  <button class="goto_main" id="WTfu" onclick="BACKT();">მთავარი 
  გვერდი</button>
  <img src="home.png" class="home_icon" onclick="main()">
  </div>
  </body>

   </html>

#thevid id vid where second user displays face_cam_vid is video where i display

iLiA
  • 3,053
  • 4
  • 23
  • 45

1 Answers1

37

It's outdated code. It contains 6 problems that track the evolution of the WebRTC API.

TL;DR: It doesn't work because you're not checking for errors and you've only tested one browser.

1) Old vendor prefixes (remove them):

yourConnection = new RTCPeerConnection(configuration);
theirConnection = new webkitRTCPeerConnection(configuration); // <-- wrong

webkit-names won't work in Firefox or Edge. These haven't been needed in years. Provided you switch to navigator.mediaDevices.getUserMedia, you can skip your 10 lines of prefix-mangling preamble entirely.

2) Uses old url (use urls)

This is technically wrong, though I suspect most browsers allow it:

iceServers: [{url: "stun:stun.1.google.com:19302"}] // <-- wrong

Instead use:

iceServers: [{urls: "stun:stun.1.google.com:19302"}]

...because an ICE server may technically be reachable at multiple urls.

3) Using old callback APIs without error checking (use promises instead):

This is wrong:

navigator.getUserMedia({video: true, audio: true}, function(stream) { /* ... */ });

...because a 3rd failure callback argument is required. Edge says TypeError: Argument not optional.

Legacy bugs in Chrome and Safari allow this, but it won't work in Firefox or Edge. Ignoring errors deprives you of learning why things don't work. If the user denies camera access, you wanna know.

All modern browsers support the promise version of the API on mediaDevices. Use that instead:

navigator.mediaDevices.getUserMedia({video: true, audio: true})
  .then(stream => { /* use stream here */ })
  .catch(error => console.log(error));

4) You fell in RTCPeerConnection's "promise/callback mix-up trap":

I've answered this before, but in short, this is similar to #2 above, but with a twist. This is wrong:

yourConnection.createOffer(function(offer) { /* ... */ }); 

You think you're calling the old callback API, but you're not. Those required two arguments:

yourConnection.createOffer(successCallback, failureCallback /*, optionsObject */);

Instead, you're actually calling the same-named modern promise API, because a function is an object in JS:

const promise = yourConnection.createOffer(optionsObject);

This is where your code stops working. Your callback function is never called, being interpreted as an empty options object instead. You ignore the returned promise. Use the promise API instead.

5) createObjectURL(stream) is deprecated, gone.

It was removed in Firefox and Chrome 71 (the warning you received). This is wrong:

theirVideo.src = URL.createObjectURL(stream);

Instead use this:

theirVideo.srcObject = stream;

6) For extra points: The whole stream API is deprecated (use tracks).

addStream() & onaddstream are no longer in the spec, and only work in some browsers:

yourConnection.addStream(stream);
theirConnection.onaddstream = e => theirVideo.srcObject = e.stream;

Instead, peer connections are now entirely track-based. Use this instead:

for (const track of stream.getTracks()) {
  yourConnection.addTrack(track, stream);
}
theirConnection.ontrack = e => theirVideo.srcObject = e.streams[0];

For more on these differences, see my blog.

Working example

The following should work in all browsers:

const yourVideo = document.querySelector("#face_cam_vid");
const theirVideo = document.querySelector("#thevid");

(async () => {
  if (!("mediaDevices" in navigator) || !("RTCPeerConnection" in window)) {
    alert("Sorry, your browser does not support WebRTC.");
    return;
  }
  const stream = await navigator.mediaDevices.getUserMedia({video:true, audio:true});
  yourVideo.srcObject = stream;

  const configuration = {
    iceServers: [{urls: "stun:stun.1.google.com:19302"}]
  };
  const yours = new RTCPeerConnection(configuration);
  const theirs = new RTCPeerConnection(configuration);

  for (const track of stream.getTracks()) {
    yours.addTrack(track, stream);
  }
  theirs.ontrack = e => theirVideo.srcObject = e.streams[0];

  yours.onicecandidate = e => theirs.addIceCandidate(e.candidate);
  theirs.onicecandidate = e => yours.addIceCandidate(e.candidate);

  const offer = await yours.createOffer();
  await yours.setLocalDescription(offer);
  await theirs.setRemoteDescription(offer);

  const answer = await theirs.createAnswer();
  await theirs.setLocalDescription(answer);
  await yours.setRemoteDescription(answer);
})();
jib
  • 40,579
  • 17
  • 100
  • 158
  • hey it works but partly because it does not wait second user to connect this route and displays both my and their video with my camera soo as i said i want one-to-one chatroom and i think this code can u help me with that : here is the photo https://imgur.com/a/nG7Xif6 – iLiA Nov 18 '18 at 18:13
  • 1
    Your code is a local-loop demo, not a chat room. Check out [this tutorial](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling) instead on MDN. – jib Nov 18 '18 at 22:38
  • checked it also tried demo for this but there is no rooms and how can three people have WEBRTC connection same time – iLiA Nov 19 '18 at 17:15
  • The hard way. Three people either means each person has two connections, one for each of the other participants (a.k.a. a mesh call). Past ~5 participants you'll want a central SFU server approach instead. "Rooms" is just app logic to discover peers; not part of WebRTC. – jib Nov 19 '18 at 17:56
  • and do i need rooms or it will separate third client when first 2 is already streaming or what? sorry for that i am newbie – iLiA Nov 19 '18 at 19:29
  • All you have is a demo that pairs the first two people who access the server. How you want to discover and connect people beyond that is entirely up to you. Most people use some concept like "[rooms](https://stackoverflow.com/a/36893505/918910)". This has nothing to do with the `RTCPeerConnection` API, which is solely about creating a single connection between two peers. – jib Nov 19 '18 at 21:05
  • and if WebRTC perceives me as 2 user and displays both video tag with my src how can i get users in room , what i said is kinda obscure but lemme give u example : for exp i created "rooms" and host my web how can user be able to connect second user and have video chat with him/her when code displays both recieved and local video with my camera it is like chat with myself , i wanna answer for that thanks – iLiA Nov 20 '18 at 12:13
  • There's a lot more to understand first about how WebRTC works. It's a big topic, and I recommend [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API). Good luck! – jib Nov 20 '18 at 12:33
  • Hey I'm a beginner to WebRTC, is there an up-to-date documentation on developing WebRTC for video chat? – mding5692 May 31 '19 at 20:16
  • @jib would you please help me on https://stackoverflow.com/questions/63862778/webrtc-video-streaming-is-working-in-firefox-but-not-in-chrome – Rakibul Islam Prince Sep 13 '20 at 18:32