First video call ever !!!

This commit is contained in:
Pierre HUBERT 2019-01-20 16:26:06 +01:00
parent e9189376bc
commit baa3971722
5 changed files with 359 additions and 0 deletions

View File

@ -0,0 +1,203 @@
/**
* Signal exchanger web client
*
* @author Pierre HUBERT
*/
class SignalExchangerClient {
/**
* Server domain
*
* @type {String}
*/
//domain;
/**
* Server port
*
* @type {Number}
*/
//port;
/**
* Current client ID
*
* @type {String}
*/
//clientID;
/**
* Socket connection to the server
*
* @type {WebSocket}
*/
//socket;
/**
* Function called in case of error
*
* @type {Function}
*/
//onError = null;
/**
* Function called when the connection is etablished
*
* @type {Function}
*/
//onConnected = null;
/**
* Function called when the connection to the socket is closed
*
* @type {Function}
*/
//onClosed = null;
/**
* Function called when we get a new signal information
*
* @type {Function}
*/
//onSignal = null;
/**
* Construct a client instance
*
* @param {String} domain The name of the signal server
* @param {Number} port The port of the server to use
* @param {String} clientID The ID of current client
*/
constructor(domain, port, clientID) {
//Save information
this.domain = domain,
this.port = port;
this.clientID = clientID;
this.socket = new WebSocket("ws://" + this.domain + ":" + this.port + "/socket");
//Add a few events listeners
this.socket.addEventListener("open", () => {
this.serverConnected();
if(this.onConnected != null)
setTimeout(this.onConnected, 10);
});
this.socket.addEventListener("message", message => {
let data;
try {
data = JSON.parse(message.data);
} catch(e){
console.error("Could not parse message from server!");
return;
}
console.log("New message from socket", data);
this.serverMessage(data);
});
this.socket.addEventListener("error", () => {
if(this.onError != null)
setTimeout(this.onError, 0);
});
this.socket.addEventListener("close", () => {
if(this.onClosed != null)
setTimeout(this.onClosed, 0);
});
}
/**
* Method called once the client is successfully
* connected to the client
*/
serverConnected(){
//Send data to the server to identificate client
this.sendData({
client_id: this.clientID
});
}
/**
* Send a signal to the server
*
* @param target_id The ID of the target for the signal
* @param content Signal to send to the target
*/
sendSignal(target_id, content){
//Send directly the message to the server
this.sendData({
signal: content,
target_id: target_id
});
//Save the current signal being sent to be able to send
//it again in case of failure
this.pending_signal = content;
this.pending_signal_target = target_id;
}
/**
* Stop to try to send the current signal message in queue
*
* This does not cancel the sending of messages already sent through
* socket
*/
cancelCurrentSignal() {
this.pending_signal = undefined;
this.pending_signal_target = undefined;
}
/**
* Send data to the server
*
* @param {Object} data The data to send to the server
*/
sendData(data){
console.log("Sending data to server", data);
this.socket.send(JSON.stringify(data));
}
/**
* This method is called when the server has sent a new message to this client
*
* @param {Object} message The message sent by the server, as a JSON object
*/
serverMessage(message){
//Check if it is a callback for a pending message
if(message.signal_sent){
if(message.number_of_targets < 1 && this.pending_signal && this.pending_signal_target){
//We have to send the message again
setTimeout(() => {
this.sendSignal(this.pending_signal, this.pending_signal_target);
}, 1000);
}
else {
//Else we can remove from this class information about the signal being sent
this.cancelCurrentSignal();
}
}
// Check if the message is a signal
else if(message.signal){
if(this.onSignal != null)
this.onSignal(message.signal, message.source_id);
}
}
}

3
video-client/server.py Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env python
import SimpleHTTPServer
SimpleHTTPServer.test();

11
video-client/simplepeer.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Signal Exchanger Video test client</title>
<style>
video {
height: 250px;
}
</style>
</head>
<body>
<h1>Signal Exchanger test video client</h1>
<video id="localVideo" muted></video>
<video id="remoteVideo"></video>
<script src="simplepeer.min.js"></script>
<script src="SignalExchangerClient.js"></script>
<script src="test-video-client.js"></script>
</body>
</html>

View File

@ -0,0 +1,114 @@
/**
* Node Signal Exchanger test client
*
* @author Pierre HUBERT
*/
function byId(id){
return document.getElementById(id);
}
const Config = {
port: 8081,
server_name: "localhost",
clientID: location.href.toString().includes("#1") ? "client-1" : "client-2",
otherPeerID: location.href.toString().includes("#1") ? "client-2" : "client-1"
};
let client = new SignalExchangerClient(
Config.server_name,
Config.port,
Config.clientID
);
let peer;
let localStream;
client.onConnected = function(){
console.log("Connected to signal exchanger server.");
InitializeVideo();
}
client.onError = function() {
console.error("An error occurred with the connection to the signal exchanger server");
}
client.onClosed = function() {
console.log("Connection to server closed.");
}
client.onSignal = function(signal, peerID){
if(peerID !== Config.otherPeerID)
return alert("A signal from an unknow peer ID has just been received!");
peer.signal(JSON.parse(signal));
}
function InitializeVideo(){
navigator.mediaDevices
.getUserMedia({
audio: true,
video: true
})
.then(stream => {
localStream = stream;
InitializePeer();
//Play local video
let video = byId("localVideo");
video.srcObject = stream;
video.play();
})
.catch(err => {
alert("Can not continue because you did not accept to share your camera!");
console.error(err);
});
}
/**
* Initialize peer connection
*
* Warning : It is better to wait for the socket connection to be ready before
* launching this function if this peer is the initiator of the connection
*/
function InitializePeer() {
peer = new SimplePeer({
initiator: location.hash === '#1',
stream: localStream,
trickle: false,
config: {
'iceServers': [
{ urls: 'stun:127.0.0.1:3478' },
{"url":"turn:127.0.0.1:3478",
"credential":"anonymous",
"username": "anonymous"}
]
}
});
peer.on('error', function (err) { console.log('SimplePeer error', err) });
//Automatically send new signals to the other peer
peer.on('signal', function (data) {
console.log('SIGNAL', JSON.stringify(data))
client.sendSignal(Config.otherPeerID, JSON.stringify(data));
});
peer.on("stream", stream => {
let video = byId("remoteVideo");
video.srcObject = stream;
video.play();
});
peer.on("message", message => {
console.log("Message from remote peer: " + message);
});
}