title: Video Conferencing in HTML5: WebRTC via Socket.io
body: <p>I'm trying to implement this <a href="http://html5videoguide.net/presentations/LCA_2013_webrtc/socket-server/webrtc.html" rel="nofollow">video conferencing</a> HTML5 application. I'm not sure exactly what is going on but I followed the instructions, maybe I missed something...</p>
  
  <p>I copied the HTML file (index.html) with the socket IP changed to the correct one for my server:</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;WebRTC Demo&lt;/title&gt;  
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;WebRTC Demo using Socket.IO&lt;/h1&gt;
    &lt;video id="webrtc-sourcevid" autoplay style="width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;
    &lt;button type="button" onclick="startVideo();"&gt;Start video&lt;/button&gt;
    &lt;button type="button" onclick="stopVideo();"&gt;Stop video&lt;/button&gt;
    &lt;video id="webrtc-remotevid" autoplay style="width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;
    &lt;button type="button" onclick="connect();"&gt;Connect&lt;/button&gt;
    &lt;button type="button" onclick="hangUp();"&gt;Hang Up&lt;/button&gt;
  
    &lt;p&gt;Run a node.js server and adapt the address in the code.&lt;/p&gt;
    &lt;script src="http://cdn.socket.io/stable/socket.io.js"&gt;&lt;/script&gt;
    &lt;script&gt;
    // create socket
    var socket = io.connect('localhost:1337/');
  
    var sourcevid = document.getElementById('webrtc-sourcevid');
    var remotevid = document.getElementById('webrtc-remotevid');
    var localStream = null;
    var peerConn = null;
    var started = false;
    var channelReady = false;
    var mediaConstraints = {'mandatory': {
                            'OfferToReceiveAudio':true, 
                            'OfferToReceiveVideo':true }};
    var isVideoMuted = false;
  
    // get the local video up
    function startVideo() {
        navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia || navigator.msGetUserMedia;
        window.URL = window.URL || window.webkitURL;
  
        navigator.getUserMedia({video: true, audio: true}, successCallback, errorCallback);
        function successCallback(stream) {
            localStream = stream;
            if (sourcevid.mozSrcObject) {
              sourcevid.mozSrcObject = stream;
              sourcevid.play();
            } else {
              try {
                sourcevid.src = window.URL.createObjectURL(stream);
                sourcevid.play();
              } catch(e) {
                console.log("Error setting video src: ", e);
              }
            }
        }
        function errorCallback(error) {
            console.error('An error occurred: [CODE ' + error.code + ']');
            return;
        }
    }
  
    // stop local video
    function stopVideo() {
      if (sourcevid.mozSrcObject) {
        sourcevid.mozSrcObject.stop();
        sourcevid.src = null;
      } else {
        sourcevid.src = "";
        localStream.stop();
      }
    }
  
    // send SDP via socket connection
    function setLocalAndSendMessage(sessionDescription) {
      peerConn.setLocalDescription(sessionDescription);
      console.log("Sending: SDP");
      console.log(sessionDescription);
      socket.json.send(sessionDescription);
    }
  
    function createOfferFailed() {
      console.log("Create Answer failed");
    }
  
    // start the connection upon user request
    function connect() {
      if (!started &amp;&amp; localStream &amp;&amp; channelReady) {
        createPeerConnection();
        started = true;
        peerConn.createOffer(setLocalAndSendMessage, createOfferFailed, mediaConstraints);
      } else {
        alert("Local stream not running yet - try again.");
      }
    }
  
    // stop the connection upon user request
    function hangUp() {
      console.log("Hang up.");    
      socket.json.send({type: "bye"});
      stop();
    }
  
    function stop() {
      peerConn.close();
      peerConn = null;
      started = false;    
    }
  
    // socket: channel connected
    socket.on('connect', onChannelOpened)
          .on('message', onMessage);
  
    function onChannelOpened(evt) {
      console.log('Channel opened.');
      channelReady = true;
    }
  
    function createAnswerFailed() {
      console.log("Create Answer failed");
    }
    // socket: accept connection request
    function onMessage(evt) {
      if (evt.type === 'offer') {
        console.log("Received offer...")
        if (!started) {
          createPeerConnection();
          started = true;
        }
        console.log('Creating remote session description...' );
        peerConn.setRemoteDescription(new RTCSessionDescription(evt));
        console.log('Sending answer...');
        peerConn.createAnswer(setLocalAndSendMessage, createAnswerFailed, mediaConstraints);
  
      } else if (evt.type === 'answer' &amp;&amp; started) {
        console.log('Received answer...');
        console.log('Setting remote session description...' );
        peerConn.setRemoteDescription(new RTCSessionDescription(evt));
  
      } else if (evt.type === 'candidate' &amp;&amp; started) {
        console.log('Received ICE candidate...');
        var candidate = new RTCIceCandidate({sdpMLineIndex:evt.sdpMLineIndex, sdpMid:evt.sdpMid, candidate:evt.candidate});
        console.log(candidate);
        peerConn.addIceCandidate(candidate);
  
      } else if (evt.type === 'bye' &amp;&amp; started) {
        console.log("Received bye");
        stop();
      }
    }
  
    function createPeerConnection() {
      console.log("Creating peer connection");
      RTCPeerConnection = webkitRTCPeerConnection || mozRTCPeerConnection;
      var pc_config = {"iceServers":[]};
      try {
        peerConn = new RTCPeerConnection(pc_config);
      } catch (e) {
        console.log("Failed to create PeerConnection, exception: " + e.message);
      }
      // send any ice candidates to the other peer
      peerConn.onicecandidate = function (evt) {
        if (event.candidate) {
          console.log('Sending ICE candidate...');
          console.log(evt.candidate);
          socket.json.send({type: "candidate",
                            sdpMLineIndex: evt.candidate.sdpMLineIndex,
                            sdpMid: evt.candidate.sdpMid,
                            candidate: evt.candidate.candidate});
        } else {
          console.log("End of candidates.");
        }
      };
      console.log('Adding local stream...');
      peerConn.addStream(localStream);
  
      peerConn.addEventListener("addstream", onRemoteStreamAdded, false);
      peerConn.addEventListener("removestream", onRemoteStreamRemoved, false)
  
      // when remote adds a stream, hand it on to the local video element
      function onRemoteStreamAdded(event) {
        console.log("Added remote stream");
        remotevid.src = window.URL.createObjectURL(event.stream);
      }
  
      // when remote removes a stream, remove it from the local video element
      function onRemoteStreamRemoved(event) {
        console.log("Remove remote stream");
        remotevid.src = "";
      }
    }
    &lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>And the Javascript file (server.js) for the server (with same port number as above):</p>
  
  <pre><code>// create the http server and listen on port
  var server = require('http').createServer();
  var app = server.listen(1337, function() {
    console.log((new Date()) + " Server is listening on port 1337");
  });
  
  // create the socket server on the port
  var io = require('socket.io').listen(app);
  
  
  // This callback function is called every time a socket
  // tries to connect to the server
  io.sockets.on('connection', function(socket) {
  
      console.log((new Date()) + ' Connection established.');
  
      // When a user send a SDP message
      // broadcast to all users in the room
      socket.on('message', function(message) {
          console.log((new Date()) + ' Received Message, broadcasting: ' + message);
          socket.broadcast.emit('message', message);
      });
  
      // When the user hangs up
      // broadcast bye signal to all users in the room
      socket.on('disconnect', function() {
          // close user connection
          console.log((new Date()) + " Peer disconnected.");
          socket.broadcast.emit('user disconnected');
      });
  
  });
  </code></pre>
  
  <p>I have node.js installed. Next I installed express and socket.io:</p>
  
  <pre><code>npm install express
  npm install socket.io
  </code></pre>
  
  <p>I then run this file with node to start the server.</p>
  
  <pre><code>node server.js
  </code></pre>
  
  <p>Accessing the index.html from the server gives me this error</p>
  
  <pre><code>Uncaught TypeError: Object #&lt;Object&gt; has no method 'connect' 
  </code></pre>
  
  <p>This was being caused by the line var socket = <code>io.connect('localhost:1337/');</code> in server.js</p>
  
  <p>I have searched this error and have tried putting the socket.io file on the server and linking it as <code>&lt;script src="/socket.io/socket.io.js"&gt;&lt;/script&gt;</code>, doesn't change anything.</p>