preface


I wrote an article about Websocket “Online Chat room based on WebSocket (I) (II)” before, this time I changed to WebRTC to realize voice and video functions.

The client


There are plenty of WebRTC demos available online, but many of them won’t work even if they climb the wall. In addition, it is complicated to configure using WebRTC directly, so in this article, we use a package library of WebRTC, SimpleWebRTC, the website is github.com/andyet/Simp… , this is a nodeJS project, after testing can be directly used in the LAN without climbing over the wall.

First, introduce latest-v2.js from the demo above into the page

<script type="text/javascript" src="js/latest-v2.js"></script>
Copy the code

Webrtc is then configured in JS and the connection is established

webrtc = new SimpleWebRTC({
    // The id of the video element that displays the local camera screen
    localVideoEl: 'myVideo'.// The id of the video element that displays the image of the remote camera
    remoteVideosEl: ' '.// Automatically requests access to media devices, i.e. the popup box asks whether access to camera and microphone devices is allowed
    autoRequestMedia: true.debug: false.detectSpeakingEvents: true.// Media request parameters
    media: {
        video: true./ / camera
        audio: true/ / the microphone
    },
    autoAdjustMic: false
});
// Add the video control to display the screen when new remote videos are uploaded
webrtc.on('videoAdded'.function (video, peer) {
	console.log('video added', peer);
	$(video).fadeIn('slow').appendTo(Console.Win + " #videocontent");
	$(video).attr("id"."dest-" + peer.id);
});
// Remove the video screen when the remote video stream is disconnected
webrtc.on('videoRemoved'.function (video, peer) {
    console.log('video removed ', peer);
    var dest = $('video[id="dest-' + peer.id + '"]);
	dest && dest.remove()
});
Copy the code

To join the room

webrtc.joinRoom('video');// 'video' is the name of the room, which can be set arbitrarily, but can only be used in the same room
Copy the code

Leave the room

webrtc.leaveRoom();// The remote client cannot receive the audio/video stream after leaving the room
Copy the code

Note: WebrTC seems to have requirements for chrominum, so we recommend upgrading to the latest Chrome browser. Edge browser support has been tested and IE11 still does not support it.

The service side


The previous server used Tomcat7, so this time we will use nodeJS instead. The most common examples of websocket in NodeJS on the web are socket.io, which claims to provide the following real-time connection schemes and automatically selects the most capable transport mode at runtime without affecting API usage.

* WebSocket * Adobe Flash Socket * AJAX long polling * AJAX multiple streams * Iframe * JSONP pollingCopy the code

However, I feel that the usage of socket. IO is complicated, or there are some differences from the previous tomcat development ideas, and the triggered event name is strange, which I cannot accept for a while (it seems that the client also needs to change the socket. IO writing method), so I give up and choose to use the original usage, which is similar to the client. The most important thing is that the client doesn’t have to change.

Nodejs environment configuration here is not much to introduce, I am also n long ago curious to come over to play, perennial use, a rookie.

First, install the WS module

NPM install ws // it is better to install in the global path with -g so that you do not have to install everywhereCopy the code

And then there was a flood of code

(function(){
	// HTTP service Settings
	var express = require('express'),
		app = express(),
		http = require('http').createServer(app);

	app.use(express.static(__dirname));

	http.listen(8080.function(){
		console.log('httpServer: listening on "http://localhost:8080"');
	});

	// WebSocket service Settings
	var WebSocketServer = require('ws').Server,
		wss = new WebSocketServer({
			port: 8082.// Port Settings, preferably different from the HTTP service listening port
			// host: "localhost",// If this parameter is not set, websocket requests can be initiated using external, internal, or loopback addresses. After this parameter is set, only specified IP addresses can be used
			path: "/websocket/chat"// Request address, do not set the default root path
		}, function() {
			console.log('websocketServer: listening on "ws://localhost:8082/chat"');
		}),
		connectionList = new ArrayList(),
		roomInfo = {};

	// The connection is established
	wss.on('connection'.function(ws) {
		var wsid = ws._ultron.id,
			name = "Tourists" + new Date().getTime().toString();

		console.log("%s joined the chat room.",name);

		roomInfo = connectionList.length > 0 ? roomInfo : {
			creater: name,
			createTime: new Date().toLocaleString()
		};

		connectionList.add({
			wsid: wsid,
			name: name,
			connect: ws
		});

		var	dests = getDests(),
			setNameMsg = {
				host: name,
				type: 6.//setName
				roomInfo: roomInfo,
				dests: dests
			},
			joinMsg = {
				host: name,
				type: 1.//setName
				roomInfo: roomInfo,
				dests: dests
			},
			msg = JSON.stringify(setNameMsg);

		// Set the name
		ws.send(msg);

		msg = JSON.stringify(joinMsg);

		// Notify everyone of a new connection
	    connectionList.foreach(function(obj) {
	    	obj.connect.send(msg);
	    });

		// Received the message
	    ws.on('message'.function(message) {
	        console.log('Received message from %s: %s', name, message);
	        
	        // deserialize
	        var msg = JSON.parse(message);

	        msg.host = name;
	        
	        / / the serialization
	        message = JSON.stringify(msg);
	        
	        connectionList.foreach(function(obj) {
	        	obj.connect.send(message);
	        });
	    });

	    // The connection is down
	    ws.on('close'.function(message) {
	        console.log("%s left the chat room.", name  );
	        
	        // Remove the current connection
			var index = connectionList.find(function(obj) {
	        	return obj.wsid == wsid;
	        });

	        index > -1 && connectionList.removeAt(index);

			var closeMsg = {
				host: name,
				type: 2.//close
				dests: getDests()
			};

	        message = JSON.stringify(closeMsg);

	        connectionList.foreach(function(obj) {
	        	obj.connect.send(message);
	        });
	    });
	});

	function getDests() {
		var dests = [];

	    connectionList.foreach(function(obj) {
	    	dests[dests.length] = obj.name;
	    });

	    return dests;
	}

	function ArrayList(array) {
		this.array = typeofarray ! = ='undefined' && array instanceof Array ? array : new Array(a);this.length = this.array.length;
		var that = this,
			setLength = function() {
			that.length = that.array.length;
		};

		this.get = function(index){
			return this.array[index];
		}
		this.add = function(obj) {
			this.array.push(obj);
			setLength();
		};

		this.indexOf = function(obj) {
			return this.array.indexOf(obj);
		}

		this.find = function(callback) {
			for(var i = 0; i < this.length; i++){
				if(callback(this.get(i))) {
					returni; }}return -1;
		}

		this.removeAt = function(index){ 
			this.array.splice(index, 1);
			setLength();
		};

		this.remove = function(obj){ 
			var index = this.indexOf(obj); 
			if (index >= 0) {this.removeAt(index); }};this.clear = function(){ 
			this.array.length = 0;
			setLength();
		};

		this.insertAt = function(index, obj){ 
			this.array.splice(index, 0, obj);
			setLength();
		};

		this.foreach = function(callback) {
			for(var i = 0; i < this.length; i++){
				callback(this.get(i)); }}; }}) ();Copy the code

Write the above code to server.js, then run the command line to switch to the current directory and start the service using the Node server command (in my case, double-click the batch file in the root directory of the project to open it).

Two servers are started. HTTP is the HTTP server, which is used for page access in the current directory. The other WSS is the WebSocket server, which is used for the WebSocket service. When a new connection is established, the WebSocket server triggers the “connection” event. When a message is received and the connection is disconnected, the webSocket server triggers the “object” event. This is slightly different from tomcat, which fires all ServerEndpoint events.

The reverse proxy configuration of Nginx was mentioned at the end of the previous article, which also applies to NodeJS, so I won’t go into details here.

conclusion


  1. Thanks to the off-the-shelf wrapper library SimpleWebRTC, it has very little code, is very easy to use, and is much better in terms of performance than my previous implementation through WebSocket. However, the effect of the Internet access has not been tested, the Internet also needs STUN, ICE and other servers to achieve NAT penetration, interested students can go over the wall to try.
  2. The server side is implemented by NodeJS, so that all the code is composed of HTML + JS + CSS, and the service starts quickly and consumes little memory.

Reference article:

  • Blog.chinaunix.net/uid-2456787…
  • My.oschina.net/yushulx/blo…

The project code is already ingithubUpdate on


Please indicate the source of reprint:www.jianshu.com/p/63d4d1528…