Use WebRtc with SimplePeer
This commit is contained in:
parent
a5b5072de1
commit
c28108f6c9
@ -7,6 +7,7 @@ import Jwt, {JsonWebTokenError} from "jsonwebtoken";
|
|||||||
import {SECRET_KEY} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
import {SECRET_KEY} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
||||||
import {ExtRooms, RefreshUserPositionFunction} from "../Model/Websocket/ExtRoom";
|
import {ExtRooms, RefreshUserPositionFunction} from "../Model/Websocket/ExtRoom";
|
||||||
import {ExtRoomsInterface} from "_Model/Websocket/ExtRoomsInterface";
|
import {ExtRoomsInterface} from "_Model/Websocket/ExtRoomsInterface";
|
||||||
|
import {ExtWebSocket} from "../../../../publicis/sources/api/src/Entities/WebSocket/ExtWebSocket";
|
||||||
|
|
||||||
export class IoSocketController{
|
export class IoSocketController{
|
||||||
Io: socketIO.Server;
|
Io: socketIO.Server;
|
||||||
@ -84,28 +85,25 @@ export class IoSocketController{
|
|||||||
(socket as ExSocketInterface).roomId = data.roomId;
|
(socket as ExSocketInterface).roomId = data.roomId;
|
||||||
|
|
||||||
//if two persone in room share
|
//if two persone in room share
|
||||||
|
console.log("nb user => " + data.roomId, this.Io.sockets.adapter.rooms[data.roomId].length);
|
||||||
if(this.Io.sockets.adapter.rooms[data.roomId].length < 2) {
|
if(this.Io.sockets.adapter.rooms[data.roomId].length < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let clients : Array<any> = Object.values(this.Io.sockets.sockets);
|
let clients : Array<any> = Object.values(this.Io.sockets.sockets);
|
||||||
|
|
||||||
//send start at one client to initialise offer webrtc
|
//send start at one client to initialise offer webrtc
|
||||||
clients[0].emit('webrtc-start');
|
clients.forEach((client: ExtWebSocket, index : number) => {
|
||||||
|
client.emit('webrtc-start', JSON.stringify({
|
||||||
|
userId: client.userId,
|
||||||
|
initiator : index === 0
|
||||||
|
}));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('video-offer', (message : string) => {
|
socket.on('webrtc-signal', (message : string) => {
|
||||||
let data : any = JSON.parse(message);
|
let data : any = JSON.parse(message);
|
||||||
socket.to(data.roomId).emit('video-offer', message);
|
console.info('webrtc-signal', message);
|
||||||
});
|
socket.to(data.roomId).emit('webrtc-signal', message);
|
||||||
|
|
||||||
socket.on('video-answer', (message : string) => {
|
|
||||||
let data : any = JSON.parse(message);
|
|
||||||
socket.to(data.roomId).emit('video-answer', message);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('ice-candidate', (message : string) => {
|
|
||||||
let data : any = JSON.parse(message);
|
|
||||||
socket.to(data.roomId).emit('ice-candidate', message);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/axios": "^0.14.0",
|
"@types/axios": "^0.14.0",
|
||||||
|
"@types/simple-peer": "^9.6.0",
|
||||||
"@types/socket.io-client": "^1.4.32",
|
"@types/socket.io-client": "^1.4.32",
|
||||||
"phaser": "^3.22.0",
|
"phaser": "^3.22.0",
|
||||||
|
"simple-peer": "^9.6.2",
|
||||||
"socket.io-client": "^2.3.0"
|
"socket.io-client": "^2.3.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -4,6 +4,15 @@ const SocketIo = require('socket.io-client');
|
|||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import {API_URL} from "./Enum/EnvironmentVariable";
|
import {API_URL} from "./Enum/EnvironmentVariable";
|
||||||
|
|
||||||
|
enum EventMessage{
|
||||||
|
WEBRTC_SIGNAL = "webrtc-signal",
|
||||||
|
WEBRTC_START = "webrtc-start",
|
||||||
|
WEBRTC_ROOM = "webrtc-room",
|
||||||
|
JOIN_ROOM = "join-room",
|
||||||
|
USER_POSITION = "user-position",
|
||||||
|
MESSAGE_ERROR = "message-error"
|
||||||
|
}
|
||||||
|
|
||||||
class Message {
|
class Message {
|
||||||
userId: string;
|
userId: string;
|
||||||
roomId: string;
|
roomId: string;
|
||||||
@ -56,6 +65,7 @@ export interface MessageUserPositionInterface {
|
|||||||
roomId: string;
|
roomId: string;
|
||||||
position: PointInterface;
|
position: PointInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageUserPosition extends Message implements MessageUserPositionInterface{
|
class MessageUserPosition extends Message implements MessageUserPositionInterface{
|
||||||
position: PointInterface;
|
position: PointInterface;
|
||||||
|
|
||||||
@ -76,14 +86,15 @@ class MessageUserPosition extends Message implements MessageUserPositionInterfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ListMessageUserPositionInterface {
|
export interface ListMessageUserPositionInterface {
|
||||||
roomId : string;
|
roomId: string;
|
||||||
listUsersPosition: Array<MessageUserPosition>;
|
listUsersPosition: Array<MessageUserPosition>;
|
||||||
}
|
}
|
||||||
class ListMessageUserPosition{
|
|
||||||
roomId : string;
|
class ListMessageUserPosition {
|
||||||
|
roomId: string;
|
||||||
listUsersPosition: Array<MessageUserPosition>;
|
listUsersPosition: Array<MessageUserPosition>;
|
||||||
|
|
||||||
constructor(roomId : string, data : any) {
|
constructor(roomId: string, data: any) {
|
||||||
this.roomId = roomId;
|
this.roomId = roomId;
|
||||||
this.listUsersPosition = new Array<MessageUserPosition>();
|
this.listUsersPosition = new Array<MessageUserPosition>();
|
||||||
data.forEach((userPosition: any) => {
|
data.forEach((userPosition: any) => {
|
||||||
@ -99,32 +110,47 @@ class ListMessageUserPosition{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConnexionInterface {
|
export interface ConnexionInterface {
|
||||||
socket : any;
|
socket: any;
|
||||||
token : string;
|
token: string;
|
||||||
email : string;
|
email: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
startedRoom : string;
|
startedRoom: string;
|
||||||
createConnexion() : Promise<any>;
|
|
||||||
joinARoom(roomId : string) : void;
|
createConnexion(): Promise<any>;
|
||||||
sharePosition(roomId : string, x : number, y : number, direction : string) : void;
|
|
||||||
positionOfAllUser() : void;
|
joinARoom(roomId: string): void;
|
||||||
|
|
||||||
|
sharePosition(roomId: string, x: number, y: number, direction: string): void;
|
||||||
|
|
||||||
|
positionOfAllUser(): void;
|
||||||
|
|
||||||
|
/*webrtc*/
|
||||||
|
sendWebrtcRomm(roomId: string): void;
|
||||||
|
|
||||||
|
sendWebrtcSignal(signal: any, roomId: string): void;
|
||||||
|
|
||||||
|
receiveWebrtcSignal(callBack: Function): void;
|
||||||
|
|
||||||
|
receiveWebrtcStart(callBack: Function): void;
|
||||||
}
|
}
|
||||||
export class Connexion implements ConnexionInterface{
|
|
||||||
socket : any;
|
export class Connexion implements ConnexionInterface {
|
||||||
token : string;
|
socket: any;
|
||||||
email : string;
|
token: string;
|
||||||
|
email: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
startedRoom : string;
|
startedRoom: string;
|
||||||
|
|
||||||
GameManager: GameManagerInterface;
|
GameManager: GameManagerInterface;
|
||||||
|
|
||||||
constructor(email : string, GameManager: GameManagerInterface) {
|
constructor(email: string, GameManager: GameManagerInterface) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.GameManager = GameManager;
|
this.GameManager = GameManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
createConnexion() : Promise<ConnexionInterface>{
|
createConnexion(): Promise<ConnexionInterface> {
|
||||||
return Axios.post(`${API_URL}/login`, {email: this.email})
|
return Axios.post(`${API_URL}/login`, {email: this.email})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.token = res.data.token;
|
this.token = res.data.token;
|
||||||
@ -159,9 +185,9 @@ export class Connexion implements ConnexionInterface{
|
|||||||
* Permit to join a room
|
* Permit to join a room
|
||||||
* @param roomId
|
* @param roomId
|
||||||
*/
|
*/
|
||||||
joinARoom(roomId : string) : void {
|
joinARoom(roomId: string): void {
|
||||||
let messageUserPosition = new MessageUserPosition(this.userId, this.startedRoom, new Point(0, 0));
|
let messageUserPosition = new MessageUserPosition(this.userId, this.startedRoom, new Point(0, 0));
|
||||||
this.socket.emit('join-room', messageUserPosition.toString());
|
this.socket.emit(EventMessage.JOIN_ROOM, messageUserPosition.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,12 +197,12 @@ export class Connexion implements ConnexionInterface{
|
|||||||
* @param y
|
* @param y
|
||||||
* @param direction
|
* @param direction
|
||||||
*/
|
*/
|
||||||
sharePosition(roomId : string, x : number, y : number, direction : string = "none") : void{
|
sharePosition(roomId: string, x: number, y: number, direction: string = "none"): void {
|
||||||
if(!this.socket){
|
if (!this.socket) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let messageUserPosition = new MessageUserPosition(this.userId, roomId, new Point(x, y, direction));
|
let messageUserPosition = new MessageUserPosition(this.userId, roomId, new Point(x, y, direction));
|
||||||
this.socket.emit('user-position', messageUserPosition.toString());
|
this.socket.emit(EventMessage.USER_POSITION, messageUserPosition.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,8 +220,8 @@ export class Connexion implements ConnexionInterface{
|
|||||||
* ...
|
* ...
|
||||||
* ]
|
* ]
|
||||||
**/
|
**/
|
||||||
positionOfAllUser() : void {
|
positionOfAllUser(): void {
|
||||||
this.socket.on("user-position", (message: string) => {
|
this.socket.on(EventMessage.USER_POSITION, (message: string) => {
|
||||||
let dataList = JSON.parse(message);
|
let dataList = JSON.parse(message);
|
||||||
dataList.forEach((UserPositions: any) => {
|
dataList.forEach((UserPositions: any) => {
|
||||||
let listMessageUserPosition = new ListMessageUserPosition(UserPositions[0], UserPositions[1]);
|
let listMessageUserPosition = new ListMessageUserPosition(UserPositions[0], UserPositions[1]);
|
||||||
@ -204,9 +230,29 @@ export class Connexion implements ConnexionInterface{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMessage() : void {
|
sendWebrtcSignal(signal: any, roomId: string) {
|
||||||
this.socket.on('message-error', (message : string) => {
|
this.socket.emit(EventMessage.WEBRTC_SIGNAL, JSON.stringify({
|
||||||
console.error("message-error", message);
|
userId: this.userId,
|
||||||
|
roomId: roomId,
|
||||||
|
signal: signal
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
sendWebrtcRomm(roomId: string) {
|
||||||
|
this.socket.emit(EventMessage.WEBRTC_ROOM, JSON.stringify({roomId: roomId}));
|
||||||
|
}
|
||||||
|
|
||||||
|
receiveWebrtcStart(callback: Function) {
|
||||||
|
this.socket.on(EventMessage.WEBRTC_START, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
receiveWebrtcSignal(callback: Function) {
|
||||||
|
this.socket.on(EventMessage.WEBRTC_SIGNAL, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorMessage(): void {
|
||||||
|
this.socket.on(EventMessage.MESSAGE_ERROR, (message: string) => {
|
||||||
|
console.error(EventMessage.MESSAGE_ERROR, message);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import {GameSceneInterface, GameScene} from "./GameScene";
|
import {GameSceneInterface, GameScene} from "./GameScene";
|
||||||
import {ROOM} from "../../Enum/EnvironmentVariable"
|
import {ROOM} from "../../Enum/EnvironmentVariable"
|
||||||
import {Connexion, ConnexionInterface, ListMessageUserPositionInterface} from "../../Connexion";
|
import {Connexion, ConnexionInterface, ListMessageUserPositionInterface} from "../../Connexion";
|
||||||
import {WebRtcEventManager} from "../../WebRtc/WebRtcEventManager";
|
import {SimplePeer} from "../../WebRtc/SimplePeer";
|
||||||
|
|
||||||
export enum StatusGameManagerEnum {
|
export enum StatusGameManagerEnum {
|
||||||
IN_PROGRESS = 1,
|
IN_PROGRESS = 1,
|
||||||
@ -30,7 +30,7 @@ export class GameManager implements GameManagerInterface {
|
|||||||
this.configureGame();
|
this.configureGame();
|
||||||
/** TODO add loader in the page **/
|
/** TODO add loader in the page **/
|
||||||
//initialise cam
|
//initialise cam
|
||||||
new WebRtcEventManager(ConnexionInstance);
|
new SimplePeer(ConnexionInstance);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
throw err;
|
throw err;
|
||||||
|
@ -47,7 +47,7 @@ export class MediaManager {
|
|||||||
let webRtc = document.getElementById('webRtc');
|
let webRtc = document.getElementById('webRtc');
|
||||||
webRtc.classList.add('active');
|
webRtc.classList.add('active');
|
||||||
|
|
||||||
this.getCamera();
|
//this.getCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
enabledCamera() {
|
enabledCamera() {
|
||||||
@ -56,7 +56,7 @@ export class MediaManager {
|
|||||||
this.constraintsMedia.video = true;
|
this.constraintsMedia.video = true;
|
||||||
this.localStream = null;
|
this.localStream = null;
|
||||||
this.myCamVideo.srcObject = null;
|
this.myCamVideo.srcObject = null;
|
||||||
this.getCamera();
|
//this.getCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
disabledCamera() {
|
disabledCamera() {
|
||||||
@ -74,14 +74,14 @@ export class MediaManager {
|
|||||||
}
|
}
|
||||||
this.localStream = null;
|
this.localStream = null;
|
||||||
this.myCamVideo.srcObject = null;
|
this.myCamVideo.srcObject = null;
|
||||||
this.getCamera();
|
//this.getCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
enabledMicrophone() {
|
enabledMicrophone() {
|
||||||
this.microphoneClose.style.display = "none";
|
this.microphoneClose.style.display = "none";
|
||||||
this.microphone.style.display = "block";
|
this.microphone.style.display = "block";
|
||||||
this.constraintsMedia.audio = true;
|
this.constraintsMedia.audio = true;
|
||||||
this.getCamera();
|
//this.getCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
disabledMicrophone() {
|
disabledMicrophone() {
|
||||||
@ -95,17 +95,17 @@ export class MediaManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.getCamera();
|
//this.getCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
//get camera
|
//get camera
|
||||||
getCamera() {
|
getCamera() {
|
||||||
this.getCameraPromise = navigator.mediaDevices.getUserMedia(this.constraintsMedia)
|
return this.getCameraPromise = navigator.mediaDevices.getUserMedia(this.constraintsMedia)
|
||||||
.then((stream: MediaStream) => {
|
.then((stream: MediaStream) => {
|
||||||
console.log("constraintsMedia", stream);
|
|
||||||
this.localStream = stream;
|
this.localStream = stream;
|
||||||
this.myCamVideo.srcObject = this.localStream;
|
this.myCamVideo.srcObject = this.localStream;
|
||||||
this.myCamVideo.play();
|
this.myCamVideo.play();
|
||||||
|
return stream;
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
this.localStream = null;
|
this.localStream = null;
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
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> {
|
|
||||||
return this.MediaManager.getCameraPromise.then(() => {
|
|
||||||
this.peerConnection = new RTCPeerConnection();
|
|
||||||
|
|
||||||
//init all events peer connection
|
|
||||||
this.createEventPeerConnection();
|
|
||||||
|
|
||||||
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.addEventListener('icecandidate', ({candidate}) => {
|
|
||||||
let message = {message: candidate};
|
|
||||||
if (!candidate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.WebRtcEventManager.emitIceCandidate(message);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.peerConnection.addEventListener('iceconnectionstatechange', (e : Event) => {
|
|
||||||
console.info('oniceconnectionstatechange => iceConnectionState', this.peerConnection.iceConnectionState);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.peerConnection.addEventListener('negotiationneeded', (e : Event) => {
|
|
||||||
console.info("Event:negotiationneeded => call()", e);
|
|
||||||
this.createOffer()
|
|
||||||
});
|
|
||||||
|
|
||||||
this.peerConnection.addEventListener("track", (e:RTCTrackEvent) => {
|
|
||||||
console.info('Event:track', e);
|
|
||||||
if (this.MediaManager.remoteVideo.srcObject !== e.streams[0]) {
|
|
||||||
this.MediaManager.remoteVideo.srcObject = e.streams[0];
|
|
||||||
console.log('pc1 received remote stream');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.peerConnection.onicegatheringstatechange = () => {
|
|
||||||
console.info('onicegatheringstatechange => iceConnectionState', this.peerConnection.iceConnectionState);
|
|
||||||
};
|
|
||||||
this.peerConnection.onsignalingstatechange = () => {
|
|
||||||
console.info('onsignalingstatechange => iceConnectionState', this.peerConnection.iceConnectionState);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
106
front/src/WebRtc/SimplePeer.ts
Normal file
106
front/src/WebRtc/SimplePeer.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import {ConnexionInterface} from "../Connexion";
|
||||||
|
import {MediaManager} from "./MediaManager";
|
||||||
|
let Peer = require('simple-peer');
|
||||||
|
|
||||||
|
export class SimplePeer {
|
||||||
|
Connexion: ConnexionInterface;
|
||||||
|
MediaManager: MediaManager;
|
||||||
|
RoomId: string;
|
||||||
|
|
||||||
|
PeerConnexion: any;
|
||||||
|
|
||||||
|
constructor(Connexion: ConnexionInterface, roomId: string = "test-webrtc") {
|
||||||
|
this.Connexion = Connexion;
|
||||||
|
this.MediaManager = new MediaManager();
|
||||||
|
this.RoomId = roomId;
|
||||||
|
this.initialise();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* server has two person connected, start the meet
|
||||||
|
*/
|
||||||
|
initialise() {
|
||||||
|
return this.MediaManager.getCamera().then(() => {
|
||||||
|
//send message to join a room
|
||||||
|
this.Connexion.sendWebrtcRomm(this.RoomId);
|
||||||
|
|
||||||
|
//receive message start
|
||||||
|
this.Connexion.receiveWebrtcStart((message : string) => {
|
||||||
|
this.receiveWebrtcStart(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
//receive signal by gemer
|
||||||
|
this.Connexion.receiveWebrtcSignal((message : string) => {
|
||||||
|
this.receiveWebrtcSignal(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
receiveWebrtcStart(message: string) {
|
||||||
|
let data = JSON.parse(message);
|
||||||
|
|
||||||
|
//create pear connexion of user stared
|
||||||
|
this.createPeerConnexion(data.initiator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param userId
|
||||||
|
* @param initiator
|
||||||
|
*/
|
||||||
|
createPeerConnexion(initiator : boolean = false){
|
||||||
|
this.PeerConnexion = new Peer({initiator: initiator});
|
||||||
|
this.addMedia();
|
||||||
|
|
||||||
|
this.PeerConnexion.on('signal', (data: any) => {
|
||||||
|
this.sendWebrtcSignal(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.PeerConnexion.on('stream', (stream: MediaStream) => {
|
||||||
|
this.stream(stream)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* permit to send signal
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
sendWebrtcSignal(data: any) {
|
||||||
|
this.Connexion.sendWebrtcSignal(data, this.RoomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
receiveWebrtcSignal(message: string) {
|
||||||
|
let data = JSON.parse(message);
|
||||||
|
if(!this.PeerConnexion){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.PeerConnexion.signal(data.signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* permit stream video
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
|
stream(stream: MediaStream) {
|
||||||
|
this.MediaManager.remoteStream = stream;
|
||||||
|
this.MediaManager.remoteVideo.srcObject = this.MediaManager.remoteStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permit to update stream
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
|
addMedia () {
|
||||||
|
this.PeerConnexion.addStream(this.MediaManager.localStream) // <- add streams to peer dynamically
|
||||||
|
}
|
||||||
|
}
|
@ -1,92 +0,0 @@
|
|||||||
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();
|
|
||||||
|
|
||||||
//start to connect on event
|
|
||||||
//TODO test
|
|
||||||
this.emitWebRtcRoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)'}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
emitWebRtcRoom(){
|
|
||||||
//connect on the room to create a meet
|
|
||||||
this.Connexion.socket.emit('webrtc-room', JSON.stringify({roomId: this.RoomId}));
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -65,6 +65,13 @@
|
|||||||
version "13.11.0"
|
version "13.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
|
||||||
|
|
||||||
|
"@types/simple-peer@^9.6.0":
|
||||||
|
version "9.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/simple-peer/-/simple-peer-9.6.0.tgz#b5828d835b7f42dde27db584ba127e7a9f9072f4"
|
||||||
|
integrity sha512-X2y6s+vE/3j03hkI90oqld2JH2J/m1L7yFCYYPyFV/whrOK1h4neYvJL3GIE+UcACJacXZqzdmDKudwec18RbA==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/socket.io-client@^1.4.32":
|
"@types/socket.io-client@^1.4.32":
|
||||||
version "1.4.32"
|
version "1.4.32"
|
||||||
resolved "https://registry.yarnpkg.com/@types/socket.io-client/-/socket.io-client-1.4.32.tgz#988a65a0386c274b1c22a55377fab6a30789ac14"
|
resolved "https://registry.yarnpkg.com/@types/socket.io-client/-/socket.io-client-1.4.32.tgz#988a65a0386c274b1c22a55377fab6a30789ac14"
|
||||||
@ -1718,6 +1725,11 @@ functional-red-black-tree@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
||||||
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
|
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
|
||||||
|
|
||||||
|
get-browser-rtc@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-browser-rtc/-/get-browser-rtc-1.0.2.tgz#bbcd40c8451a7ed4ef5c373b8169a409dd1d11d9"
|
||||||
|
integrity sha1-u81AyEUaftTvXDc7gWmkCd0dEdk=
|
||||||
|
|
||||||
get-caller-file@^1.0.1:
|
get-caller-file@^1.0.1:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
|
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
|
||||||
@ -3097,7 +3109,12 @@ querystringify@^2.1.1:
|
|||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
|
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
|
||||||
|
|
||||||
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
|
queue-microtask@^1.1.0:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.1.2.tgz#139bf8186db0c545017ec66c2664ac646d5c571e"
|
||||||
|
integrity sha512-F9wwNePtXrzZenAB3ax0Y8TSKGvuB7Qw16J30hspEUTbfUM+H827XyN3rlpwhVmtm5wuZtbKIHjOnwDn7MUxWQ==
|
||||||
|
|
||||||
|
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.3, randombytes@^2.0.5:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3135,7 +3152,7 @@ raw-body@2.4.0:
|
|||||||
string_decoder "~1.1.1"
|
string_decoder "~1.1.1"
|
||||||
util-deprecate "~1.0.1"
|
util-deprecate "~1.0.1"
|
||||||
|
|
||||||
readable-stream@^3.0.6:
|
readable-stream@^3.0.6, readable-stream@^3.4.0:
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3418,6 +3435,17 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
|||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
||||||
|
|
||||||
|
simple-peer@^9.6.2:
|
||||||
|
version "9.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/simple-peer/-/simple-peer-9.6.2.tgz#42418e77cf8f9184e4fa22ef1017b195c2bf84d7"
|
||||||
|
integrity sha512-EOKoImCaqtNvXIntxT1CBBK/3pVi7tMAoJ3shdyd9qk3zLm3QPiRLb/sPC1G2xvKJkJc5fkQjCXqRZ0AknwTig==
|
||||||
|
dependencies:
|
||||||
|
debug "^4.0.1"
|
||||||
|
get-browser-rtc "^1.0.0"
|
||||||
|
queue-microtask "^1.1.0"
|
||||||
|
randombytes "^2.0.3"
|
||||||
|
readable-stream "^3.4.0"
|
||||||
|
|
||||||
slice-ansi@^2.1.0:
|
slice-ansi@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
|
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
|
||||||
|
Loading…
Reference in New Issue
Block a user