Create webrtc connexion between two player
This commit is contained in:
parent
0f2e21e88e
commit
5b62ac39fb
13 changed files with 769 additions and 8 deletions
|
@ -1,6 +1,7 @@
|
|||
import {GameSceneInterface, GameScene} from "./GameScene";
|
||||
import {ROOM} from "../../Enum/EnvironmentVariable"
|
||||
import {Connexion, ConnexionInterface, ListMessageUserPositionInterface} from "../../Connexion";
|
||||
import {WebRtcEventManager} from "../../WebRtc/WebRtcEventManager";
|
||||
|
||||
export enum StatusGameManagerEnum {
|
||||
IN_PROGRESS = 1,
|
||||
|
@ -28,6 +29,8 @@ export class GameManager implements GameManagerInterface {
|
|||
return ConnexionInstance.createConnexion().then(() => {
|
||||
this.configureGame();
|
||||
/** TODO add loader in the page **/
|
||||
//initialise cam
|
||||
new WebRtcEventManager(ConnexionInstance);
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
throw err;
|
||||
|
|
183
front/src/WebRtc/Index.ts
Normal file
183
front/src/WebRtc/Index.ts
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*import {ConnexionInterface} from "../Connexion";
|
||||
|
||||
const Peer = require('simple-peer');
|
||||
|
||||
let cinemaClose : any = null;
|
||||
let cinema : any = null;
|
||||
let microphoneClose : any = null;
|
||||
let microphone : any = null;
|
||||
|
||||
let localStream : MediaStream = null;
|
||||
let remoteStream : MediaStream = null;
|
||||
let remoteVideo : any = null;
|
||||
let myCamVideo : any = null;
|
||||
|
||||
let promiseGetCam : Promise<any> = null;
|
||||
|
||||
let peer : any = null;
|
||||
|
||||
let Connexion : ConnexionInterface = null;
|
||||
|
||||
let roomId = "test-wertc";
|
||||
|
||||
let gettingCamera : Promise<any> = null;
|
||||
let constraintsMedia = {audio: true, video: true};
|
||||
|
||||
function joinRoom(){
|
||||
Connexion.JoinRoomWebRtc(roomId);
|
||||
Connexion.startRoomWebRtc(initialiseWebSocket)
|
||||
}
|
||||
|
||||
function initialiseWebSocket(message : any){
|
||||
console.log('initialiseWebSocket => message', message);
|
||||
peer = new Peer({
|
||||
initiator: message.initiator
|
||||
});
|
||||
|
||||
peer.on('signal', (data : any) => {
|
||||
//send signal
|
||||
//permit to send message and initialise peer connexion
|
||||
console.log('signal sended', data);
|
||||
Connexion.shareSignalWebRtc({
|
||||
roomId: roomId,
|
||||
signal: data
|
||||
});
|
||||
});
|
||||
|
||||
//permit to receive message and initialise peer connexion
|
||||
Connexion.receiveSignalWebRtc((data : any) => {
|
||||
let signal = JSON.parse(data);
|
||||
console.log('receiveSignalWebRtc => signal', signal);
|
||||
peer.signal(signal.signal);
|
||||
});
|
||||
|
||||
peer.on('stream', (stream : MediaStream) => {
|
||||
// got remote video stream, now let's show it in a video tag
|
||||
console.log("peer => stream", stream);
|
||||
|
||||
//set local stream in little cam
|
||||
myCamVideo.srcObject = localStream;
|
||||
|
||||
//set remote stream in remote video
|
||||
remoteStream = stream;
|
||||
remoteVideo.srcObject = stream;
|
||||
});
|
||||
|
||||
peer.on('connect', () => {
|
||||
console.log('CONNECT')
|
||||
peer.send('whatever' + Math.random())
|
||||
});
|
||||
|
||||
peer.on('data', (data : any) => {
|
||||
console.log('data: ' + data)
|
||||
});
|
||||
|
||||
peer.on('close', (err : any) => console.error('close', err));
|
||||
peer.on('error', (err : any) => console.error('error', err));
|
||||
|
||||
|
||||
peer.on('track', (track : any, stream : any) => {
|
||||
remoteStream = stream;
|
||||
remoteVideo.srcObject = stream;
|
||||
track.onended = (e : any) => remoteVideo.srcObject = remoteVideo.srcObject; // Chrome/Firefox bug
|
||||
});
|
||||
|
||||
gettingCamera.then(() => {
|
||||
addMedia();
|
||||
});
|
||||
}
|
||||
|
||||
//get camera
|
||||
function getCamera() {
|
||||
gettingCamera = navigator.mediaDevices.getUserMedia(constraintsMedia)
|
||||
.then((stream: MediaStream) => {
|
||||
localStream = stream;
|
||||
remoteVideo.srcObject = stream;
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
localStream = null;
|
||||
throw err;
|
||||
});
|
||||
return gettingCamera;
|
||||
}
|
||||
|
||||
function addMedia () {
|
||||
if(peer) {
|
||||
peer.addStream(localStream) // <- add streams to peer dynamically
|
||||
}
|
||||
}
|
||||
|
||||
function enabledCamera(){
|
||||
cinemaClose.style.display = "none";
|
||||
cinema.style.display = "block";
|
||||
constraintsMedia.video = true;
|
||||
}
|
||||
|
||||
function disabledCamera(){
|
||||
cinemaClose.style.display = "block";
|
||||
cinema.style.display = "none";
|
||||
constraintsMedia.video = false;
|
||||
}
|
||||
|
||||
function enabledMicrophone(){
|
||||
microphoneClose.style.display = "none";
|
||||
microphone.style.display = "block";
|
||||
constraintsMedia.audio = true;
|
||||
}
|
||||
|
||||
function disabledMicrophone(){
|
||||
microphoneClose.style.display = "block";
|
||||
microphone.style.display = "none";
|
||||
constraintsMedia.audio = false;
|
||||
}
|
||||
|
||||
function showWebRtc(){
|
||||
remoteVideo = document.getElementById('activeCamVideo');
|
||||
myCamVideo = document.getElementById('myCamVideo');
|
||||
|
||||
microphoneClose = document.getElementById('microphone-close');
|
||||
microphoneClose.addEventListener('click', (e : any) => {
|
||||
e.preventDefault();
|
||||
enabledMicrophone();
|
||||
//update tracking
|
||||
});
|
||||
|
||||
microphone = document.getElementById('microphone');
|
||||
microphone.addEventListener('click', (e : any) => {
|
||||
e.preventDefault();
|
||||
disabledMicrophone();
|
||||
//update tracking
|
||||
});
|
||||
|
||||
cinemaClose = document.getElementById('cinema-close');
|
||||
cinemaClose.addEventListener('click', (e : any) => {
|
||||
e.preventDefault();
|
||||
enabledCamera();
|
||||
//update tracking
|
||||
});
|
||||
cinema = document.getElementById('cinema');
|
||||
cinema.addEventListener('click', (e : any) => {
|
||||
e.preventDefault();
|
||||
disabledCamera();
|
||||
//update tracking
|
||||
});
|
||||
|
||||
enabledMicrophone();
|
||||
enabledCamera();
|
||||
|
||||
let webRtc = document.getElementById('webRtc');
|
||||
webRtc.classList.add('active');
|
||||
}
|
||||
|
||||
export const initialisation = (ConnexionInterface : ConnexionInterface) => {
|
||||
Connexion = ConnexionInterface;
|
||||
|
||||
//show camera
|
||||
showWebRtc();
|
||||
|
||||
//open the camera
|
||||
getCamera();
|
||||
|
||||
//join room to create webrtc
|
||||
joinRoom();
|
||||
};*/
|
89
front/src/WebRtc/MediaManager.ts
Normal file
89
front/src/WebRtc/MediaManager.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
export class MediaManager {
|
||||
localStream: MediaStream;
|
||||
remoteStream: MediaStream;
|
||||
remoteVideo: any;
|
||||
myCamVideo: any;
|
||||
cinemaClose: any = null;
|
||||
cinema: any = null;
|
||||
microphoneClose: any = null;
|
||||
microphone: any = null;
|
||||
constraintsMedia = {audio: true, video: true};
|
||||
getCameraPromise : Promise<any> = null;
|
||||
|
||||
constructor() {
|
||||
this.remoteVideo = document.getElementById('activeCamVideo');
|
||||
this.myCamVideo = document.getElementById('myCamVideo');
|
||||
|
||||
this.microphoneClose = document.getElementById('microphone-close');
|
||||
this.microphoneClose.addEventListener('click', (e: any) => {
|
||||
e.preventDefault();
|
||||
this.enabledMicrophone();
|
||||
//update tracking
|
||||
});
|
||||
|
||||
this.microphone = document.getElementById('microphone');
|
||||
this.microphone.addEventListener('click', (e: any) => {
|
||||
e.preventDefault();
|
||||
this.disabledMicrophone();
|
||||
//update tracking
|
||||
});
|
||||
|
||||
this.cinemaClose = document.getElementById('cinema-close');
|
||||
this.cinemaClose.addEventListener('click', (e: any) => {
|
||||
e.preventDefault();
|
||||
this.enabledCamera();
|
||||
//update tracking
|
||||
});
|
||||
this.cinema = document.getElementById('cinema');
|
||||
this.cinema.addEventListener('click', (e: any) => {
|
||||
e.preventDefault();
|
||||
this.disabledCamera();
|
||||
//update tracking
|
||||
});
|
||||
|
||||
this.enabledMicrophone();
|
||||
this.enabledCamera();
|
||||
|
||||
let webRtc = document.getElementById('webRtc');
|
||||
webRtc.classList.add('active');
|
||||
|
||||
this.getCamera();
|
||||
}
|
||||
|
||||
enabledCamera() {
|
||||
this.cinemaClose.style.display = "none";
|
||||
this.cinema.style.display = "block";
|
||||
this.constraintsMedia.video = true;
|
||||
}
|
||||
|
||||
disabledCamera() {
|
||||
this.cinemaClose.style.display = "block";
|
||||
this.cinema.style.display = "none";
|
||||
this.constraintsMedia.video = false;
|
||||
}
|
||||
|
||||
enabledMicrophone() {
|
||||
this.microphoneClose.style.display = "none";
|
||||
this.microphone.style.display = "block";
|
||||
this.constraintsMedia.audio = true;
|
||||
}
|
||||
|
||||
disabledMicrophone() {
|
||||
this.microphoneClose.style.display = "block";
|
||||
this.microphone.style.display = "none";
|
||||
this.constraintsMedia.audio = false;
|
||||
}
|
||||
|
||||
//get camera
|
||||
getCamera() {
|
||||
this.getCameraPromise = navigator.mediaDevices.getUserMedia(this.constraintsMedia)
|
||||
.then((stream: MediaStream) => {
|
||||
this.localStream = stream;
|
||||
this.myCamVideo.srcObject = this.localStream;
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
this.localStream = null;
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
}
|
136
front/src/WebRtc/PeerConnexionManager.ts
Normal file
136
front/src/WebRtc/PeerConnexionManager.ts
Normal file
|
@ -0,0 +1,136 @@
|
|||
import {WebRtcEventManager} from "./WebRtcEventManager";
|
||||
import {MediaManager} from "./MediaManager";
|
||||
const offerOptions = {
|
||||
offerToReceiveAudio: 1,
|
||||
offerToReceiveVideo: 1,
|
||||
iceServers: [{url:'stun:stun.l.google.com:19302'}],
|
||||
};
|
||||
|
||||
export class PeerConnexionManager {
|
||||
|
||||
WebRtcEventManager: WebRtcEventManager;
|
||||
MediaManager : MediaManager;
|
||||
|
||||
peerConnection: RTCPeerConnection;
|
||||
|
||||
constructor(WebRtcEventManager : WebRtcEventManager) {
|
||||
this.WebRtcEventManager = WebRtcEventManager;
|
||||
this.MediaManager = new MediaManager();
|
||||
}
|
||||
|
||||
createPeerConnection(data: any = null): Promise<any> {
|
||||
this.peerConnection = new RTCPeerConnection();
|
||||
|
||||
//init all events peer connection
|
||||
this.createEventPeerConnection();
|
||||
|
||||
this.MediaManager.getCameraPromise.then(() => {
|
||||
this.MediaManager.localStream.getTracks().forEach(
|
||||
(track : MediaStreamTrack) => this.peerConnection.addTrack(track, this.MediaManager.localStream)
|
||||
);
|
||||
});
|
||||
|
||||
//if no data, create offer
|
||||
if (!data || !data.message) {
|
||||
return this.createOffer();
|
||||
}
|
||||
|
||||
let description = new RTCSessionDescription(data.message);
|
||||
return this.peerConnection.setRemoteDescription(description).catch((err) => {
|
||||
console.error("createPeerConnection => setRemoteDescription", err);
|
||||
throw err;
|
||||
})
|
||||
}
|
||||
|
||||
createOffer(): Promise<any> {
|
||||
console.log('pc1 createOffer start');
|
||||
// @ts-ignore
|
||||
return this.peerConnection.createOffer(offerOptions).then((offer: RTCSessionDescriptionInit) => {
|
||||
this.peerConnection.setLocalDescription(offer).then(() => {
|
||||
let message = {message: this.peerConnection.localDescription};
|
||||
this.WebRtcEventManager.emitVideoOffer(message);
|
||||
}).catch((err) => {
|
||||
console.error("createOffer => setLocalDescription", err);
|
||||
throw err;
|
||||
});
|
||||
}).catch((err: Error) => {
|
||||
console.error("createOffer => createOffer", err);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
createAnswer(): Promise<any> {
|
||||
return this.peerConnection.createAnswer().then((answer : RTCSessionDescriptionInit) => {
|
||||
this.peerConnection.setLocalDescription(answer).then(() => {
|
||||
//push video-answer
|
||||
let messageSend = {message: this.peerConnection.localDescription};
|
||||
this.WebRtcEventManager.emitVideoAnswer(messageSend);
|
||||
console.info("video-answer => send", messageSend);
|
||||
}).catch((err) => {
|
||||
console.error("eventVideoOffer => createAnswer => setLocalDescription", err);
|
||||
throw err;
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.error("eventVideoOffer => createAnswer", err);
|
||||
throw err;
|
||||
})
|
||||
}
|
||||
|
||||
setRemoteDescription(data: any): Promise<any> {
|
||||
let description = new RTCSessionDescription(data.message);
|
||||
return this.peerConnection.setRemoteDescription(description).catch((err) => {
|
||||
console.error("PeerConnexionManager => setRemoteDescription", err);
|
||||
throw err;
|
||||
})
|
||||
}
|
||||
|
||||
addIceCandidate(data: any): Promise<any> {
|
||||
return this.peerConnection.addIceCandidate(data.message)
|
||||
.catch((err) => {
|
||||
console.error("PeerConnexionManager => addIceCandidate", err);
|
||||
throw err;
|
||||
})
|
||||
}
|
||||
|
||||
hangup() {
|
||||
console.log('Ending call');
|
||||
if (this.peerConnection) {
|
||||
this.peerConnection.close();
|
||||
}
|
||||
this.peerConnection = null;
|
||||
}
|
||||
|
||||
createEventPeerConnection(){
|
||||
//define creator of offer
|
||||
this.peerConnection.onicecandidate = (event: RTCPeerConnectionIceEvent) => {
|
||||
let message = {message: event.candidate};
|
||||
if (!event.candidate) {
|
||||
return;
|
||||
}
|
||||
this.WebRtcEventManager.emitIceCandidate(message);
|
||||
};
|
||||
|
||||
this.peerConnection.ontrack = (e:RTCTrackEvent) => {
|
||||
console.info('Event:track', e);
|
||||
this.MediaManager.remoteVideo.srcObject = e.streams[0];
|
||||
this.MediaManager.myCamVideo.srcObject = e.streams[0];
|
||||
};
|
||||
|
||||
this.peerConnection.onnegotiationneeded = (e : Event) => {
|
||||
console.info("Event:negotiationneeded => call()", e);
|
||||
this.createOffer()
|
||||
};
|
||||
this.peerConnection.oniceconnectionstatechange = (e) => {
|
||||
console.info('ICE state change event: ', e);
|
||||
};
|
||||
this.peerConnection.oniceconnectionstatechange = (e:Event) => {
|
||||
console.info('oniceconnectionstatechange => iceConnectionState', this.peerConnection.iceConnectionState);
|
||||
};
|
||||
this.peerConnection.onicegatheringstatechange = () => {
|
||||
console.info('onicegatheringstatechange => iceConnectionState', this.peerConnection.iceConnectionState);
|
||||
};
|
||||
this.peerConnection.onsignalingstatechange = () => {
|
||||
console.info('onsignalingstatechange => iceConnectionState', this.peerConnection.iceConnectionState);
|
||||
};
|
||||
}
|
||||
}
|
86
front/src/WebRtc/WebRtcEventManager.ts
Normal file
86
front/src/WebRtc/WebRtcEventManager.ts
Normal file
|
@ -0,0 +1,86 @@
|
|||
import {ConnexionInterface} from "../Connexion";
|
||||
import {PeerConnexionManager} from "./PeerConnexionManager";
|
||||
|
||||
export class WebRtcEventManager {
|
||||
Connexion: ConnexionInterface;
|
||||
PeerConnexionManager: PeerConnexionManager;
|
||||
RoomId : string;
|
||||
|
||||
constructor(Connexion : ConnexionInterface, roomId : string = "test-webrtc") {
|
||||
this.RoomId = roomId;
|
||||
this.Connexion = Connexion;
|
||||
this.PeerConnexionManager = new PeerConnexionManager(this);
|
||||
|
||||
this.start();
|
||||
this.eventVideoOffer();
|
||||
this.eventVideoAnswer();
|
||||
this.eventIceCandidate();
|
||||
|
||||
//connect on the room to create a meet
|
||||
Connexion.socket.emit('webrtc-room', JSON.stringify({roomId: roomId}));
|
||||
}
|
||||
|
||||
/**
|
||||
* server has two person connected, start the meet
|
||||
*/
|
||||
start(){
|
||||
this.Connexion.socket.on('webrtc-start', () => {
|
||||
return this.PeerConnexionManager.createPeerConnection();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive video offer
|
||||
*/
|
||||
eventVideoOffer() {
|
||||
this.Connexion.socket.on("video-offer", (message : any) => {
|
||||
let data = JSON.parse(message);
|
||||
console.info("video-offer", data);
|
||||
this.PeerConnexionManager.createPeerConnection(data).then(() => {
|
||||
return this.PeerConnexionManager.createAnswer();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive video answer
|
||||
*/
|
||||
eventVideoAnswer() {
|
||||
this.Connexion.socket.on("video-answer", (message : any) => {
|
||||
let data = JSON.parse(message);
|
||||
console.info("video-answer", data);
|
||||
this.PeerConnexionManager.setRemoteDescription(data)
|
||||
.catch((err) => {
|
||||
console.error("video-answer => setRemoteDescription", err)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive ice candidate
|
||||
*/
|
||||
eventIceCandidate() {
|
||||
this.Connexion.socket.on("ice-candidate", (message : any) => {
|
||||
let data = JSON.parse(message);
|
||||
console.info("ice-candidate", data);
|
||||
this.PeerConnexionManager.addIceCandidate(data).then(() => {
|
||||
console.log(`ICE candidate:\n${data.message ? data.message.candidate : '(null)'}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
emitIceCandidate(message : any){
|
||||
message.roomId = this.RoomId;
|
||||
this.Connexion.socket.emit('ice-candidate', JSON.stringify(message));
|
||||
}
|
||||
|
||||
emitVideoOffer(message : any){
|
||||
message.roomId = this.RoomId;
|
||||
this.Connexion.socket.emit('video-offer', JSON.stringify(message));
|
||||
}
|
||||
|
||||
emitVideoAnswer(message : any){
|
||||
message.roomId = this.RoomId;
|
||||
this.Connexion.socket.emit("video-answer", JSON.stringify(message));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue