mirror of
https://gitlab.com/comunic/nodejs-webrtcsignalexchangerserver
synced 2024-11-24 14:29:27 +00:00
First video call ever !!!
This commit is contained in:
parent
e9189376bc
commit
baa3971722
203
video-client/SignalExchangerClient.js
Normal file
203
video-client/SignalExchangerClient.js
Normal 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
3
video-client/server.py
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import SimpleHTTPServer
|
||||||
|
SimpleHTTPServer.test();
|
11
video-client/simplepeer.min.js
vendored
Normal file
11
video-client/simplepeer.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
28
video-client/test-video-client.html
Normal file
28
video-client/test-video-client.html
Normal 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>
|
114
video-client/test-video-client.js
Normal file
114
video-client/test-video-client.js
Normal 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);
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user