RudolphRedNose
RudolphRedNose

Reputation: 173

simpleWebRTC video chat Failed to construct 'RTCPeerConnection': error

Ok so I am doing tutorials on webRTC and I've been using the following two tutorials to help me.

Sitepoint tutorial and Scotch tutorial

First thing to note, for the first tutorial even with the source code cloned from github here:

https://github.com/sitepoint-editors/simplewebrtc-messenger.git

when I deploy the app on Now.sh it works but I am unable to join different users.

TLDR;

Here is My Deployed App. When I try to join a remote connection I get this error

Uncaught DOMException: Failed to construct 'RTCPeerConnection': 'stun.l.google.com' is not one of the supported URL schemes 'stun', 'turn' or 'turns'.

Here is the [source code

// Code goes here

let username, roomname;
// Determine whether or not we have a querystring.
function hasQueryString() {
    console.log(location.href.indexOf("?"))
    return location.href.indexOf("?") !== -1;
}
const formEl = $('.form');
// Enable video on the page.
function enableVideo() {
    document.getElementById("url").style.display = "block";
    document.getElementById("remotes").style.visibility = "visible";
    loadSimpleWebRTC();
}

if (hasQueryString()) {
    console.log("Query string!");
    enableVideo();
    if (formEl) {
        formEl.hide();
    }
} else if (formEl) {
    formEl.show();
}

// Handle form submission
console.log("Form loaded!")
$("#join-btn").click(function (event) {
    const formEl = $('.form');
    var usernameInput = formEl.find('#inputUsername');
    var roomnameInput = formEl.find('#inputRoomname');

    if (usernameInput.length > 0 && !usernameInput[0].value) {
        alert("Invalid username!")
    } else if (roomnameInput.length > 0 && !roomnameInput[0].value) {
        alert("Please enter a roomname");
    } else if (roomnameInput.length > 0 && roomnameInput[0].value.length < 6) {
        alert("Roomname must be longer than 5 characters!");
    } else {
        username = usernameInput[0].value;
        roomname = roomnameInput[0].value.toLowerCase();
        window.location = getRoomURL();
        enableVideo();
    }
    return false;
})

// Determine the room name and public URL for this chat session.
function getRoom() {
    if (roomname) {
        return roomname;
    } else {
        var query = location.search && location.search.split("?")[1];
        console.log(query);
        if (query) {
            console.log("roomname is:");
            console.log((location.search && decodeURIComponent(query.split("=")[1]).toLowerCase()));
            roomname = location.search && decodeURIComponent(query.split("=")[1]).toLowerCase();
            return roomname;
        }
    }
    roomname = "room" + Math.floor(Math.random() * 0xFFFFFF).toString(16);
    return roomname;
}

function getUser() {
    if (username) {
        return username;
    } else return "User" + Math.floor(Math.random() * 0xFFFFFF).toString(16);
}


// Retrieve the absolute room URL.
function getRoomURL() {
    return location.protocol + "//" + location.host + (location.path || "") + "?room=" + getRoom();
}

// Dynamically load the simplewebrtc script so that we can
// kickstart the video call.
function loadSimpleWebRTC() {
    var script = document.createElement("script");
    script.src = "https://simplewebrtc.com/latest-v3.js";
    document.head.appendChild(script);

    script.onload = function () {
        var webrtc = new SimpleWebRTC({
            localVideoEl: "selfVideo",
            // the id/element dom element that will hold remote videos
            remoteVideosEl: "",
            autoRequestMedia: true,
            debug: false,
            detectSpeakingEvents: true,
            autoAdjustMic: false
        });

        // Set the publicly available room URL.
        document.getElementById("roomUrl").innerText = getRoomURL();

        // Immediately join room when loaded.
        webrtc.on("readyToCall", function () {
            webrtc.joinRoom(getRoom());
        });

        function showVolume(el, volume) {
            if (!el) return;
            if (volume < -45) volume = -45; // -45 to -20 is
            if (volume > -20) volume = -20; // a good range
            el.value = volume;
        }

        // Display the volume meter.
        webrtc.on("localStream", function (stream) {
            var button = document.querySelector("form>button");
            if (button) button.removeAttribute("disabled");
            document.getElementById("localVolume").style.display = "block";
        });

        // If we didn't get access to the camera, raise an error.
        webrtc.on("localMediaError", function (err) {
            alert("This service only works if you allow camera access.Please grant access and refresh the page.");
        });

        // When another person joins the chat room, we'll display their video.
        webrtc.on("videoAdded", function (video, peer) {
            console.log("user added to chat", peer);
            var remotes = document.getElementById("remotes");

            if (remotes) {
                var outerContainer = document.createElement("div");
                outerContainer.className = "col-md-6";

                var container = document.createElement("div");
                container.className = "videoContainer";
                container.id = "container_" + webrtc.getDomId(peer);
                container.appendChild(video);

                // Suppress right-clicks on the video.
                video.oncontextmenu = function () { return false; };

                // Show the volume meter.
                var vol = document.createElement("meter");
                vol.id = "volume_" + peer.id;
                vol.className = "volume";
                vol.min = -45;
                vol.max = -20;
                vol.low = -40;
                vol.high = -25;
                container.appendChild(vol);

                // Show the connection state.
                if (peer && peer.pc) {
                    var connstate = document.createElement("div");
                    connstate.className = "connectionstate";
                    container.appendChild(connstate);

                    peer.pc.on("iceConnectionStateChange", function (event) {
                        switch (peer.pc.iceConnectionState) {
                            case "checking":
                                connstate.innerText = "connecting to peer...";
                                break;
                            case "connected":
                            case "completed": // on caller side
                                vol.style.display = "block";
                                connstate.innerText = "connection established";
                                break;
                            case "disconnected":
                                connstate.innerText = "disconnected";
                                break;
                            case "failed":
                                connstate.innerText = "connection failed";
                                break;
                            case "closed":
                                connstate.innerText = "connection closed";
                                break;
                        }
                    });
                }

                outerContainer.appendChild(container);
                remotes.appendChild(outerContainer);

                // If we're adding a new video we need to modify bootstrap so we
                // only get two videos per row.
                var remoteVideos = document.getElementById("remotes").getElementsByTagName("video").length;

                if (!(remoteVideos % 2)) {
                    var spacer = document.createElement("div");
                    spacer.className = "w-100";
                    remotes.appendChild(spacer);
                }
            }
        });

        // If a user disconnects from chat, we need to remove their video feed.
        webrtc.on("videoRemoved", function (video, peer) {
            console.log("user removed from chat", peer);
            var remotes = document.getElementById("remotes");
            var el = document.getElementById("container_" + webrtc.getDomId(peer));
            if (remotes && el) {
                remotes.removeChild(el.parentElement);
            }
        });

        // If our volume has changed, update the meter.
        webrtc.on("volumeChange", function (volume, treshold) {
            showVolume(document.getElementById("localVolume"), volume);
        });

        // If a remote user's volume has changed, update the meter.
        webrtc.on("remoteVolumeChange", function (peer, volume) {
            showVolume(document.getElementById("volume_" + peer.id), volume);
        });

        // If there is a P2P failure, we need to error out.
        webrtc.on("iceFailed", function (peer) {
            var connstate = document.querySelector("#container_" + webrtc.getDomId(peer) + " .connectionstate");
            console.log("local fail", connstate);
            if (connstate) {
                connstate.innerText = "connection failed";
                fileinput.disabled = "disabled";
            }
        });

        // remote p2p/ice failure
        webrtc.on("connectivityError", function (peer) {
            var connstate = document.querySelector("#container_" + webrtc.getDomId(peer) + " .connectionstate");
            console.log("remote fail", connstate);
            if (connstate) {
                connstate.innerText = "connection failed";
                fileinput.disabled = "disabled";
            }
        });
    }
}
body {                                                                                                                        
    font-family: 'Raleway', sans-serif;                                                                                         
  }                                                                                                                             
  
  footer {                                                                                                                      
    text-align: center;                                                                                                         
    margin-top: 2em;                                                                                                            
  }                                                                                                                             
  
  h2 {                                                                                                                          
    font-style: italic;                                                                                                         
  }                                                                                                                             
  
  header {                                                                                                                      
    text-align: center;                                                                                                         
    margin: 4em;                                                                                                                
  }                                                                                                                             
  
  header h1, header h2 {         
    display: inline;             
  }                              
  
  header h1 a, header h2 a, header h1 a:hover, header h2 a:hover {                                                              
    color: inherit;              
    text-decoration: none;       
  }                              
  
  header h2 {                    
    font-size: 24px;             
    padding-left: .5em;          
  }                              
  
  #remotes {                     
    visibility: hidden;          
  }                              
  
  #url {                         
    text-align: center;          
    display: none;               
  }                              
  
  #login {                       
    display: none;               
  }                              
  
  #roomIntro {                   
    font-weight: bold;           
  }
  
  .videoContainer {              
    object-fit: cover;           
    margin: 0 auto;              
    padding: 0;                  
  }                              
  
  .videoContainer video {        
    width: 100%;                 
    height: 100%;                
    border-radius: 10px;         
    border: 5px double #f2f2f2;  
  }                              
  
  .volume {                      
    position: absolute;          
    left: 15%;                   
    width: 70%;                  
    bottom: 20px;                
    height: 10px;                
    display: none;               
  }                              
  
  .connectionstate {             
    position: absolute;          
    top: 10px;                   
    width: 100%;                 
    text-align: center;          
    color: #fff                  
  }                              
  
  .col-md-6 {                    
    margin-bottom: 1em;          
  } 
