WebRTC is a new standard being put forth by the W3C to create an API to deliver realtime data, audio, and video between browsers in a peer to peer fashion.
Unfortunately, there is a fair amount of complexity involved in sending descriptions of the data, audio and video channels from peer to peer.
Fortunately, a few JavaScript libraries have popped up to aide in this. One, in particular that we'll go over is PeerJS
The first step is to do our normal getUserMedia, gaining access to a stream from the user's camera and microphone:
/* Get User Media */ var my_stream = null; window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL; navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; if (navigator.getUserMedia) { navigator.getUserMedia({video: true, audio: true}, function(stream) { my_stream = stream; var videoElement = document.getElementById('myvideo'); videoElement.src = window.URL.createObjectURL(stream) || stream; videoElement.play(); }, function(err) { console.log('Failed to get local stream' ,err); }); }This requires that a video element be present on the page with the id of "myvideo":
<video id="myvideo" width="320" height="240"></video>Also, it should be run inside an onload event as the video element isn't available until it is rendered.
The next step is to include the PeerJS JavaScript library:
<script src="http://cdn.peerjs.com/0.3/peer.min.js">/script>and to create an instance of a "peer" and connect to the PeerJS server
// We'll use a global variable to hold on to our id from PeerJS var peer_id = null; // Register for an API Key: http://peerjs.com/peerserver var peer = new Peer({key: 'YOU API KEY'}); // Get an ID from the PeerJS server peer.on('open', function(id) { console.log('My peer ID is: ' + id); peer_id = id; });
This should be enough for us to receive a "call"
peer.on('call', function(incoming_call) { console.log("Got a call!"); incoming_call.answer(my_stream); // Answer the call with our stream from getUserMedia incoming_call.on('stream', function(remoteStream) { // we receive a getUserMedia stream from the remote caller // And attach it to a video object var ovideoElement = document.getElementById('othervideo'); ovideoElement.src = window.URL.createObjectURL(remoteStream) || remoteStream; ovideoElement.play(); }); });
PeerJS runs a server which aides in the transmission of audio/video/data channel information but we'll still need to run a server to introduce the users to each-other. We can use a normal WebSocket server as we have been doing and use it to share the PeerJS ID value between users.
Here is a basic server that relays the peer_id's:
// HTTP Portion var http = require('http'); var fs = require('fs'); // Using the filesystem module var httpServer = http.createServer(requestHandler); httpServer.listen(8080); function requestHandler(req, res) { // Read index.html fs.readFile(__dirname + '/webrtc.html', // Callback function for reading function (err, data) { // if there is an error if (err) { res.writeHead(500); return res.end('Error loading index.html'); } // Otherwise, send the data, the contents of the file res.writeHead(200); res.end(data); } ); } // WebSocket Portion // WebSockets work with the HTTP server var io = require('socket.io').listen(httpServer); // Register a callback function to run when we have an individual connection // This is run for each individual user that connects io.sockets.on('connection', // We are given a websocket object in our function function (socket) { console.log("We have a new client: " + socket.id); socket.on('peer_id', function(data) { console.log("Received: 'peer_id' " + data); // We can save this in the socket object if we like socket.peer_id = data; console.log("Saved: " + socket.peer_id); // We can loop through these if we like for (var i = 0; i < io.sockets.clients().length; i++) { console.log("loop: " + i + " " + io.sockets.clients()[i].peer_id); } // Tell everyone my peer_id socket.broadcast.emit('peer_id',data); }); socket.on('disconnect', function() { console.log("Client has disconnected"); }); } );
To use the server, we'll use our normal Socket.io code:
/* Socket Server - Socket.io */ var socket = io.connect('YOUR SOCKET.IO SERVER URL PORT'); // When we connect, assuming we have a peer_id, send it out socket.on('connect', function() { console.log("Connected"); // When we connect, if we have a peer_id, send it out if (peer_id != null) { console.log("peer id is not null, sending it"); socket.emit("peer_id",peer_id); } }); // Receive other folks peer_ids socket.on('peer_id', function (data) { console.log("Got a new peer: " + data); // Call them with our stream, my_stream console.log("Calling peer: " + data); var call = peer.call(data, my_stream); // After they answer, we'll get a 'stream' event with their stream call.on('stream', function(remoteStream) { console.log("Got remote stream"); document.getElementById('othervideo').src = window.URL.createObjectURL(remoteStream) || remoteStream; }); });Here is a full example: webrtc_video.zip