@voicemaster/core 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +61 -63
- package/dist/index.mjs +61 -53
- package/package.json +1 -1
- package/src/VoiceClient.ts +65 -58
package/dist/index.d.mts
CHANGED
|
@@ -7,7 +7,7 @@ interface VoiceClientConfig {
|
|
|
7
7
|
}
|
|
8
8
|
declare class VoiceClient {
|
|
9
9
|
private ws;
|
|
10
|
-
private
|
|
10
|
+
private pc;
|
|
11
11
|
private localStream;
|
|
12
12
|
private remoteStream;
|
|
13
13
|
private eventHandlers;
|
|
@@ -21,10 +21,13 @@ declare class VoiceClient {
|
|
|
21
21
|
private emit;
|
|
22
22
|
connect(): Promise<void>;
|
|
23
23
|
private initMicrophone;
|
|
24
|
+
private initPeerConnection;
|
|
24
25
|
private initWebSocket;
|
|
25
26
|
private handleSignalingMessage;
|
|
26
|
-
private
|
|
27
|
-
private
|
|
27
|
+
private createOffer;
|
|
28
|
+
private handleOffer;
|
|
29
|
+
private handleAnswer;
|
|
30
|
+
private handleCandidate;
|
|
28
31
|
private send;
|
|
29
32
|
disconnect(): void;
|
|
30
33
|
toggleMute(): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ interface VoiceClientConfig {
|
|
|
7
7
|
}
|
|
8
8
|
declare class VoiceClient {
|
|
9
9
|
private ws;
|
|
10
|
-
private
|
|
10
|
+
private pc;
|
|
11
11
|
private localStream;
|
|
12
12
|
private remoteStream;
|
|
13
13
|
private eventHandlers;
|
|
@@ -21,10 +21,13 @@ declare class VoiceClient {
|
|
|
21
21
|
private emit;
|
|
22
22
|
connect(): Promise<void>;
|
|
23
23
|
private initMicrophone;
|
|
24
|
+
private initPeerConnection;
|
|
24
25
|
private initWebSocket;
|
|
25
26
|
private handleSignalingMessage;
|
|
26
|
-
private
|
|
27
|
-
private
|
|
27
|
+
private createOffer;
|
|
28
|
+
private handleOffer;
|
|
29
|
+
private handleAnswer;
|
|
30
|
+
private handleCandidate;
|
|
28
31
|
private send;
|
|
29
32
|
disconnect(): void;
|
|
30
33
|
toggleMute(): void;
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/index.ts
|
|
@@ -35,11 +25,10 @@ __export(index_exports, {
|
|
|
35
25
|
module.exports = __toCommonJS(index_exports);
|
|
36
26
|
|
|
37
27
|
// src/VoiceClient.ts
|
|
38
|
-
var import_simple_peer = __toESM(require("simple-peer"));
|
|
39
28
|
var VoiceClient = class {
|
|
40
29
|
constructor(config) {
|
|
41
30
|
this.ws = null;
|
|
42
|
-
this.
|
|
31
|
+
this.pc = null;
|
|
43
32
|
this.localStream = null;
|
|
44
33
|
this.remoteStream = null;
|
|
45
34
|
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
@@ -48,8 +37,7 @@ var VoiceClient = class {
|
|
|
48
37
|
this.roomId = config.roomId;
|
|
49
38
|
this.userId = config.userId;
|
|
50
39
|
this.iceServers = config.iceServers || [
|
|
51
|
-
{ urls: "stun:stun.l.google.com:19302" }
|
|
52
|
-
{ urls: "stun:stun1.l.google.com:19302" }
|
|
40
|
+
{ urls: "stun:stun.l.google.com:19302" }
|
|
53
41
|
];
|
|
54
42
|
if (config.autoConnect !== false) {
|
|
55
43
|
this.connect();
|
|
@@ -70,6 +58,7 @@ var VoiceClient = class {
|
|
|
70
58
|
async connect() {
|
|
71
59
|
try {
|
|
72
60
|
await this.initMicrophone();
|
|
61
|
+
this.initPeerConnection();
|
|
73
62
|
this.initWebSocket();
|
|
74
63
|
} catch (error) {
|
|
75
64
|
this.emit("error", error);
|
|
@@ -85,78 +74,89 @@ var VoiceClient = class {
|
|
|
85
74
|
});
|
|
86
75
|
this.emit("localStream", this.localStream);
|
|
87
76
|
}
|
|
77
|
+
initPeerConnection() {
|
|
78
|
+
this.pc = new RTCPeerConnection({ iceServers: this.iceServers });
|
|
79
|
+
this.localStream?.getTracks().forEach((track) => {
|
|
80
|
+
this.pc.addTrack(track, this.localStream);
|
|
81
|
+
});
|
|
82
|
+
this.pc.ontrack = (event) => {
|
|
83
|
+
this.remoteStream = event.streams[0];
|
|
84
|
+
this.emit("remoteStream", this.remoteStream);
|
|
85
|
+
if (!this.isConnectedFlag) {
|
|
86
|
+
this.isConnectedFlag = true;
|
|
87
|
+
this.emit("connected");
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
this.pc.onicecandidate = (event) => {
|
|
91
|
+
if (event.candidate) {
|
|
92
|
+
this.send({
|
|
93
|
+
type: "candidate",
|
|
94
|
+
candidate: event.candidate
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
88
99
|
initWebSocket() {
|
|
89
100
|
const url = `${this.signalingUrl}?userId=${this.userId}&roomId=${this.roomId}`;
|
|
90
101
|
this.ws = new WebSocket(url);
|
|
91
102
|
this.ws.onopen = () => {
|
|
92
103
|
this.send({ type: "join", roomId: this.roomId, userId: this.userId });
|
|
93
104
|
};
|
|
94
|
-
this.ws.onmessage = (event) => {
|
|
105
|
+
this.ws.onmessage = async (event) => {
|
|
95
106
|
const message = JSON.parse(event.data);
|
|
96
|
-
this.handleSignalingMessage(message);
|
|
107
|
+
await this.handleSignalingMessage(message);
|
|
97
108
|
};
|
|
98
109
|
this.ws.onclose = () => {
|
|
99
110
|
this.emit("disconnected");
|
|
100
111
|
};
|
|
101
112
|
}
|
|
102
|
-
handleSignalingMessage(message) {
|
|
113
|
+
async handleSignalingMessage(message) {
|
|
103
114
|
switch (message.type) {
|
|
104
115
|
case "user-joined":
|
|
105
116
|
if (message.userId !== this.userId) {
|
|
106
|
-
this.
|
|
117
|
+
await this.createOffer();
|
|
107
118
|
this.emit("userJoined", message.userId);
|
|
108
119
|
}
|
|
109
120
|
break;
|
|
110
|
-
case "
|
|
111
|
-
this.
|
|
121
|
+
case "offer":
|
|
122
|
+
await this.handleOffer(message);
|
|
123
|
+
break;
|
|
124
|
+
case "answer":
|
|
125
|
+
await this.handleAnswer(message);
|
|
126
|
+
break;
|
|
127
|
+
case "candidate":
|
|
128
|
+
await this.handleCandidate(message);
|
|
112
129
|
break;
|
|
113
130
|
case "user-left":
|
|
114
131
|
this.emit("userLeft", message.userId);
|
|
115
132
|
break;
|
|
116
133
|
}
|
|
117
134
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
initiator,
|
|
125
|
-
trickle: true,
|
|
126
|
-
stream: this.localStream || void 0,
|
|
127
|
-
config
|
|
128
|
-
});
|
|
129
|
-
this.peer.on("signal", (data) => {
|
|
130
|
-
this.send({
|
|
131
|
-
type: "signal",
|
|
132
|
-
userId: this.userId,
|
|
133
|
-
roomId: this.roomId,
|
|
134
|
-
payload: data
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
this.peer.on("stream", (stream) => {
|
|
138
|
-
this.remoteStream = stream;
|
|
139
|
-
this.emit("remoteStream", stream);
|
|
140
|
-
if (!this.isConnectedFlag) {
|
|
141
|
-
this.isConnectedFlag = true;
|
|
142
|
-
this.emit("connected");
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
this.peer.on("connect", () => {
|
|
146
|
-
if (!this.isConnectedFlag) {
|
|
147
|
-
this.isConnectedFlag = true;
|
|
148
|
-
this.emit("connected");
|
|
149
|
-
}
|
|
135
|
+
async createOffer() {
|
|
136
|
+
const offer = await this.pc.createOffer();
|
|
137
|
+
await this.pc.setLocalDescription(offer);
|
|
138
|
+
this.send({
|
|
139
|
+
type: "offer",
|
|
140
|
+
sdp: this.pc.localDescription
|
|
150
141
|
});
|
|
151
|
-
|
|
152
|
-
|
|
142
|
+
}
|
|
143
|
+
async handleOffer(message) {
|
|
144
|
+
const offer = new RTCSessionDescription(message.sdp);
|
|
145
|
+
await this.pc.setRemoteDescription(offer);
|
|
146
|
+
const answer = await this.pc.createAnswer();
|
|
147
|
+
await this.pc.setLocalDescription(answer);
|
|
148
|
+
this.send({
|
|
149
|
+
type: "answer",
|
|
150
|
+
sdp: this.pc.localDescription
|
|
153
151
|
});
|
|
154
152
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
153
|
+
async handleAnswer(message) {
|
|
154
|
+
const answer = new RTCSessionDescription(message.sdp);
|
|
155
|
+
await this.pc.setRemoteDescription(answer);
|
|
156
|
+
}
|
|
157
|
+
async handleCandidate(message) {
|
|
158
|
+
const candidate = new RTCIceCandidate(message.candidate);
|
|
159
|
+
await this.pc.addIceCandidate(candidate);
|
|
160
160
|
}
|
|
161
161
|
send(data) {
|
|
162
162
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
@@ -168,10 +168,8 @@ var VoiceClient = class {
|
|
|
168
168
|
this.send({ type: "leave", roomId: this.roomId, userId: this.userId });
|
|
169
169
|
this.ws.close();
|
|
170
170
|
}
|
|
171
|
-
this.
|
|
172
|
-
|
|
173
|
-
this.localStream.getTracks().forEach((track) => track.stop());
|
|
174
|
-
}
|
|
171
|
+
this.pc?.close();
|
|
172
|
+
this.localStream?.getTracks().forEach((track) => track.stop());
|
|
175
173
|
this.isConnectedFlag = false;
|
|
176
174
|
this.emit("disconnected");
|
|
177
175
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// src/VoiceClient.ts
|
|
2
|
-
import Peer from "simple-peer";
|
|
3
2
|
var VoiceClient = class {
|
|
4
3
|
constructor(config) {
|
|
5
4
|
this.ws = null;
|
|
6
|
-
this.
|
|
5
|
+
this.pc = null;
|
|
7
6
|
this.localStream = null;
|
|
8
7
|
this.remoteStream = null;
|
|
9
8
|
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
@@ -12,8 +11,7 @@ var VoiceClient = class {
|
|
|
12
11
|
this.roomId = config.roomId;
|
|
13
12
|
this.userId = config.userId;
|
|
14
13
|
this.iceServers = config.iceServers || [
|
|
15
|
-
{ urls: "stun:stun.l.google.com:19302" }
|
|
16
|
-
{ urls: "stun:stun1.l.google.com:19302" }
|
|
14
|
+
{ urls: "stun:stun.l.google.com:19302" }
|
|
17
15
|
];
|
|
18
16
|
if (config.autoConnect !== false) {
|
|
19
17
|
this.connect();
|
|
@@ -34,6 +32,7 @@ var VoiceClient = class {
|
|
|
34
32
|
async connect() {
|
|
35
33
|
try {
|
|
36
34
|
await this.initMicrophone();
|
|
35
|
+
this.initPeerConnection();
|
|
37
36
|
this.initWebSocket();
|
|
38
37
|
} catch (error) {
|
|
39
38
|
this.emit("error", error);
|
|
@@ -49,78 +48,89 @@ var VoiceClient = class {
|
|
|
49
48
|
});
|
|
50
49
|
this.emit("localStream", this.localStream);
|
|
51
50
|
}
|
|
51
|
+
initPeerConnection() {
|
|
52
|
+
this.pc = new RTCPeerConnection({ iceServers: this.iceServers });
|
|
53
|
+
this.localStream?.getTracks().forEach((track) => {
|
|
54
|
+
this.pc.addTrack(track, this.localStream);
|
|
55
|
+
});
|
|
56
|
+
this.pc.ontrack = (event) => {
|
|
57
|
+
this.remoteStream = event.streams[0];
|
|
58
|
+
this.emit("remoteStream", this.remoteStream);
|
|
59
|
+
if (!this.isConnectedFlag) {
|
|
60
|
+
this.isConnectedFlag = true;
|
|
61
|
+
this.emit("connected");
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
this.pc.onicecandidate = (event) => {
|
|
65
|
+
if (event.candidate) {
|
|
66
|
+
this.send({
|
|
67
|
+
type: "candidate",
|
|
68
|
+
candidate: event.candidate
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
52
73
|
initWebSocket() {
|
|
53
74
|
const url = `${this.signalingUrl}?userId=${this.userId}&roomId=${this.roomId}`;
|
|
54
75
|
this.ws = new WebSocket(url);
|
|
55
76
|
this.ws.onopen = () => {
|
|
56
77
|
this.send({ type: "join", roomId: this.roomId, userId: this.userId });
|
|
57
78
|
};
|
|
58
|
-
this.ws.onmessage = (event) => {
|
|
79
|
+
this.ws.onmessage = async (event) => {
|
|
59
80
|
const message = JSON.parse(event.data);
|
|
60
|
-
this.handleSignalingMessage(message);
|
|
81
|
+
await this.handleSignalingMessage(message);
|
|
61
82
|
};
|
|
62
83
|
this.ws.onclose = () => {
|
|
63
84
|
this.emit("disconnected");
|
|
64
85
|
};
|
|
65
86
|
}
|
|
66
|
-
handleSignalingMessage(message) {
|
|
87
|
+
async handleSignalingMessage(message) {
|
|
67
88
|
switch (message.type) {
|
|
68
89
|
case "user-joined":
|
|
69
90
|
if (message.userId !== this.userId) {
|
|
70
|
-
this.
|
|
91
|
+
await this.createOffer();
|
|
71
92
|
this.emit("userJoined", message.userId);
|
|
72
93
|
}
|
|
73
94
|
break;
|
|
74
|
-
case "
|
|
75
|
-
this.
|
|
95
|
+
case "offer":
|
|
96
|
+
await this.handleOffer(message);
|
|
97
|
+
break;
|
|
98
|
+
case "answer":
|
|
99
|
+
await this.handleAnswer(message);
|
|
100
|
+
break;
|
|
101
|
+
case "candidate":
|
|
102
|
+
await this.handleCandidate(message);
|
|
76
103
|
break;
|
|
77
104
|
case "user-left":
|
|
78
105
|
this.emit("userLeft", message.userId);
|
|
79
106
|
break;
|
|
80
107
|
}
|
|
81
108
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
initiator,
|
|
89
|
-
trickle: true,
|
|
90
|
-
stream: this.localStream || void 0,
|
|
91
|
-
config
|
|
92
|
-
});
|
|
93
|
-
this.peer.on("signal", (data) => {
|
|
94
|
-
this.send({
|
|
95
|
-
type: "signal",
|
|
96
|
-
userId: this.userId,
|
|
97
|
-
roomId: this.roomId,
|
|
98
|
-
payload: data
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
this.peer.on("stream", (stream) => {
|
|
102
|
-
this.remoteStream = stream;
|
|
103
|
-
this.emit("remoteStream", stream);
|
|
104
|
-
if (!this.isConnectedFlag) {
|
|
105
|
-
this.isConnectedFlag = true;
|
|
106
|
-
this.emit("connected");
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
this.peer.on("connect", () => {
|
|
110
|
-
if (!this.isConnectedFlag) {
|
|
111
|
-
this.isConnectedFlag = true;
|
|
112
|
-
this.emit("connected");
|
|
113
|
-
}
|
|
109
|
+
async createOffer() {
|
|
110
|
+
const offer = await this.pc.createOffer();
|
|
111
|
+
await this.pc.setLocalDescription(offer);
|
|
112
|
+
this.send({
|
|
113
|
+
type: "offer",
|
|
114
|
+
sdp: this.pc.localDescription
|
|
114
115
|
});
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
}
|
|
117
|
+
async handleOffer(message) {
|
|
118
|
+
const offer = new RTCSessionDescription(message.sdp);
|
|
119
|
+
await this.pc.setRemoteDescription(offer);
|
|
120
|
+
const answer = await this.pc.createAnswer();
|
|
121
|
+
await this.pc.setLocalDescription(answer);
|
|
122
|
+
this.send({
|
|
123
|
+
type: "answer",
|
|
124
|
+
sdp: this.pc.localDescription
|
|
117
125
|
});
|
|
118
126
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
127
|
+
async handleAnswer(message) {
|
|
128
|
+
const answer = new RTCSessionDescription(message.sdp);
|
|
129
|
+
await this.pc.setRemoteDescription(answer);
|
|
130
|
+
}
|
|
131
|
+
async handleCandidate(message) {
|
|
132
|
+
const candidate = new RTCIceCandidate(message.candidate);
|
|
133
|
+
await this.pc.addIceCandidate(candidate);
|
|
124
134
|
}
|
|
125
135
|
send(data) {
|
|
126
136
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
@@ -132,10 +142,8 @@ var VoiceClient = class {
|
|
|
132
142
|
this.send({ type: "leave", roomId: this.roomId, userId: this.userId });
|
|
133
143
|
this.ws.close();
|
|
134
144
|
}
|
|
135
|
-
this.
|
|
136
|
-
|
|
137
|
-
this.localStream.getTracks().forEach((track) => track.stop());
|
|
138
|
-
}
|
|
145
|
+
this.pc?.close();
|
|
146
|
+
this.localStream?.getTracks().forEach((track) => track.stop());
|
|
139
147
|
this.isConnectedFlag = false;
|
|
140
148
|
this.emit("disconnected");
|
|
141
149
|
}
|
package/package.json
CHANGED
package/src/VoiceClient.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import Peer from 'simple-peer';
|
|
2
|
-
|
|
3
1
|
export interface VoiceClientConfig {
|
|
4
2
|
signalingUrl: string;
|
|
5
3
|
roomId: string;
|
|
@@ -10,7 +8,7 @@ export interface VoiceClientConfig {
|
|
|
10
8
|
|
|
11
9
|
export class VoiceClient {
|
|
12
10
|
private ws: WebSocket | null = null;
|
|
13
|
-
private
|
|
11
|
+
private pc: RTCPeerConnection | null = null;
|
|
14
12
|
private localStream: MediaStream | null = null;
|
|
15
13
|
private remoteStream: MediaStream | null = null;
|
|
16
14
|
private eventHandlers: Map<string, Function[]> = new Map();
|
|
@@ -25,8 +23,7 @@ export class VoiceClient {
|
|
|
25
23
|
this.roomId = config.roomId;
|
|
26
24
|
this.userId = config.userId;
|
|
27
25
|
this.iceServers = config.iceServers || [
|
|
28
|
-
{ urls: 'stun:stun.l.google.com:19302' }
|
|
29
|
-
{ urls: 'stun:stun1.l.google.com:19302' }
|
|
26
|
+
{ urls: 'stun:stun.l.google.com:19302' }
|
|
30
27
|
];
|
|
31
28
|
|
|
32
29
|
if (config.autoConnect !== false) {
|
|
@@ -51,6 +48,7 @@ export class VoiceClient {
|
|
|
51
48
|
async connect(): Promise<void> {
|
|
52
49
|
try {
|
|
53
50
|
await this.initMicrophone();
|
|
51
|
+
this.initPeerConnection();
|
|
54
52
|
this.initWebSocket();
|
|
55
53
|
} catch (error) {
|
|
56
54
|
this.emit('error', error);
|
|
@@ -68,6 +66,32 @@ export class VoiceClient {
|
|
|
68
66
|
this.emit('localStream', this.localStream);
|
|
69
67
|
}
|
|
70
68
|
|
|
69
|
+
private initPeerConnection(): void {
|
|
70
|
+
this.pc = new RTCPeerConnection({ iceServers: this.iceServers });
|
|
71
|
+
|
|
72
|
+
this.localStream?.getTracks().forEach(track => {
|
|
73
|
+
this.pc!.addTrack(track, this.localStream!);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
this.pc.ontrack = (event) => {
|
|
77
|
+
this.remoteStream = event.streams[0];
|
|
78
|
+
this.emit('remoteStream', this.remoteStream);
|
|
79
|
+
if (!this.isConnectedFlag) {
|
|
80
|
+
this.isConnectedFlag = true;
|
|
81
|
+
this.emit('connected');
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
this.pc.onicecandidate = (event) => {
|
|
86
|
+
if (event.candidate) {
|
|
87
|
+
this.send({
|
|
88
|
+
type: 'candidate',
|
|
89
|
+
candidate: event.candidate
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
71
95
|
private initWebSocket(): void {
|
|
72
96
|
const url = `${this.signalingUrl}?userId=${this.userId}&roomId=${this.roomId}`;
|
|
73
97
|
this.ws = new WebSocket(url);
|
|
@@ -76,9 +100,9 @@ export class VoiceClient {
|
|
|
76
100
|
this.send({ type: 'join', roomId: this.roomId, userId: this.userId });
|
|
77
101
|
};
|
|
78
102
|
|
|
79
|
-
this.ws.onmessage = (event) => {
|
|
103
|
+
this.ws.onmessage = async (event) => {
|
|
80
104
|
const message = JSON.parse(event.data);
|
|
81
|
-
this.handleSignalingMessage(message);
|
|
105
|
+
await this.handleSignalingMessage(message);
|
|
82
106
|
};
|
|
83
107
|
|
|
84
108
|
this.ws.onclose = () => {
|
|
@@ -86,16 +110,22 @@ export class VoiceClient {
|
|
|
86
110
|
};
|
|
87
111
|
}
|
|
88
112
|
|
|
89
|
-
private handleSignalingMessage(message: any): void {
|
|
113
|
+
private async handleSignalingMessage(message: any): Promise<void> {
|
|
90
114
|
switch (message.type) {
|
|
91
115
|
case 'user-joined':
|
|
92
116
|
if (message.userId !== this.userId) {
|
|
93
|
-
this.
|
|
117
|
+
await this.createOffer();
|
|
94
118
|
this.emit('userJoined', message.userId);
|
|
95
119
|
}
|
|
96
120
|
break;
|
|
97
|
-
case '
|
|
98
|
-
this.
|
|
121
|
+
case 'offer':
|
|
122
|
+
await this.handleOffer(message);
|
|
123
|
+
break;
|
|
124
|
+
case 'answer':
|
|
125
|
+
await this.handleAnswer(message);
|
|
126
|
+
break;
|
|
127
|
+
case 'candidate':
|
|
128
|
+
await this.handleCandidate(message);
|
|
99
129
|
break;
|
|
100
130
|
case 'user-left':
|
|
101
131
|
this.emit('userLeft', message.userId);
|
|
@@ -103,55 +133,34 @@ export class VoiceClient {
|
|
|
103
133
|
}
|
|
104
134
|
}
|
|
105
135
|
|
|
106
|
-
private
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
this.peer = new Peer({
|
|
114
|
-
initiator,
|
|
115
|
-
trickle: true,
|
|
116
|
-
stream: this.localStream || undefined,
|
|
117
|
-
config: config
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
this.peer.on('signal', (data) => {
|
|
121
|
-
this.send({
|
|
122
|
-
type: 'signal',
|
|
123
|
-
userId: this.userId,
|
|
124
|
-
roomId: this.roomId,
|
|
125
|
-
payload: data
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
this.peer.on('stream', (stream) => {
|
|
130
|
-
this.remoteStream = stream;
|
|
131
|
-
this.emit('remoteStream', stream);
|
|
132
|
-
if (!this.isConnectedFlag) {
|
|
133
|
-
this.isConnectedFlag = true;
|
|
134
|
-
this.emit('connected');
|
|
135
|
-
}
|
|
136
|
+
private async createOffer(): Promise<void> {
|
|
137
|
+
const offer = await this.pc!.createOffer();
|
|
138
|
+
await this.pc!.setLocalDescription(offer);
|
|
139
|
+
this.send({
|
|
140
|
+
type: 'offer',
|
|
141
|
+
sdp: this.pc!.localDescription
|
|
136
142
|
});
|
|
143
|
+
}
|
|
137
144
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
private async handleOffer(message: any): Promise<void> {
|
|
146
|
+
const offer = new RTCSessionDescription(message.sdp);
|
|
147
|
+
await this.pc!.setRemoteDescription(offer);
|
|
148
|
+
const answer = await this.pc!.createAnswer();
|
|
149
|
+
await this.pc!.setLocalDescription(answer);
|
|
150
|
+
this.send({
|
|
151
|
+
type: 'answer',
|
|
152
|
+
sdp: this.pc!.localDescription
|
|
143
153
|
});
|
|
154
|
+
}
|
|
144
155
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
156
|
+
private async handleAnswer(message: any): Promise<void> {
|
|
157
|
+
const answer = new RTCSessionDescription(message.sdp);
|
|
158
|
+
await this.pc!.setRemoteDescription(answer);
|
|
148
159
|
}
|
|
149
160
|
|
|
150
|
-
private
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
this.peer?.signal(signal);
|
|
161
|
+
private async handleCandidate(message: any): Promise<void> {
|
|
162
|
+
const candidate = new RTCIceCandidate(message.candidate);
|
|
163
|
+
await this.pc!.addIceCandidate(candidate);
|
|
155
164
|
}
|
|
156
165
|
|
|
157
166
|
private send(data: any): void {
|
|
@@ -165,10 +174,8 @@ export class VoiceClient {
|
|
|
165
174
|
this.send({ type: 'leave', roomId: this.roomId, userId: this.userId });
|
|
166
175
|
this.ws.close();
|
|
167
176
|
}
|
|
168
|
-
this.
|
|
169
|
-
|
|
170
|
-
this.localStream.getTracks().forEach(track => track.stop());
|
|
171
|
-
}
|
|
177
|
+
this.pc?.close();
|
|
178
|
+
this.localStream?.getTracks().forEach(track => track.stop());
|
|
172
179
|
this.isConnectedFlag = false;
|
|
173
180
|
this.emit('disconnected');
|
|
174
181
|
}
|