<!DOCTYPE html>
<html>

<head>
  <title>vchat - a simple video chat app</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
    crossorigin="anonymous">
  <link rel="stylesheet" type="text/css" href="style.css">
  <script src="https://webrtc.github.io/adapter/adapter-4.2.2.js"></script>
  <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet">
</head>

<body>
  <div class="container">

    <div class="row">
      <div id="enter-form-container" class="jumbotron col-md-6 banner">
        <h1 class="display-4">Web Chat</h1>
        <p class="lead">This is a simple free webRTC video chat.</p>
        <hr class="my-4">
        <!-- <a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>-->
        <div id="enter-form" class="form">
          <p>Enter a username followed by a room name to join a preexisting room or create a new one.</p>
          <div class="form-group">
            <label for="exampleInputUsername1">Username</label>
            <input type="text" class="form-control" id="inputUsername" name="username" aria-describedby="usernameHelp" placeholder="Enter Username">
          </div>
          <div class="form-group">
            <label for="exampleInputPassword1">Room Name</label>
            <input type="text" class="form-control" id="inputRoomname" name="roomname" placeholder="Room Name">
          </div>
          <button id="join-btn" class="btn btn-primary submit">Enter Room</button>
        </div>
        <div id="url" class="alert alert-dark" role="alert">
          <span id="roomIntro">ROOM URL</span>:
          <span id="roomUrl"></span>
        </div>
        <div id="chat"></div>
      </div>
    </div>

    <div id="remotes" class="row">
      <div class="col-md-6">
        <div class="videoContainer">
          <video id="selfVideo" oncontextmenu="return false;"></video>
          <meter id="localVolume" class="volume" min="-45" max="-20" high="-25" low="-40"></meter>
        </div>
      </div>
    </div>
  </div>

  <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
    crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
    crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T"
    crossorigin="anonymous"></script>
  <script src="script.js"></script>
</body>

</html>

Any ideas as to what I'm doing wrong??

Upvotes: 0

Views: 2822

Answers (2)

RudolphRedNose
RudolphRedNose

Reputation: 173

OK so apparently there has been some issues with simpleWebRTC's Sandbox signalling server all week and they also advise that you use your own signaling server.

So I found XirSys xsdk platform and followed their simpleWebRtc example and BOOM! It works.

Upvotes: 0

Joseph D.
Joseph D.

Reputation: 12174

Use:

stun:stun.l.google.com:19302

There should be stun in the Server URL and indicate the Port Number.

Upvotes: 5

Related Questions