Compare commits

...

228 Commits

Author SHA1 Message Date
c823f7578c LH-265: Update client 2022-11-29 13:27:33 +02:00
6cc14cdf30 LH-265: Update documentation and README.md 2022-11-29 13:27:12 +02:00
4bb23def42 Update server 2022-11-29 11:32:03 +02:00
fc745a5879 Update server 2022-11-29 11:09:10 +02:00
742d67f2e3 Update server 2022-11-29 11:08:12 +02:00
e22093d97e Update server 2022-11-29 10:27:55 +02:00
7634a18465 Update server 2022-11-29 10:22:02 +02:00
d17b035526 Update server 2022-11-29 04:03:06 +02:00
a21451e46d Update server 2022-11-29 03:59:42 +02:00
df0cb81a8e Update server 2022-11-29 03:55:34 +02:00
ac8c651a9d Update server 2022-11-29 03:52:15 +02:00
9111c4e245 Update server 2022-11-29 03:50:45 +02:00
7a2d02dcda Update server 2022-11-29 03:44:02 +02:00
39efdd12b7 Update server 2022-11-29 03:41:00 +02:00
0bdc6fac3a Update server 2022-11-29 03:17:28 +02:00
ae7a8ed9ce Update server 2022-11-29 03:16:15 +02:00
9feaebf8a7 Update server 2022-11-29 02:46:12 +02:00
85110b7f5c Update server 2022-11-29 02:44:40 +02:00
d047cdf7d1 Update server 2022-11-29 02:44:01 +02:00
753b476462 Update server 2022-11-29 02:42:13 +02:00
359c7c784e Update server 2022-11-29 02:40:25 +02:00
5169d0d49f Update server 2022-11-29 02:39:11 +02:00
a3b083fe24 Update server 2022-11-29 02:37:55 +02:00
46d3499e3d Update server 2022-11-29 02:34:48 +02:00
38b95d5246 Update server 2022-11-29 02:21:29 +02:00
984b2b892e Update server 2022-11-29 02:20:05 +02:00
e085d22e89 Update server 2022-11-29 02:16:44 +02:00
3bc15fdef1 Update server 2022-11-29 02:09:37 +02:00
67042185c4 Update server 2022-11-29 01:59:53 +02:00
c92dff9bfe Update server 2022-11-28 23:40:56 +02:00
3605ca0468 Update server 2022-11-28 23:40:08 +02:00
1edbcb2179 Merge branch 'LH-265-enable-audio-in-mediasoup' of https://git.safemobile.org/Safemobile/mediasoup into LH-265-enable-audio-in-mediasoup 2022-11-25 10:00:28 +02:00
adbcf6c2bc Update server 2022-11-25 10:00:17 +02:00
c862224ead LH-265: Update client and server 2022-11-25 09:58:53 +02:00
c02a7c7380 Update server 2022-11-24 23:56:42 +02:00
3387a362a6 Update server 2022-11-24 23:30:27 +02:00
21dffefa8c Update server 2022-11-24 23:29:03 +02:00
1369491529 Update server 2022-11-24 23:22:55 +02:00
56bdbca537 Update server 2022-11-24 23:09:18 +02:00
8444809910 Update server 2022-11-24 23:06:02 +02:00
cd84c534ce Update server 2022-11-24 22:27:33 +02:00
038bdb99bc Update server 2022-11-24 22:18:37 +02:00
d94ea12a40 Update server 2022-11-24 17:08:54 +02:00
1148532a9b Update server 2022-11-24 17:01:26 +02:00
3561bb13a6 Update server 2022-11-24 16:59:04 +02:00
22ead926b0 Update server 2022-11-24 16:57:26 +02:00
c6edb2947d Update server 2022-11-24 16:46:00 +02:00
e59f134a68 Update server 2022-11-24 16:37:44 +02:00
aad96b72f2 Update server 2022-11-24 16:36:36 +02:00
3e4c0a32bc Update server 2022-11-24 16:36:00 +02:00
2a7bd42247 Update server 2022-11-24 16:34:54 +02:00
f2c0794bf4 Update server 2022-11-24 16:22:56 +02:00
950298c4f6 Update server 2022-11-24 16:21:22 +02:00
6e74083733 Update server 2022-11-24 13:49:04 +02:00
8ef6c2abb0 Update server 2022-11-24 13:43:33 +02:00
2a86042c80 Update server 2022-11-24 13:41:24 +02:00
56b8e2ea74 Update server 2022-11-24 13:38:28 +02:00
6c42814229 Update server 2022-11-24 13:37:42 +02:00
e65b7e0d7c Update server 2022-11-24 13:36:21 +02:00
aa7c2aea90 Update server 2022-11-24 13:35:32 +02:00
458342c0d2 Update server 2022-11-24 13:32:45 +02:00
fa5a1a5ae7 Update server 2022-11-23 17:56:18 +02:00
9fbe01ae1d Update server 2022-11-23 17:19:55 +02:00
e5bcc6262b Update server 2022-11-23 17:11:09 +02:00
c758a9106c Update server 2022-11-23 16:27:13 +02:00
fcbc28c801 Update server 2022-11-23 16:26:28 +02:00
ba63fb20bf Update server 2022-11-23 16:24:12 +02:00
e8bd6837cf Update server 2022-11-23 16:21:48 +02:00
d386915ff2 Update server 2022-11-23 16:16:17 +02:00
2479f58e21 Update server 2022-11-23 16:09:26 +02:00
d49b8e42ff Update server 2022-11-23 16:03:13 +02:00
a3ae874f8e Update server 2022-11-23 16:01:51 +02:00
c2dbef1918 Update server 2022-11-23 16:00:54 +02:00
b41b8f2d64 Update server 2022-11-23 15:57:27 +02:00
c089e91fba Update server 2022-11-23 13:20:49 +02:00
c63aee83a1 Update server 2022-11-23 13:19:56 +02:00
a97ec24148 Update server 2022-11-23 00:54:03 +02:00
3c23c6791d Update server 2022-11-23 00:34:12 +02:00
1a7b44807d Update server 2022-11-23 00:32:24 +02:00
daa2c556e4 Update server 2022-11-23 00:25:16 +02:00
22656722e8 Update server 2022-11-23 00:22:00 +02:00
f5b9067b7e Update server 2022-11-23 00:21:26 +02:00
0b3a45ae45 Update server 2022-11-23 00:13:56 +02:00
dfe4630839 Update server 2022-11-23 00:11:26 +02:00
d18041cadd Update server 2022-11-23 00:11:16 +02:00
fa42caeeb2 Update server 2022-11-22 23:14:01 +02:00
4dbb7ad554 Update server 2022-11-22 23:12:55 +02:00
d1063803b9 Update server 2022-11-22 23:12:21 +02:00
3cbd31b49c Update server 2022-11-22 23:11:45 +02:00
a39e0eaa17 Update server 2022-11-22 23:11:14 +02:00
b63fb39fd4 Update server 2022-11-22 23:09:33 +02:00
0dfbd296a7 Update server 2022-11-22 20:44:22 +02:00
233f49a998 Update server 2022-11-22 20:43:30 +02:00
127f17cd97 Update server 2022-11-22 20:42:55 +02:00
d1ad8b4d3a Update server 2022-11-22 20:38:16 +02:00
f20e1ad260 Update build 2022-11-22 20:04:43 +02:00
27151a26d1 Update build 2022-11-22 20:03:36 +02:00
544e9e59ab Update build 2022-11-22 20:00:44 +02:00
4e4cd6f893 Update build 2022-11-22 19:55:55 +02:00
e9ff060544 Update build 2022-11-22 19:52:25 +02:00
7d677f4a34 Update build 2022-11-22 19:52:11 +02:00
8f96b8c98b Update build 2022-11-22 19:51:09 +02:00
1084a808c7 Update build 2022-11-22 19:40:02 +02:00
3838f774bf Update build 2022-11-22 19:33:38 +02:00
06bb275f0d Update build 2022-11-22 19:18:48 +02:00
a05f7cc987 Update build 2022-11-22 19:15:34 +02:00
c5c8bc5bb3 Update build 2022-11-22 19:14:50 +02:00
d6bc4e51e5 Update build 2022-11-22 19:11:00 +02:00
4ae02f70d6 Update build 2022-11-22 18:54:22 +02:00
d593d6dc83 Update build 2022-11-22 18:35:36 +02:00
1a1fa9450e Update build 2022-11-22 18:34:12 +02:00
0d24604f2a Update build 2022-11-22 18:33:46 +02:00
1d7c994036 Update build 2022-11-22 18:33:06 +02:00
bc2bf24a65 Update build 2022-11-22 18:32:47 +02:00
cdbfc7891d Update build 2022-11-22 18:30:25 +02:00
c730341674 Update build 2022-11-22 18:28:50 +02:00
b621b76e37 Connect to mediasoup with timeout(fix when it appears offline) 2022-11-22 18:27:56 +02:00
39ad9cad27 Update bundle 2022-11-22 18:10:05 +02:00
8860423e21 LH-265: Update client config 2022-11-22 10:28:45 +02:00
9179a67f64 LH-265: Enable audio on video server 2022-11-21 22:59:41 +02:00
75d0e3aee7 exe right for build.sh 2022-10-31 22:26:08 +00:00
30ac997634 Merge pull request 'added build.sh' (#14) from temp-build into develop
Reviewed-on: #14
2022-10-31 22:22:20 +00:00
5aea138f6a added build.sh 2022-10-31 12:17:07 +02:00
5b01ddc2a8 Merge pull request 'LH-259-mediasoup-always-return-a-callback-response-to-clients' (#13) from LH-259-mediasoup-always-return-a-callback-response-to-clients into develop
Reviewed-on: #13
2022-10-25 16:18:54 +00:00
084ff36ebe LH-259: Refactor createRoom 2022-10-24 22:38:06 +03:00
f4ebf92783 LH-259: Added callback from transport-produce 2022-10-24 22:35:22 +03:00
b59a157b18 LH-259: Comment callback from transport-produce 2022-10-24 22:19:37 +03:00
9f8347bec5 LH-259: Update createRoom callback 2022-10-24 22:16:47 +03:00
24390c98e5 LH-259: Added callbacks 2022-10-24 22:11:14 +03:00
1a7371fe18 Parse RTC_MIN_PORT and RTC_MAX_PORT 2022-10-18 18:27:02 +03:00
be5f97762a Merge pull request 'LH-253: Added callId for transportclose and producerclose events' (#12) from LH-253-mediasoup-handle-callid-undefined into master
Reviewed-on: #12
2022-10-18 07:53:33 +00:00
03a11126c4 LH-253: Check if we have callId in closeCall 2022-10-18 10:51:20 +03:00
fafbee6e4c LH-253: Added callId for transportclose and producerclose events 2022-10-18 02:05:22 +03:00
bbf23c33d4 Merge pull request 'LH-252: Update .env variables' (#11) from LH-252-mediasoup-add-a-config-file-with-keys-and-ports into master
Reviewed-on: #11
2022-10-09 06:50:45 +00:00
5c2808e75a LH-252: Update .env variables 2022-10-06 15:21:54 +03:00
2aea7497cc Merge pull request 'added log for dtls transport-connect' (#10) from LH-249-debug-for-i-os-dtls-problems into master
Reviewed-on: #10
2022-10-06 06:41:07 +00:00
56835d6660 added log for dtls transport-connect 2022-10-05 15:44:46 +03:00
fc42c79210 Fix missing callId 2022-09-27 13:13:29 +03:00
d81bc8582d Merge branch 'master' of https://git.safemobile.org/Safemobile/mediasoup 2022-09-27 13:05:15 +03:00
a4d16998cd Fix call check before call close() 2022-09-27 13:03:32 +03:00
de1458bbde Merge pull request 'LINXD-2197: Added comments; Catch errors; Fix package.json start:run script' (#8) from LINXD-2197-refactor-improving-mediasoup-web-socket-component into master
Reviewed-on: #8
2022-09-27 10:00:25 +00:00
b0fad5f1db LINXD-2197: On peer disconnect delete the call; Added log when call is already deleted; Added log when user send multiple createWebRtcTransport 2022-09-27 12:43:07 +03:00
eb5aa12d65 LINXD-2197: Added the initial demo project used; Check before set producerTransport and consumerTransport if it was set before 2022-09-27 07:55:25 +03:00
52b4794a86 LINXD-2197: Added workflow diagram 2022-09-25 20:29:32 +03:00
5f8f2ab44c LINXD-2197: Added comments; Catch errors; Fix package.json start:run script 2022-09-25 20:03:17 +03:00
55455be8e7 Merge pull request 'LINXD-2222-debugging-for-i-os' (#7) from LINXD-2222-debugging-for-i-os into master
Reviewed-on: #7
2022-09-20 23:16:16 +00:00
62a82dc3a5 LINXD-2222: Removed socketio-wildcard 2022-09-20 14:17:16 +03:00
ac078e72ff LINXD-2222: Removed requestCert and rejectedUnauthorized from server options 2022-09-20 14:15:54 +03:00
be396e1047 LINXD-2222: Set namespate to '/'; Removed httpolyglot; Removed unused code 2022-09-20 14:02:22 +03:00
149876fc70 LINXD-2222: use https instead of httpolyglot; Added logs 2022-09-20 09:36:31 +03:00
adbeb2071b Update to start with defeult port 3000 2022-09-19 23:37:20 +03:00
a6681ffe40 LINXD-2222: Update 2022-09-19 23:32:15 +03:00
efc9bfd114 LINXD-2222: Update 2022-09-19 23:31:36 +03:00
a8afa8a532 LINXD-2222: Update 2022-09-19 23:30:18 +03:00
507c131058 LINXD-2222: Update 2022-09-19 23:28:39 +03:00
043f66eb0c LINXD-2222: Update 2022-09-19 23:24:32 +03:00
cb5716dd5c LINXD-2222: Update 2022-09-19 23:12:24 +03:00
ae39a45f6d LINXD-2222: Update 2022-09-19 23:09:55 +03:00
0ec5769ee0 LINXD-2222: Update 2022-09-19 18:12:37 +03:00
72ee3e43ab LINXD-2222: Update 2022-09-19 18:10:34 +03:00
f20c7fada8 LINXD-2222: Update 2022-09-19 18:06:39 +03:00
53a654c50f LINXD-2222: Update 2022-09-19 18:02:30 +03:00
d54403299f LINXD-2222: Update 2022-09-19 17:55:21 +03:00
177d54ec67 LINXD-2222: Update 2022-09-19 17:45:42 +03:00
649c7a3767 LINXD-2222: Update 2022-09-19 17:45:18 +03:00
08d6ccbb21 LINXD-2222: Update 2022-09-19 17:44:45 +03:00
fd005351b5 LINXD-2222: Update 2022-09-19 17:43:39 +03:00
fc111540d8 LINXD-2222: Update 2022-09-19 17:42:42 +03:00
c4f4be0aa8 LINXD-2222: Update 2022-09-19 17:42:16 +03:00
40c03592df LINXD-2222: Update 2022-09-19 17:40:57 +03:00
a59cbcf8cc LINXD-2222: Update 2022-09-19 17:13:48 +03:00
7cc3a95b38 LINXD-2222: Update 2022-09-19 17:12:22 +03:00
05e3d997f1 LINXD-2222: Update 2022-09-19 17:04:56 +03:00
9c731f4085 LINXD-2222: Update 2022-09-19 17:03:58 +03:00
f6d862966e LINXD-2222: Update 2022-09-19 17:02:13 +03:00
05ccd5cfd4 LINXD-2222: Update 2022-09-19 17:00:43 +03:00
43eee11c7e LINXD-2222: Update 2022-09-19 16:53:32 +03:00
0033cd528d LINXD-2222: Update 2022-09-19 16:53:09 +03:00
5022d88b1d LINXD-2222: Update 2022-09-19 16:51:15 +03:00
52b922825f LINXD-2222: Update 2022-09-19 16:48:46 +03:00
07be8af9ae LINXD-2222: Update 2022-09-19 16:46:43 +03:00
29737fe5d8 LINXD-2222: Fix middleware typo 2022-09-19 16:44:29 +03:00
1f5755b72d LINXD-2222: Added wildcard; Replace httpolyglot with https; Set CORS to * 2022-09-19 16:21:50 +03:00
a2c878f91c Merge pull request 'Delete the whole call(with id) when we call closeCall' (#5) from delete-whole-call-id into master
Reviewed-on: #5
2022-09-17 08:43:57 +00:00
7b6f78725b LINXD-2209: Call closeCall from producerclose and transportclose on consumer handlers; Update README.md 2022-09-16 18:49:56 +03:00
41c6ad281d Delete the whole call(with id) when we call closeCall 2022-09-16 11:08:02 +03:00
f5406f163f Merge pull request 'Allow io3 on server creation' (#4) from Allow-io3 into master
Reviewed-on: #4
2022-09-15 14:54:41 +00:00
28497fda91 Merge with master 2022-09-15 17:53:37 +03:00
4a98a79630 Merge pull request 'LINXD-2209-black-screen-when-2-video-calls-are-answered-simultaneously' (#3) from LINXD-2209-black-screen-when-2-video-calls-are-answered-simultaneously into master
Reviewed-on: #3
2022-09-15 14:49:55 +00:00
22e8b4d364 LINXD-2209: Refactor how we close the call; Check for callId in createRoom event 2022-09-15 17:07:47 +03:00
575dbd69b0 Allow io3 on server creation 2022-09-15 14:49:10 +03:00
a51a757d17 LINXD-2209: Correctly close the call 2022-09-15 09:57:57 +03:00
c059dd5afc LINXD-2209: Correctly close the call 2022-09-15 09:56:32 +03:00
19808da24e LINXD-2209: Get callId from soekct dictionary in consumer-resume case 2022-09-15 09:43:59 +03:00
2f6c25c171 LINXD-2209: Correctly set router to videoCalls 2022-09-15 09:41:24 +03:00
ead0069aa8 LINXD-2209: Correctly set router to videoCalls 2022-09-15 09:39:52 +03:00
434c8f744c LINXD-2209: Correctly set router to videoCalls 2022-09-15 09:35:35 +03:00
7198dc91b1 LINXD-2209: Check for router in videoCalls 2022-09-15 09:33:30 +03:00
f629012712 LINXD-2209: Check for router in videoCalls 2022-09-15 09:32:41 +03:00
41b50d2a11 LINXD-2209: Identify the callId from dictionary 2022-09-15 09:19:04 +03:00
b85ba68c9c LINXD-2209: Added comments 2022-09-13 22:24:10 +03:00
6acd276324 LINXD-2209: Refactor how we save router, consumer, producer, producerTransport and consumerTransport 2022-09-13 22:16:51 +03:00
294dbdf38d LINXD-2209: Added logs 2022-09-13 21:43:16 +03:00
c3d50fdc4e LINXD-2209: Add 4000ms delay between room creation 2022-09-13 21:38:06 +03:00
c12ececf47 LINXD-2209: Add 2000ms delay between room creation 2022-09-13 21:35:26 +03:00
47eb302f5f LINXD-2209: Added logs on consume 2022-09-13 21:33:04 +03:00
accf960aa7 LINXD-2209: Added logs on consume 2022-09-13 21:15:51 +03:00
ab685270f1 LINXD-2209: Add 1000ms delay between room creation 2022-09-13 21:08:14 +03:00
6938e751fe LINXD-2209: Add 100ms delay between room creation 2022-09-13 21:08:03 +03:00
031a7bc4c5 LINXD-2209: Remove console.logs 2022-09-13 21:05:24 +03:00
d7486d0fd6 LINXD-2209: Add 10ms delay between room creation 2022-09-13 21:04:42 +03:00
38931f0654 LINXD-2209: Add 50ms delay between room creation 2022-09-13 21:02:29 +03:00
bb684ca4db LINXD-2209: Add 300ms delay 2022-09-13 20:59:55 +03:00
25a76c343b LINXD-2209: Move getRtpCapa outside of room creation 2022-09-13 20:59:12 +03:00
817a49204d LINXD-2209: Added logs 2022-09-13 20:58:06 +03:00
91b4db1982 LINXD-2209: Added logs 2022-09-13 20:54:35 +03:00
8562f6c58c LINXD-2209: Added logs 2022-09-13 20:49:40 +03:00
5abc309502 LINXD-2209: Added logs 2022-09-13 20:28:07 +03:00
ecb5a88a2c LINXD-2209: Update port 2022-09-13 20:10:34 +03:00
782b749ea3 LINXD-2209: Check queue length 2022-09-13 20:09:25 +03:00
b834016dcb LINXD-2209: Create rooms in sequence 2022-09-13 19:56:06 +03:00
523945271e Remove callback with producer id from transport-produce 2022-08-31 17:06:54 +03:00
0af7ddd786 Remove callback with producer id from transport-produce 2022-08-31 16:53:08 +03:00
ba5add489d Remove callback with producer id from transport-produce 2022-08-31 16:49:23 +03:00
d5cb144799 Remove callback with producer id from transport-produce 2022-08-31 16:47:54 +03:00
4e92f6cdd3 Remove callback with producer id from transport-produce 2022-08-31 16:43:59 +03:00
aaa1c5cea4 Remove callback with producer id from transport-produce 2022-08-31 16:40:38 +03:00
4f302570a2 Remove callback with producer id from transport-produce 2022-08-31 16:24:21 +03:00
12 changed files with 1512 additions and 1488 deletions

4
.env
View File

@ -1,3 +1,7 @@
PORT=3000 PORT=3000
IP=0.0.0.0 # Listening IPv4 or IPv6. IP=0.0.0.0 # Listening IPv4 or IPv6.
ANNOUNCED_IP=185.8.154.190 # Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with private IP). ANNOUNCED_IP=185.8.154.190 # Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with private IP).
RTC_MIN_PORT=2000
RTC_MAX_PORT=2020
SERVER_CERT="./server/ssl/cert.pem"
SERVER_KEY="./server/ssl/key.pem"

1
.gitignore vendored
View File

@ -1 +1,2 @@
/node_modules /node_modules
/dist

View File

@ -1,5 +1,11 @@
# Video server # Video server
### Generating certificates
##### To generate SSL certificates you must:
1. Go to `/server/ssl`
2. Execute `openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem`
### Development ### Development
@ -16,14 +22,21 @@
2. Run the `npm start:prod` command to start the server in production mode. 2. Run the `npm start:prod` command to start the server in production mode.
(To connect to the terminal, use `pm2 log video-server`) (To connect to the terminal, use `pm2 log video-server`)
---
### Web client
- The server will start by default on port 3000, and the ssl certificates will have to be configured - The server will start by default on port 3000, and the ssl certificates will have to be configured
- The web client can be accessed using the /sfu path - The web client can be accessed using the /sfu path
ex: http://localhost:3000/sfu/?assetId=1&&accountId=1&producer=true&assetName=Adi&assetType=linx ex: https://HOST/sfu/?assetId=1&&accountId=1&producer=true&dest_asset_id=75&assetName=Adi
assetId = asset id of the unit on which you are doing the test assetId = asset id of the unit on which you are doing the test
accountId = account id of the unit on which you are doing the test accountId = account id of the unit on which you are doing the test
producer = it will always be true because you are the producer producer = it will always be true because you are the producer
(it's possible to put false, but then you have to have another client with producer true) (it's possible to put false, but then you have to have another client with producer true)
assetName = asset name of the unit on which you are doing the test assetName = asset name of the unit on which you are doing the test
assetType = asset type of the unit on which you are doing the test dest_asset_id= the addressee with whom the call is made
- To make a call using this client, you need a microphone and permission to use it
- For any changes related to the client, the command `npm run watch' will have to be used to generate the bundle.js used by the web client
### Demo project
The demo project used initially and then modified for our needs `https://github.com/jamalag/mediasoup2`

660
app.js
View File

@ -1,28 +1,38 @@
import 'dotenv/config' require('dotenv').config()
/** const express = require('express');
* integrating mediasoup server with a node.js application const app = express();
*/ const Server = require('socket.io');
const path = require('node:path');
/* Please follow mediasoup installation requirements */ const fs = require('node:fs');
/* https://mediasoup.org/documentation/v3/mediasoup/installation/ */ let https;
import express from 'express' try {
const app = express() https = require('node:https');
} catch (err) {
import https from 'httpolyglot' console.log('https support is disabled!');
import fs from 'fs' }
import path from 'path' const mediasoup = require('mediasoup');
const __dirname = path.resolve()
import Server from 'socket.io'
import mediasoup, { getSupportedRtpCapabilities } from 'mediasoup'
let worker let worker
let router = {} /**
let producerTransport * videoCalls
let consumerTransport * |-> Router
let producer * |-> Producer
let consumer * |-> Consumer
* |-> Producer Transport
* |-> Consumer Transport
*
* '<callId>': {
* router: Router,
* producer: Producer,
* producerTransport: Producer Transport,
* consumer: Consumer,
* consumerTransport: Consumer Transport
* }
*
**/
let videoCalls = {}
let socketDetails = {}
app.get('/', (_req, res) => { app.get('/', (_req, res) => {
res.send('Hello from mediasoup app!') res.send('Hello from mediasoup app!')
@ -32,212 +42,441 @@ app.use('/sfu', express.static(path.join(__dirname, 'public')))
// SSL cert for HTTPS access // SSL cert for HTTPS access
const options = { const options = {
key: fs.readFileSync('./server/ssl/key.pem', 'utf-8'), key: fs.readFileSync(process.env.SERVER_KEY, 'utf-8'),
cert: fs.readFileSync('./server/ssl/cert.pem', 'utf-8') cert: fs.readFileSync(process.env.SERVER_CERT, 'utf-8'),
} }
const httpsServer = https.createServer(options, app) const httpsServer = https.createServer(options, app);
const io = new Server(httpsServer, {
allowEIO3: true,
origins: ["*:*"],
// allowRequest: (req, next) => {
// console.log('req', req);
// next(null, true)
// }
});
// const io = new Server(server, { origins: '*:*', allowEIO3: true });
httpsServer.listen(process.env.PORT, () => { httpsServer.listen(process.env.PORT, () => {
console.log('Listening on port:', process.env.PORT) console.log('Video server listening on port:', process.env.PORT);
}) });
const io = new Server(httpsServer) const peers = io.of('/');
// socket.io namespace (could represent a room?)
const peers = io.of('/mediasoup')
/**
* Worker
* |-> Router(s)
* |-> Producer Transport(s)
* |-> Producer
* |-> Consumer Transport(s)
* |-> Consumer
**/
const createWorker = async () => { const createWorker = async () => {
worker = await mediasoup.createWorker({ try {
rtcMinPort: 2000, worker = await mediasoup.createWorker({
rtcMaxPort: 2020, rtcMinPort: parseInt(process.env.RTC_MIN_PORT),
}) rtcMaxPort: parseInt(process.env.RTC_MAX_PORT),
console.log(`[createWorker] worker pid ${worker.pid}`) })
console.log(`[createWorker] worker pid ${worker.pid}`);
worker.on('died', error => {
// This implies something serious happened, so kill the application worker.on('died', error => {
console.error('mediasoup worker has died', error) // This implies something serious happened, so kill the application
setTimeout(() => process.exit(1), 2000) // exit in 2 seconds console.error('mediasoup worker has died', error);
}) setTimeout(() => process.exit(1), 2000); // exit in 2 seconds
})
return worker return worker;
} catch (error) {
console.log(`ERROR | createWorker | ${error.message}`);
}
} }
// We create a Worker as soon as our application starts // We create a Worker as soon as our application starts
worker = createWorker() worker = createWorker();
// This is an Array of RtpCapabilities // This is an Array of RtpCapabilities
// https://mediasoup.org/documentation/v3/mediasoup/rtp-parameters-and-capabilities/#RtpCodecCapability // https://mediasoup.org/documentation/v3/mediasoup/rtp-parameters-and-capabilities/#RtpCodecCapability
// list of media codecs supported by mediasoup ... // list of media codecs supported by mediasoup ...
// https://github.com/versatica/mediasoup/blob/v3/src/supportedRtpCapabilities.ts // https://github.com/versatica/mediasoup/blob/v3/src/supportedRtpCapabilities.ts
const mediaCodecs = [ const mediaCodecs = [
{ {
kind: 'audio', kind : 'audio',
mimeType: 'audio/opus', mimeType : 'audio/opus',
clockRate: 48000, clockRate : 48000,
channels: 2, channels : 2
}, },
{ {
kind: 'video', kind : 'video',
mimeType: 'video/VP8', mimeType : 'video/VP8',
clockRate: 90000, clockRate : 90000,
parameters: { parameters :
'x-google-start-bitrate': 1000, {
'x-google-start-bitrate' : 1000
}, },
channels : 2
}, },
] {
kind : 'video',
peers.on('connection', async socket => { mimeType : 'video/VP9',
console.log('[connection] socketId:', socket.id) clockRate : 90000,
socket.emit('connection-success', { parameters :
socketId: socket.id, {
existsProducer: producer ? true : false, 'profile-id' : 2,
}) 'x-google-start-bitrate' : 1000
}
socket.on('disconnect', () => { },
// do some cleanup {
console.log('peer disconnected') kind : 'video',
}) mimeType : 'video/h264',
clockRate : 90000,
socket.on('createRoom', async ({ callId }, callback) => { parameters :
console.log('[createRoom] callId', callId); {
console.log('Router length:', Object.keys(router).length); 'packetization-mode' : 1,
if (router[callId] === undefined) { 'profile-level-id' : '4d0032',
// worker.createRouter(options) 'level-asymmetry-allowed' : 1,
// options = { mediaCodecs, appData } 'x-google-start-bitrate' : 1000
// mediaCodecs -> defined above }
// appData -> custom application data - we are not supplying any },
// none of the two are required {
router[callId] = await worker.createRouter({ mediaCodecs }) kind : 'video',
console.log(`[createRoom] Router ID: ${router[callId].id}`) mimeType : 'video/h264',
clockRate : 90000,
parameters :
{
'packetization-mode' : 1,
'profile-level-id' : '42e01f',
'level-asymmetry-allowed' : 1,
'x-google-start-bitrate' : 1000
} }
getRtpCapabilities(callId, callback)
})
const getRtpCapabilities = (callId, callback) => {
const rtpCapabilities = router[callId].rtpCapabilities
callback({ rtpCapabilities })
} }
// {
// kind: 'audio',
// mimeType: 'audio/opus',
// clockRate: 48000,
// channels: 2,
// },
// {
// kind: 'video',
// mimeType: 'video/VP8',
// clockRate: 90000,
// parameters: {
// 'x-google-start-bitrate': 1000,
// },
// },
];
// Client emits a request to create server side Transport const closeCall = (callId) => {
// We need to differentiate between the producer and consumer transports try {
socket.on('createWebRtcTransport', async ({ sender, callId }, callback) => { if (callId && videoCalls[callId]) {
console.log(`[createWebRtcTransport] Is this a sender request? ${sender} | callId ${callId}`) videoCalls[callId].producerVideo?.close();
// The client indicates if it is a producer or a consumer videoCalls[callId].producerAudio?.close();
// if sender is true, indicates a producer else a consumer videoCalls[callId].consumerVideo?.close();
if (sender) videoCalls[callId].consumerAudio?.close();
producerTransport = await createWebRtcTransportLayer(callId, callback)
else
consumerTransport = await createWebRtcTransportLayer(callId, callback)
})
// see client's socket.emit('transport-connect', ...) videoCalls[callId]?.consumerTransport?.close();
socket.on('transport-connect', async ({ dtlsParameters }) => { videoCalls[callId]?.producerTransport?.close();
console.log('[transport-connect] DTLS PARAMS... ', { dtlsParameters }) videoCalls[callId]?.router?.close();
await producerTransport.connect({ dtlsParameters }) delete videoCalls[callId];
}) } else {
console.log(`The call with id ${callId} has already been deleted`);
}
} catch (error) {
console.log(`ERROR | closeCall | callid ${callId} | ${error.message}`);
}
}
// see client's socket.emit('transport-produce', ...) /*
socket.on('transport-produce', async ({ kind, rtpParameters, appData }, callback) => { - Handlers for WS events
// call produce based on the prameters from the client - These are created only when we have a connection with a peer
producer = await producerTransport.produce({ */
kind, peers.on('connection', async socket => {
rtpParameters, console.log('[connection] socketId:', socket.id);
})
console.log(`[transport-produce] Producer ID: ${producer.id} | kind: ${producer.kind}`) // After making the connection successfully, we send the client a 'connection-success' event
socket.emit('connection-success', {
socketId: socket.id
});
producer.on('transportclose', () => { // It is triggered when the peer is disconnected
console.log('transport for this producer closed', callId) socket.on('disconnect', () => {
const callId = socketDetails[socket.id];
// https://mediasoup.org/documentation/v3/mediasoup/api/#producer-close console.log(`disconnect | socket ${socket.id} | callId ${callId}`);
producer.close() delete socketDetails[socket.id];
closeCall(callId);
});
// https://mediasoup.org/documentation/v3/mediasoup/api/#router-close /*
router[callId].close() - This event creates a room with the roomId and the callId sent
delete router[callId] - It will return the rtpCapabilities of that room
}) - If the room already exists, it will not create it, but will only return rtpCapabilities
*/
// Send back to the client the Producer's id socket.on('createRoom', async ({ callId }, callback) => {
callback({ let callbackResponse = null;
id: producer.id
})
})
// see client's socket.emit('transport-recv-connect', ...)
socket.on('transport-recv-connect', async ({ dtlsParameters }) => {
console.log(`[transport-recv-connect] DTLS PARAMS: ${dtlsParameters}`)
await consumerTransport.connect({ dtlsParameters })
})
socket.on('consume', async ({ rtpCapabilities, callId }, callback) => {
try { try {
console.log('consume', rtpCapabilities, callId); // We can continue with the room creation process only if we have a callId
// check if the router can consume the specified producer if (callId) {
if (router[callId].canConsume({ console.log(`[createRoom] socket.id ${socket.id} callId ${callId}`);
producerId: producer.id, if (!videoCalls[callId]) {
rtpCapabilities console.log('[createRoom] callId', callId);
})) { videoCalls[callId] = { router: await worker.createRouter({ mediaCodecs }) }
// transport can now consume and return a consumer console.log(`[createRoom] Router ID: ${videoCalls[callId].router.id}`);
consumer = await consumerTransport.consume({
producerId: producer.id,
rtpCapabilities,
paused: true,
})
consumer.on('transportclose', () => {
console.log('transport close from consumer', callId)
// closeRoom(callId)
delete router[callId]
})
consumer.on('producerclose', () => {
console.log('producer of consumer closed', callId)
// https://mediasoup.org/documentation/v3/mediasoup/api/#router-close
router[callId].close()
delete router[callId]
})
// from the consumer extract the following params
// to send back to the Client
const params = {
id: consumer.id,
producerId: producer.id,
kind: consumer.kind,
rtpParameters: consumer.rtpParameters,
} }
socketDetails[socket.id] = callId;
// send the parameters to the client // rtpCapabilities is set for callback
callback({ params }) console.log('[getRtpCapabilities] callId', callId);
callbackResponse = {
rtpCapabilities :videoCalls[callId].router.rtpCapabilities
};
} else {
console.log(`[createRoom] missing callId ${callId}`);
} }
} catch (error) { } catch (error) {
console.log(error.message) console.log(`ERROR | createRoom | callId ${callId} | ${error.message}`);
callback({ } finally {
params: { callback(callbackResponse);
error: error }
});
/*
- Client emits a request to create server side Transport
- Depending on the sender, producerTransport or consumerTransport is created on that router
- It will return parameters, these are required for the client to create the RecvTransport
from the client.
- If the client is producer(sender: true) then it will use parameters for device.createSendTransport(params)
- If the client is a consumer(sender: false) then it will use parameters for device.createRecvTransport(params)
*/
socket.on('createWebRtcTransport', async ({ sender }, callback) => {
try {
const callId = socketDetails[socket.id];
console.log(`[createWebRtcTransport] sender ${sender} | callId ${callId}`);
if (sender) {
if (!videoCalls[callId].producerTransport) {
videoCalls[callId].producerTransport = await createWebRtcTransportLayer(callId, callback);
} else {
console.log(`producerTransport has already been defined | callId ${callId}`);
callback(null);
} }
}) } else if (!sender) {
if (!videoCalls[callId].consumerTransport) {
videoCalls[callId].consumerTransport = await createWebRtcTransportLayer(callId, callback);
} else {
console.log(`consumerTransport has already been defined | callId ${callId}`);
callback(null);
}
}
} catch (error) {
console.log(`ERROR | createWebRtcTransport | callId ${socketDetails[socket.id]} | sender ${sender} | ${error.message}`);
callback(error);
}
});
/*
- The client sends this event after successfully creating a createSendTransport(AS PRODUCER)
- The connection is made to the created transport
*/
socket.on('transport-connect', async ({ dtlsParameters }) => {
try {
const callId = socketDetails[socket.id];
if (typeof dtlsParameters === 'string') dtlsParameters = JSON.parse(dtlsParameters);
console.log(`[transport-connect] socket.id ${socket.id} | callId ${callId}`);
await videoCalls[callId].producerTransport.connect({ dtlsParameters });
} catch (error) {
console.log(`ERROR | transport-connect | callId ${socketDetails[socket.id]} | ${error.message}`);
}
});
/*
- The event sent by the client (PRODUCER) after successfully connecting to producerTransport
- For the router with the id callId, we make produce on producerTransport
- Create the handler on producer at the 'transportclose' event
*/
socket.on('transport-produce', async ({ kind, rtpParameters, appData }, callback) => {
try {
const callId = socketDetails[socket.id];
if (typeof rtpParameters === 'string') rtpParameters = JSON.parse(rtpParameters);
console.log(`[transport-produce] kind: ${kind} | socket.id: ${socket.id} | callId: ${callId}`);
console.log('kind', kind);
console.log('rtpParameters', rtpParameters);
if (kind === 'video') {
videoCalls[callId].producerVideo = await videoCalls[callId].producerTransport.produce({
kind,
rtpParameters,
});
console.log(`[transport-produce] Producer ID: ${videoCalls[callId].producerVideo.id} | kind: ${videoCalls[callId].producerVideo.kind}`);
videoCalls[callId].producerVideo.on('transportclose', () => {
const callId = socketDetails[socket.id];
console.log('transport for this producer closed', callId)
closeCall(callId);
});
// Send back to the client the Producer's id
callback && callback({
id: videoCalls[callId].producerVideo.id
});
} else if (kind === 'audio') {
videoCalls[callId].producerAudio = await videoCalls[callId].producerTransport.produce({
kind,
rtpParameters,
});
console.log(`[transport-produce] Producer ID: ${videoCalls[callId].producerAudio.id} | kind: ${videoCalls[callId].producerAudio.kind}`);
videoCalls[callId].producerAudio.on('transportclose', () => {
const callId = socketDetails[socket.id];
console.log('transport for this producer closed', callId)
closeCall(callId);
});
// Send back to the client the Producer's id
callback && callback({
id: videoCalls[callId].producerAudio.id
});
}
} catch (error) {
console.log(`ERROR | transport-produce | callId ${socketDetails[socket.id]} | ${error.message}`);
}
});
/*
- The client sends this event after successfully creating a createRecvTransport(AS CONSUMER)
- The connection is made to the created consumerTransport
*/
socket.on('transport-recv-connect', async ({ dtlsParameters }) => {
try {
const callId = socketDetails[socket.id];
console.log(`[transport-recv-connect] socket.id ${socket.id} | callId ${callId}`);
await videoCalls[callId].consumerTransport.connect({ dtlsParameters });
} catch (error) {
console.log(`ERROR | transport-recv-connect | callId ${socketDetails[socket.id]} | ${error.message}`);
} }
}) })
socket.on('consumer-resume', async () => { /*
console.log(`[consumer-resume]`) - The customer consumes after successfully connecting to consumerTransport
await consumer.resume() - The previous step was 'transport-recv-connect', and before that 'createWebRtcTransport'
}) - This event is only sent by the consumer
}) - The parameters that the consumer consumes are returned
- The consumer does consumerTransport.consume(params)
*/
socket.on('consume', async ({ rtpCapabilities }, callback) => {
try {
console.log(`[consume] rtpCapabilities: ${JSON.stringify(rtpCapabilities)}`);
const callId = socketDetails[socket.id];
console.log('[consume] callId', callId);
const canConsumeVideo = !!videoCalls[callId].producerVideo && !!videoCalls[callId].router.canConsume({
producerId: videoCalls[callId].producerVideo.id,
rtpCapabilities
})
const canConsumeAudio = !!videoCalls[callId].producerAudio && !!videoCalls[callId].router.canConsume({
producerId: videoCalls[callId].producerAudio.id,
rtpCapabilities
})
console.log('[consume] canConsumeVideo', canConsumeVideo);
console.log('[consume] canConsumeAudio', canConsumeAudio);
if (canConsumeVideo && !canConsumeAudio) {
console.log('1');
const videoParams = await consumeVideo(callId, rtpCapabilities)
console.log('videoParams', videoParams);
callback({ videoParams, audioParams: null });
} else if (canConsumeVideo && canConsumeAudio) {
console.log('2');
const videoParams = await consumeVideo(callId, rtpCapabilities)
const audioParams = await consumeAudio(callId, rtpCapabilities)
callback({ videoParams, audioParams });
} else {
console.log(`[consume] Can't consume | callId ${callId}`);
callback(null);
}
} catch (error) {
console.log(`ERROR | consume | callId ${socketDetails[socket.id]} | ${error.message}`)
callback({ params: { error } });
}
});
/*
- Event sent by the consumer after consuming to resume the pause
- When consuming on consumerTransport, it is initially done with paused: true, here we will resume
*/
socket.on('consumer-resume', async () => {
try {
const callId = socketDetails[socket.id];
console.log(`[consumer-resume] callId ${callId}`)
await videoCalls[callId].consumerVideo.resume();
await videoCalls[callId].consumerAudio.resume();
} catch (error) {
console.log(`ERROR | consumer-resume | callId ${socketDetails[socket.id]} | ${error.message}`);
}
});
});
const consumeVideo = async (callId, rtpCapabilities) => {
videoCalls[callId].consumerVideo = await videoCalls[callId].consumerTransport.consume({
producerId: videoCalls[callId].producerVideo.id,
rtpCapabilities,
paused: true,
});
// https://mediasoup.org/documentation/v3/mediasoup/api/#consumer-on-transportclose
videoCalls[callId].consumerVideo.on('transportclose', () => {
const callId = socketDetails[socket.id];
console.log('transport close from consumer', callId);
closeCall(callId);
});
// https://mediasoup.org/documentation/v3/mediasoup/api/#consumer-on-producerclose
videoCalls[callId].consumerVideo.on('producerclose', () => {
const callId = socketDetails[socket.id];
console.log('producer of consumer closed', callId);
closeCall(callId);
});
return {
id: videoCalls[callId].consumerVideo.id,
producerId: videoCalls[callId].producerVideo.id,
kind: 'video',
rtpParameters: videoCalls[callId].consumerVideo.rtpParameters,
}
}
const consumeAudio = async (callId, rtpCapabilities) => {
videoCalls[callId].consumerAudio = await videoCalls[callId].consumerTransport.consume({
producerId: videoCalls[callId].producerAudio.id,
rtpCapabilities,
paused: true,
});
// https://mediasoup.org/documentation/v3/mediasoup/api/#consumer-on-transportclose
videoCalls[callId].consumerAudio.on('transportclose', () => {
const callId = socketDetails[socket.id];
console.log('transport close from consumer', callId);
closeCall(callId);
});
// https://mediasoup.org/documentation/v3/mediasoup/api/#consumer-on-producerclose
videoCalls[callId].consumerAudio.on('producerclose', () => {
const callId = socketDetails[socket.id];
console.log('producer of consumer closed', callId);
closeCall(callId);
});
return {
id: videoCalls[callId].consumerAudio.id,
producerId: videoCalls[callId].producerAudio.id,
kind: 'audio',
rtpParameters: videoCalls[callId].consumerAudio.rtpParameters,
}
}
/*
- Called from at event 'createWebRtcTransport' and assigned to the consumer or producer transport
- It will return parameters, these are required for the client to create the RecvTransport
from the client.
- If the client is producer(sender: true) then it will use parameters for device.createSendTransport(params)
- If the client is a consumer(sender: false) then it will use parameters for device.createRecvTransport(params)
*/
const createWebRtcTransportLayer = async (callId, callback) => { const createWebRtcTransportLayer = async (callId, callback) => {
try { try {
console.log('[createWebRtcTransportLayer] callId', callId); console.log('[createWebRtcTransportLayer] callId', callId);
@ -252,48 +491,41 @@ const createWebRtcTransportLayer = async (callId, callback) => {
enableUdp: true, enableUdp: true,
enableTcp: true, enableTcp: true,
preferUdp: true, preferUdp: true,
} };
// console.log('webRtcTransport_options', webRtcTransport_options);
// console.log('router', router, '| router[callId]', router[callId]);
// https://mediasoup.org/documentation/v3/mediasoup/api/#router-createWebRtcTransport // https://mediasoup.org/documentation/v3/mediasoup/api/#router-createWebRtcTransport
let transport = await router[callId].createWebRtcTransport(webRtcTransport_options) let transport = await videoCalls[callId].router.createWebRtcTransport(webRtcTransport_options)
console.log(`callId: ${callId} | transport id: ${transport.id}`) console.log(`callId: ${callId} | transport id: ${transport.id}`)
// Handler for when DTLS(Datagram Transport Layer Security) changes
transport.on('dtlsstatechange', dtlsState => { transport.on('dtlsstatechange', dtlsState => {
console.log(`transport | dtlsstatechange | calldId ${callId} | dtlsState ${dtlsState}`);
if (dtlsState === 'closed') { if (dtlsState === 'closed') {
transport.close() transport.close();
} }
}) });
// Handler if the transport layer has closed (for various reasons)
transport.on('close', () => { transport.on('close', () => {
console.log('transport closed') console.log(`transport | closed | calldId ${callId}`);
}) });
const params = { const params = {
id: transport.id, id: transport.id,
iceParameters: transport.iceParameters, iceParameters: transport.iceParameters,
iceCandidates: transport.iceCandidates, iceCandidates: transport.iceCandidates,
dtlsParameters: transport.dtlsParameters, dtlsParameters: transport.dtlsParameters,
} };
console.log('params', params); console.log('[createWebRtcTransportLayer] callback params', params);
// Send back to the client the params
callback({ params });
// send back to the client the following prameters // Set transport to producerTransport or consumerTransport
callback({ return transport;
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#TransportOptions
params
})
return transport
} catch (error) { } catch (error) {
console.log('[createWebRtcTransportLayer] ERROR', JSON.stringify(error)); console.log(`ERROR | createWebRtcTransportLayer | callId ${socketDetails[socket.id]} | ${error.message}`);
callback({ callback({ params: { error } });
params: {
error: error
}
})
} }
} }

48
build.sh Executable file
View File

@ -0,0 +1,48 @@
#/!bin/bash
## PREBUILD PROCESS
# check dist dir to be present and empty
if [ ! -d "dist" ]; then
## MAKE DIR
mkdir "dist"
echo "Directory dist created."
else
## CLEANUP
rm -fr dist/*
fi
# Install dependencies
#npm install
## PROJECT NEEDS
echo "Building app... from $(git rev-parse --abbrev-ref HEAD)"
#npm run-script build
cp -r {.env,app.js,package.json,server,public} dist/
#Add version control for pm2
cd dist
#Add version control for pm2
version=$(git describe)
file_pkg="package.json"
key=" \"version\": \""
count=$(echo ${version%%-*} | grep -o "\." | wc -l)
if (( $count > 1 )); then
version=${version%%-*}
else
version="${version%%-*}.0"
fi
if [ -f "$file_pkg" ] && [ ! -z "$version" ]; then
version=" \"version\": \"$version\","
sed -i "s|^.*$key.*|${version//\//\\/}|g" $file_pkg
text=$(cat $file_pkg | grep -c "$version")
if [ $text -eq 0 ]; then
echo "Version couldn't be set"
else
echo "Version $version successfully applied to App"
fi
fi
## POST BUILD
cd -

BIN
doc/[video] Workflow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 KiB

595
package-lock.json generated
View File

@ -12,7 +12,6 @@
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"express": "^4.18.1", "express": "^4.18.1",
"httpolyglot": "^0.1.2",
"mediasoup": "^3.10.4", "mediasoup": "^3.10.4",
"mediasoup-client": "^3.6.54", "mediasoup-client": "^3.6.54",
"parcel": "^2.7.0", "parcel": "^2.7.0",
@ -1792,27 +1791,6 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/@pm2/agent/node_modules/ws": {
"version": "7.4.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
"dev": true,
"engines": {
"node": ">=8.3.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/@pm2/io": { "node_modules/@pm2/io": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/@pm2/io/-/io-5.0.0.tgz", "resolved": "https://registry.npmjs.org/@pm2/io/-/io-5.0.0.tgz",
@ -2388,11 +2366,6 @@
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
"dev": true "dev": true
}, },
"node_modules/async-limiter": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
},
"node_modules/async-listener": { "node_modules/async-listener": {
"version": "0.6.10", "version": "0.6.10",
"resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz",
@ -2455,9 +2428,9 @@
} }
}, },
"node_modules/base64-arraybuffer": { "node_modules/base64-arraybuffer": {
"version": "0.1.5", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
"integrity": "sha512-437oANT9tP582zZMwSvZGy2nmSeAb8DW2me3y+Uv1Wp2Rulr8Mqlyrv3E7MLxmsiaPSMMDmiDVzgE+e8zlMx9g==", "integrity": "sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg==",
"engines": { "engines": {
"node": ">= 0.6.0" "node": ">= 0.6.0"
} }
@ -2483,22 +2456,11 @@
] ]
}, },
"node_modules/base64id": { "node_modules/base64id": {
"version": "1.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
"integrity": "sha512-rz8L+d/xByiB/vLVftPkyY215fqNrmasrcJsYkVcm4TgJNz+YXKrFaFAWibSaHkiKoSgMDCb+lipOIRQNGYesw==", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
"engines": { "engines": {
"node": ">= 0.4.0" "node": "^4.5.0 || >= 5.9"
}
},
"node_modules/better-assert": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
"integrity": "sha512-bYeph2DFlpK1XmGs6fvlLRUN29QISM3GBuUwSFsMY2XRx4AvC0WNCS57j4c/xGrK2RS24C1w3YoBOsw9fT46tQ==",
"dependencies": {
"callsite": "1.0.0"
},
"engines": {
"node": "*"
} }
}, },
"node_modules/binary-extensions": { "node_modules/binary-extensions": {
@ -2875,14 +2837,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/callsite": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
"integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==",
"engines": {
"node": "*"
}
},
"node_modules/callsites": { "node_modules/callsites": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@ -3051,9 +3005,9 @@
"integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw==" "integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw=="
}, },
"node_modules/component-emitter": { "node_modules/component-emitter": {
"version": "1.2.1", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA==" "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
}, },
"node_modules/component-inherit": { "node_modules/component-inherit": {
"version": "0.0.3", "version": "0.0.3",
@ -3629,36 +3583,36 @@
} }
}, },
"node_modules/engine.io": { "node_modules/engine.io": {
"version": "3.1.5", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.6.0.tgz",
"integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", "integrity": "sha512-Kc8fo5bbg8F4a2f3HPHTEpGyq/IRIQpyeHu3H1ThR14XDD7VrLcsGBo16HUpahgp8YkHJDaU5gNxJZbuGcuueg==",
"dependencies": { "dependencies": {
"accepts": "~1.3.4", "accepts": "~1.3.4",
"base64id": "1.0.0", "base64id": "2.0.0",
"cookie": "0.3.1", "cookie": "~0.4.1",
"debug": "~3.1.0", "debug": "~4.1.0",
"engine.io-parser": "~2.1.0", "engine.io-parser": "~2.2.0",
"ws": "~3.3.1" "ws": "~7.4.2"
}, },
"optionalDependencies": { "engines": {
"uws": "~9.14.0" "node": ">=8.0.0"
} }
}, },
"node_modules/engine.io-client": { "node_modules/engine.io-client": {
"version": "3.1.6", "version": "3.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.3.tgz",
"integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", "integrity": "sha512-qsgyc/CEhJ6cgMUwxRRtOndGVhIu5hpL5tR4umSpmX/MvkFoIxUTM7oFMDQumHNzlNLwSVy6qhstFPoWTf7dOw==",
"dependencies": { "dependencies": {
"component-emitter": "1.2.1", "component-emitter": "~1.3.0",
"component-inherit": "0.0.3", "component-inherit": "0.0.3",
"debug": "~3.1.0", "debug": "~3.1.0",
"engine.io-parser": "~2.1.1", "engine.io-parser": "~2.2.0",
"has-cors": "1.1.0", "has-cors": "1.1.0",
"indexof": "0.0.1", "indexof": "0.0.1",
"parseqs": "0.0.5", "parseqs": "0.0.6",
"parseuri": "0.0.5", "parseuri": "0.0.6",
"ws": "~3.3.1", "ws": "~7.4.2",
"xmlhttprequest-ssl": "~1.5.4", "xmlhttprequest-ssl": "~1.6.2",
"yeast": "0.1.2" "yeast": "0.1.2"
} }
}, },
@ -3671,33 +3625,39 @@
} }
}, },
"node_modules/engine.io-parser": { "node_modules/engine.io-parser": {
"version": "2.1.3", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz",
"integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==",
"dependencies": { "dependencies": {
"after": "0.8.2", "after": "0.8.2",
"arraybuffer.slice": "~0.0.7", "arraybuffer.slice": "~0.0.7",
"base64-arraybuffer": "0.1.5", "base64-arraybuffer": "0.1.4",
"blob": "0.0.5", "blob": "0.0.5",
"has-binary2": "~1.0.2" "has-binary2": "~1.0.2"
} }
}, },
"node_modules/engine.io/node_modules/cookie": { "node_modules/engine.io/node_modules/cookie": {
"version": "0.3.1", "version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw==", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/engine.io/node_modules/debug": { "node_modules/engine.io/node_modules/debug": {
"version": "3.1.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
"dependencies": { "dependencies": {
"ms": "2.0.0" "ms": "^2.1.1"
} }
}, },
"node_modules/engine.io/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/enquirer": { "node_modules/enquirer": {
"version": "2.3.6", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
@ -4603,14 +4563,6 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true "dev": true
}, },
"node_modules/httpolyglot": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/httpolyglot/-/httpolyglot-0.1.2.tgz",
"integrity": "sha512-ouHI1AaQMLgn4L224527S5+vq6hgvqPteurVfbm7ChViM3He2Wa8KP1Ny7pTYd7QKnDSPKcN8JYfC8r/lmsE3A==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/https-browserify": { "node_modules/https-browserify": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
@ -5758,15 +5710,11 @@
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/object-component": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
"integrity": "sha512-S0sN3agnVh2SZNEIGc0N1X4Z5K0JeFbGBrnuZpsxuUh5XLF0BnvWkMjRXo/zGKLd/eghvNIKcx1pQkmUjXIyrA=="
},
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.12.2", "version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
@ -6046,20 +5994,14 @@
} }
}, },
"node_modules/parseqs": { "node_modules/parseqs": {
"version": "0.0.5", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
"integrity": "sha512-B3Nrjw2aL7aI4TDujOzfA4NsEc4u1lVcIRE0xesutH8kjeWF70uk+W5cBlIQx04zUH9NTBvuN36Y9xLRPK6Jjw==", "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w=="
"dependencies": {
"better-assert": "~1.0.0"
}
}, },
"node_modules/parseuri": { "node_modules/parseuri": {
"version": "0.0.5", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
"integrity": "sha512-ijhdxJu6l5Ru12jF0JvzXVPvsC+VibqeaExlNoMhWN6VQ79PGjkmc7oA4W1lp00sFkNyj0fx6ivPLdV51/UMog==", "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
"dependencies": {
"better-assert": "~1.0.0"
}
}, },
"node_modules/parseurl": { "node_modules/parseurl": {
"version": "1.3.3", "version": "1.3.3",
@ -7061,16 +7003,16 @@
} }
}, },
"node_modules/socket.io": { "node_modules/socket.io": {
"version": "2.0.3", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.3.tgz", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.5.0.tgz",
"integrity": "sha512-qya7+ILKQ9vbXwJ/bUkT5Oe4RCD8c7Z9bZSg3jDDnuNxl+thkzgYz4BB+Oe8hxh1pF2xRbZUnIbrFw7+lpp94w==", "integrity": "sha512-gGunfS0od3VpwDBpGwVkzSZx6Aqo9uOcf1afJj2cKnKFAoyl16fvhpsUhmUFd4Ldbvl5JvRQed6eQw6oQp6n8w==",
"dependencies": { "dependencies": {
"debug": "~2.6.6", "debug": "~4.1.0",
"engine.io": "~3.1.0", "engine.io": "~3.6.0",
"object-assign": "~4.1.1", "has-binary2": "~1.0.2",
"socket.io-adapter": "~1.1.0", "socket.io-adapter": "~1.1.0",
"socket.io-client": "~2.0.2", "socket.io-client": "2.5.0",
"socket.io-parser": "~3.1.1" "socket.io-parser": "~3.4.0"
} }
}, },
"node_modules/socket.io-adapter": { "node_modules/socket.io-adapter": {
@ -7079,37 +7021,24 @@
"integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g=="
}, },
"node_modules/socket.io-client": { "node_modules/socket.io-client": {
"version": "2.0.3", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.3.tgz", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.5.0.tgz",
"integrity": "sha512-Lx7dCP7xCLKNXB5IB5AH37YoIjxAHLxQxXPFx0uTj9juQAayWUIwS6VS9Qn3I3eESIoQzjvsatAW1w4qb3ek9A==", "integrity": "sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw==",
"dependencies": { "dependencies": {
"backo2": "1.0.2", "backo2": "1.0.2",
"base64-arraybuffer": "0.1.5",
"component-bind": "1.0.0", "component-bind": "1.0.0",
"component-emitter": "1.2.1", "component-emitter": "~1.3.0",
"debug": "~2.6.4", "debug": "~3.1.0",
"engine.io-client": "~3.1.0", "engine.io-client": "~3.5.0",
"has-cors": "1.1.0", "has-binary2": "~1.0.2",
"indexof": "0.0.1", "indexof": "0.0.1",
"object-component": "0.0.3", "parseqs": "0.0.6",
"parseqs": "0.0.5", "parseuri": "0.0.6",
"parseuri": "0.0.5", "socket.io-parser": "~3.3.0",
"socket.io-parser": "~3.1.1",
"to-array": "0.1.4" "to-array": "0.1.4"
} }
}, },
"node_modules/socket.io-parser": { "node_modules/socket.io-client/node_modules/debug": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz",
"integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==",
"dependencies": {
"component-emitter": "1.2.1",
"debug": "~3.1.0",
"has-binary2": "~1.0.2",
"isarray": "2.0.1"
}
},
"node_modules/socket.io-parser/node_modules/debug": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
@ -7117,6 +7046,59 @@
"ms": "2.0.0" "ms": "2.0.0"
} }
}, },
"node_modules/socket.io-client/node_modules/socket.io-parser": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz",
"integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==",
"dependencies": {
"component-emitter": "~1.3.0",
"debug": "~3.1.0",
"isarray": "2.0.1"
}
},
"node_modules/socket.io-parser": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz",
"integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==",
"dependencies": {
"component-emitter": "1.2.1",
"debug": "~4.1.0",
"isarray": "2.0.1"
}
},
"node_modules/socket.io-parser/node_modules/component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA=="
},
"node_modules/socket.io-parser/node_modules/debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/socket.io-parser/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/socket.io/node_modules/debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/socket.io/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/socks": { "node_modules/socks": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz",
@ -7792,11 +7774,6 @@
"node": ">=4.2.0" "node": ">=4.2.0"
} }
}, },
"node_modules/ultron": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
},
"node_modules/umd": { "node_modules/umd": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz",
@ -7945,17 +7922,6 @@
"uuid": "dist/bin/uuid" "uuid": "dist/bin/uuid"
} }
}, },
"node_modules/uws": {
"version": "9.14.0",
"resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz",
"integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==",
"deprecated": "New code is available at github.com/uNetworking/uWebSockets.js",
"hasInstallScript": true,
"optional": true,
"engines": {
"node": ">=4"
}
},
"node_modules/v8-compile-cache": { "node_modules/v8-compile-cache": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
@ -8120,24 +8086,29 @@
"dev": true "dev": true
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "3.3.3", "version": "7.4.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
"dependencies": { "engines": {
"async-limiter": "~1.0.0", "node": ">=8.3.0"
"safe-buffer": "~5.1.0", },
"ultron": "~1.1.0" "peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
} }
}, },
"node_modules/ws/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/xmlhttprequest-ssl": { "node_modules/xmlhttprequest-ssl": {
"version": "1.5.5", "version": "1.6.3",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz",
"integrity": "sha512-/bFPLUgJrfGUL10AIv4Y7/CUt6so9CLtB/oFxQSHseSDNNCdC6vwwKEqwLN6wNPBg9YWXAiMu8jkf6RPRS/75Q==", "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==",
"engines": { "engines": {
"node": ">=0.4.0" "node": ">=0.4.0"
} }
@ -9294,13 +9265,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-7.2.3.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.2.3.tgz",
"integrity": "sha512-utbW9Z7ZxVvwiIWkdOMLOR9G/NFXh2aRucghkVrEMJWuC++r3lCkBC3LwqBinyHzGMAJxY5tn6VakZGHObq5ig==", "integrity": "sha512-utbW9Z7ZxVvwiIWkdOMLOR9G/NFXh2aRucghkVrEMJWuC++r3lCkBC3LwqBinyHzGMAJxY5tn6VakZGHObq5ig==",
"dev": true "dev": true
},
"ws": {
"version": "7.4.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
"dev": true,
"requires": {}
} }
} }
}, },
@ -9806,11 +9770,6 @@
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
"dev": true "dev": true
}, },
"async-limiter": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
},
"async-listener": { "async-listener": {
"version": "0.6.10", "version": "0.6.10",
"resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz",
@ -9861,9 +9820,9 @@
} }
}, },
"base64-arraybuffer": { "base64-arraybuffer": {
"version": "0.1.5", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
"integrity": "sha512-437oANT9tP582zZMwSvZGy2nmSeAb8DW2me3y+Uv1Wp2Rulr8Mqlyrv3E7MLxmsiaPSMMDmiDVzgE+e8zlMx9g==" "integrity": "sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg=="
}, },
"base64-js": { "base64-js": {
"version": "1.5.1", "version": "1.5.1",
@ -9872,17 +9831,9 @@
"dev": true "dev": true
}, },
"base64id": { "base64id": {
"version": "1.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
"integrity": "sha512-rz8L+d/xByiB/vLVftPkyY215fqNrmasrcJsYkVcm4TgJNz+YXKrFaFAWibSaHkiKoSgMDCb+lipOIRQNGYesw==" "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
},
"better-assert": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
"integrity": "sha512-bYeph2DFlpK1XmGs6fvlLRUN29QISM3GBuUwSFsMY2XRx4AvC0WNCS57j4c/xGrK2RS24C1w3YoBOsw9fT46tQ==",
"requires": {
"callsite": "1.0.0"
}
}, },
"binary-extensions": { "binary-extensions": {
"version": "2.2.0", "version": "2.2.0",
@ -10214,11 +10165,6 @@
"get-intrinsic": "^1.0.2" "get-intrinsic": "^1.0.2"
} }
}, },
"callsite": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
"integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ=="
},
"callsites": { "callsites": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@ -10344,9 +10290,9 @@
"integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw==" "integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw=="
}, },
"component-emitter": { "component-emitter": {
"version": "1.2.1", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA==" "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
}, },
"component-inherit": { "component-inherit": {
"version": "0.0.3", "version": "0.0.3",
@ -10830,49 +10776,53 @@
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
}, },
"engine.io": { "engine.io": {
"version": "3.1.5", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.6.0.tgz",
"integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", "integrity": "sha512-Kc8fo5bbg8F4a2f3HPHTEpGyq/IRIQpyeHu3H1ThR14XDD7VrLcsGBo16HUpahgp8YkHJDaU5gNxJZbuGcuueg==",
"requires": { "requires": {
"accepts": "~1.3.4", "accepts": "~1.3.4",
"base64id": "1.0.0", "base64id": "2.0.0",
"cookie": "0.3.1", "cookie": "~0.4.1",
"debug": "~3.1.0", "debug": "~4.1.0",
"engine.io-parser": "~2.1.0", "engine.io-parser": "~2.2.0",
"uws": "~9.14.0", "ws": "~7.4.2"
"ws": "~3.3.1"
}, },
"dependencies": { "dependencies": {
"cookie": { "cookie": {
"version": "0.3.1", "version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw==" "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
}, },
"debug": { "debug": {
"version": "3.1.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": { "requires": {
"ms": "2.0.0" "ms": "^2.1.1"
} }
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
} }
} }
}, },
"engine.io-client": { "engine.io-client": {
"version": "3.1.6", "version": "3.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.3.tgz",
"integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", "integrity": "sha512-qsgyc/CEhJ6cgMUwxRRtOndGVhIu5hpL5tR4umSpmX/MvkFoIxUTM7oFMDQumHNzlNLwSVy6qhstFPoWTf7dOw==",
"requires": { "requires": {
"component-emitter": "1.2.1", "component-emitter": "~1.3.0",
"component-inherit": "0.0.3", "component-inherit": "0.0.3",
"debug": "~3.1.0", "debug": "~3.1.0",
"engine.io-parser": "~2.1.1", "engine.io-parser": "~2.2.0",
"has-cors": "1.1.0", "has-cors": "1.1.0",
"indexof": "0.0.1", "indexof": "0.0.1",
"parseqs": "0.0.5", "parseqs": "0.0.6",
"parseuri": "0.0.5", "parseuri": "0.0.6",
"ws": "~3.3.1", "ws": "~7.4.2",
"xmlhttprequest-ssl": "~1.5.4", "xmlhttprequest-ssl": "~1.6.2",
"yeast": "0.1.2" "yeast": "0.1.2"
}, },
"dependencies": { "dependencies": {
@ -10887,13 +10837,13 @@
} }
}, },
"engine.io-parser": { "engine.io-parser": {
"version": "2.1.3", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz",
"integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==",
"requires": { "requires": {
"after": "0.8.2", "after": "0.8.2",
"arraybuffer.slice": "~0.0.7", "arraybuffer.slice": "~0.0.7",
"base64-arraybuffer": "0.1.5", "base64-arraybuffer": "0.1.4",
"blob": "0.0.5", "blob": "0.0.5",
"has-binary2": "~1.0.2" "has-binary2": "~1.0.2"
} }
@ -11558,11 +11508,6 @@
} }
} }
}, },
"httpolyglot": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/httpolyglot/-/httpolyglot-0.1.2.tgz",
"integrity": "sha512-ouHI1AaQMLgn4L224527S5+vq6hgvqPteurVfbm7ChViM3He2Wa8KP1Ny7pTYd7QKnDSPKcN8JYfC8r/lmsE3A=="
},
"https-browserify": { "https-browserify": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
@ -12447,12 +12392,8 @@
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
}, "dev": true
"object-component": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
"integrity": "sha512-S0sN3agnVh2SZNEIGc0N1X4Z5K0JeFbGBrnuZpsxuUh5XLF0BnvWkMjRXo/zGKLd/eghvNIKcx1pQkmUjXIyrA=="
}, },
"object-inspect": { "object-inspect": {
"version": "1.12.2", "version": "1.12.2",
@ -12671,20 +12612,14 @@
} }
}, },
"parseqs": { "parseqs": {
"version": "0.0.5", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
"integrity": "sha512-B3Nrjw2aL7aI4TDujOzfA4NsEc4u1lVcIRE0xesutH8kjeWF70uk+W5cBlIQx04zUH9NTBvuN36Y9xLRPK6Jjw==", "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w=="
"requires": {
"better-assert": "~1.0.0"
}
}, },
"parseuri": { "parseuri": {
"version": "0.0.5", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
"integrity": "sha512-ijhdxJu6l5Ru12jF0JvzXVPvsC+VibqeaExlNoMhWN6VQ79PGjkmc7oA4W1lp00sFkNyj0fx6ivPLdV51/UMog==", "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
"requires": {
"better-assert": "~1.0.0"
}
}, },
"parseurl": { "parseurl": {
"version": "1.3.3", "version": "1.3.3",
@ -13464,16 +13399,31 @@
"dev": true "dev": true
}, },
"socket.io": { "socket.io": {
"version": "2.0.3", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.3.tgz", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.5.0.tgz",
"integrity": "sha512-qya7+ILKQ9vbXwJ/bUkT5Oe4RCD8c7Z9bZSg3jDDnuNxl+thkzgYz4BB+Oe8hxh1pF2xRbZUnIbrFw7+lpp94w==", "integrity": "sha512-gGunfS0od3VpwDBpGwVkzSZx6Aqo9uOcf1afJj2cKnKFAoyl16fvhpsUhmUFd4Ldbvl5JvRQed6eQw6oQp6n8w==",
"requires": { "requires": {
"debug": "~2.6.6", "debug": "~4.1.0",
"engine.io": "~3.1.0", "engine.io": "~3.6.0",
"object-assign": "~4.1.1", "has-binary2": "~1.0.2",
"socket.io-adapter": "~1.1.0", "socket.io-adapter": "~1.1.0",
"socket.io-client": "~2.0.2", "socket.io-client": "2.5.0",
"socket.io-parser": "~3.1.1" "socket.io-parser": "~3.4.0"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}
} }
}, },
"socket.io-adapter": { "socket.io-adapter": {
@ -13482,34 +13432,21 @@
"integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g=="
}, },
"socket.io-client": { "socket.io-client": {
"version": "2.0.3", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.3.tgz", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.5.0.tgz",
"integrity": "sha512-Lx7dCP7xCLKNXB5IB5AH37YoIjxAHLxQxXPFx0uTj9juQAayWUIwS6VS9Qn3I3eESIoQzjvsatAW1w4qb3ek9A==", "integrity": "sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw==",
"requires": { "requires": {
"backo2": "1.0.2", "backo2": "1.0.2",
"base64-arraybuffer": "0.1.5",
"component-bind": "1.0.0", "component-bind": "1.0.0",
"component-emitter": "1.2.1", "component-emitter": "~1.3.0",
"debug": "~2.6.4",
"engine.io-client": "~3.1.0",
"has-cors": "1.1.0",
"indexof": "0.0.1",
"object-component": "0.0.3",
"parseqs": "0.0.5",
"parseuri": "0.0.5",
"socket.io-parser": "~3.1.1",
"to-array": "0.1.4"
}
},
"socket.io-parser": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz",
"integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==",
"requires": {
"component-emitter": "1.2.1",
"debug": "~3.1.0", "debug": "~3.1.0",
"engine.io-client": "~3.5.0",
"has-binary2": "~1.0.2", "has-binary2": "~1.0.2",
"isarray": "2.0.1" "indexof": "0.0.1",
"parseqs": "0.0.6",
"parseuri": "0.0.6",
"socket.io-parser": "~3.3.0",
"to-array": "0.1.4"
}, },
"dependencies": { "dependencies": {
"debug": { "debug": {
@ -13519,6 +13456,46 @@
"requires": { "requires": {
"ms": "2.0.0" "ms": "2.0.0"
} }
},
"socket.io-parser": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz",
"integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==",
"requires": {
"component-emitter": "~1.3.0",
"debug": "~3.1.0",
"isarray": "2.0.1"
}
}
}
},
"socket.io-parser": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz",
"integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==",
"requires": {
"component-emitter": "1.2.1",
"debug": "~4.1.0",
"isarray": "2.0.1"
},
"dependencies": {
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA=="
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
} }
} }
}, },
@ -14023,11 +14000,6 @@
"dev": true, "dev": true,
"peer": true "peer": true
}, },
"ultron": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
},
"umd": { "umd": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz",
@ -14138,12 +14110,6 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
}, },
"uws": {
"version": "9.14.0",
"resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz",
"integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==",
"optional": true
},
"v8-compile-cache": { "v8-compile-cache": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
@ -14273,26 +14239,15 @@
"dev": true "dev": true
}, },
"ws": { "ws": {
"version": "3.3.3", "version": "7.4.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
"requires": { "requires": {}
"async-limiter": "~1.0.0",
"safe-buffer": "~5.1.0",
"ultron": "~1.1.0"
},
"dependencies": {
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}
}
}, },
"xmlhttprequest-ssl": { "xmlhttprequest-ssl": {
"version": "1.5.5", "version": "1.6.3",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz",
"integrity": "sha512-/bFPLUgJrfGUL10AIv4Y7/CUt6so9CLtB/oFxQSHseSDNNCdC6vwwKEqwLN6wNPBg9YWXAiMu8jkf6RPRS/75Q==" "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q=="
}, },
"xregexp": { "xregexp": {
"version": "2.0.0", "version": "2.0.0",

View File

@ -5,19 +5,17 @@
"main": "app.js", "main": "app.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"start:dev": "nodemon app.ts", "start:dev": "nodemon app.js",
"start:prod": "pm2 start ./app.js -n video-server", "start:prod": "pm2 start ./app.js -n video-server",
"watch": "watchify public/index.js -o public/bundle.js -v" "watch": "watchify public/index.js -o public/bundle.js -v"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"type": "module",
"dependencies": { "dependencies": {
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"express": "^4.18.1", "express": "^4.18.1",
"httpolyglot": "^0.1.2",
"mediasoup": "^3.10.4", "mediasoup": "^3.10.4",
"mediasoup-client": "^3.6.54", "mediasoup-client": "^3.6.54",
"parcel": "^2.7.0", "parcel": "^2.7.0",

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
module.exports = { module.exports = {
hubAddress: 'https://hub.dev.linx.safemobile.com/', hubAddress: 'https://hub.dev.linx.safemobile.com/',
mediasoupAddress: 'https://video.safemobile.org/mediasoup', mediasoupAddress: 'https://video.safemobile.org',
// mediasoupAddress: 'http://localhost:3000/mediasoup',
} }

View File

@ -43,7 +43,7 @@
<tr> <tr>
<td> <td>
<div id="sharedBtns"> <div id="sharedBtns">
<video id="localVideo" autoplay class="video" ></video> <video id="localVideo" autoplay class="video" muted></video>
</div> </div>
</td> </td>
<td> <td>

View File

@ -12,145 +12,157 @@ let callId = parseInt(urlParams.get('callId')) || null;
const IS_PRODUCER = urlParams.get('producer') === 'true' ? true : false const IS_PRODUCER = urlParams.get('producer') === 'true' ? true : false
console.log('[URL] ASSET_ID', ASSET_ID, '| ACCOUNT_ID', ACCOUNT_ID, '| callId', callId, ' | IS_PRODUCER', IS_PRODUCER) console.log('[URL] ASSET_ID', ASSET_ID, '| ACCOUNT_ID', ACCOUNT_ID, '| callId', callId, ' | IS_PRODUCER', IS_PRODUCER)
let socket console.log('🟩 config', config)
hub = io(config.hubAddress)
const connectToMediasoup = () => {
socket = io(config.mediasoupAddress, {
reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax : 5000,
reconnectionAttempts: Infinity
})
socket.on('connection-success', ({ _socketId, existsProducer }) => {
console.log(`[MEDIA] ${config.mediasoupAddress} | connected: ${socket.connected} | existsProducer: ${existsProducer}`)
if (!IS_PRODUCER && existsProducer && consumer === undefined) {
goConnect()
// document.getElementById('btnRecvSendTransport').click();
}
if (IS_PRODUCER && urlParams.get('testing') === 'true') { getLocalStream() }
})
}
if (IS_PRODUCER === true) {
hub.on('connect', async () => {
console.log(`[HUB] ${config.hubAddress} | connected: ${hub.connected}`)
connectToMediasoup()
hub.emit(
'ars',
JSON.stringify({
ars: true,
asset_id: ASSET_ID,
account_id: ACCOUNT_ID,
})
)
hub.on('video', (data) => {
const parsedData = JSON.parse(data);
if (parsedData.type === 'notify-request') {
console.log('video', parsedData)
originAssetId = parsedData.origin_asset_id;
// originAssetName = parsedData.origin_asset_name;
// originAssetTypeName = parsedData.origin_asset_type_name;
callId = parsedData.video_call_id;
console.log('[VIDEO] notify-request | IS_PRODUCER', IS_PRODUCER, 'callId', callId);
getLocalStream()
}
if (parsedData.type === 'notify-end') {
console.log('[VIDEO] notify-end | IS_PRODUCER', IS_PRODUCER, 'callId', callId);
resetCallSettings()
}
})
})
hub.on('connect_error', (error) => {
console.log('connect_error', error);
});
hub.on('connection', () => {
console.log('connection')
})
hub.on('disconnect', () => {
console.log('disconnect')
})
} else {
connectToMediasoup()
}
let socket, hub
let device let device
let rtpCapabilities let rtpCapabilities
let producerTransport let producerTransport
let consumerTransport let consumerTransport
let producer let producerVideo
let producerAudio
let consumer let consumer
let originAssetId let originAssetId
// let originAssetName = 'Adi'
// let originAssetTypeName = 'linx'
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#ProducerOptions // https://mediasoup.org/documentation/v3/mediasoup-client/api/#ProducerOptions
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#transport-produce // https://mediasoup.org/documentation/v3/mediasoup-client/api/#transport-produce
let params = { let videoParams = {
// mediasoup params
encodings: [ encodings: [
{ { scaleResolutionDownBy: 4, maxBitrate: 500000 },
rid: 'r0', { scaleResolutionDownBy: 2, maxBitrate: 1000000 },
maxBitrate: 100000, { scaleResolutionDownBy: 1, maxBitrate: 5000000 },
scalabilityMode: 'S1T3', { scalabilityMode: 'S3T3_KEY' }
},
{
rid: 'r1',
maxBitrate: 300000,
scalabilityMode: 'S1T3',
},
{
rid: 'r2',
maxBitrate: 900000,
scalabilityMode: 'S1T3',
},
], ],
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#ProducerCodecOptions
codecOptions: { codecOptions: {
videoGoogleStartBitrate: 1000 videoGoogleStartBitrate: 1000
} }
} }
const streamSuccess = (stream) => { let audioParams = {
console.log('[streamSuccess]'); codecOptions :
localVideo.srcObject = stream {
const track = stream.getVideoTracks()[0] opusStereo : true,
params = { opusDtx : true
track,
...params
} }
}
setTimeout(() => {
hub = io(config.hubAddress)
const connectToMediasoup = () => {
socket = io(config.mediasoupAddress, {
reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax : 5000,
reconnectionAttempts: Infinity
})
socket.on('connection-success', ({ _socketId, existsProducer }) => {
console.log(`[MEDIA] ${config.mediasoupAddress} | connected: ${socket.connected} | existsProducer: ${existsProducer}`)
if (!IS_PRODUCER && existsProducer && consumer === undefined) {
goConnect()
// document.getElementById('btnRecvSendTransport').click();
}
if (IS_PRODUCER && urlParams.get('testing') === 'true') { getLocalStream() }
})
}
if (IS_PRODUCER === true) {
hub.on('connect', async () => {
console.log(`[HUB]! ${config.hubAddress} | connected: ${hub.connected}`)
connectToMediasoup()
hub.emit(
'ars',
JSON.stringify({
ars: true,
asset_id: ASSET_ID,
account_id: ACCOUNT_ID,
})
)
hub.on('video', (data) => {
const parsedData = JSON.parse(data);
if (parsedData.type === 'notify-request') {
console.log('video', parsedData)
originAssetId = parsedData.origin_asset_id;
// originAssetName = parsedData.origin_asset_name;
// originAssetTypeName = parsedData.origin_asset_type_name;
callId = parsedData.video_call_id;
console.log('[VIDEO] notify-request | IS_PRODUCER', IS_PRODUCER, 'callId', callId);
getLocalStream()
}
if (parsedData.type === 'notify-end') {
console.log('[VIDEO] notify-end | IS_PRODUCER', IS_PRODUCER, 'callId', callId);
resetCallSettings()
}
})
})
hub.on('connect_error', (error) => {
console.log('connect_error', error);
});
hub.on('connection', () => {
console.log('connection')
})
hub.on('disconnect', () => {
console.log('disconnect')
})
} else {
connectToMediasoup()
}
}, 1600);
const streamSuccess = (stream) => {
console.log('[streamSuccess] device', device);
localVideo.srcObject = stream
console.log('stream', stream);
const videoTrack = stream.getVideoTracks()[0]
const audioTrack = stream.getAudioTracks()[0]
videoParams = {
track: videoTrack,
...videoParams
}
audioParams = {
track: audioTrack,
...audioParams
}
console.log('[streamSuccess] videoParams', videoParams, ' | audioParams', audioParams);
goConnect() goConnect()
} }
const getLocalStream = () => { const getLocalStream = () => {
console.log('[getLocalStream]'); console.log('[getLocalStream]');
navigator.mediaDevices.getUserMedia({ navigator.mediaDevices.getUserMedia({
audio: false, audio: true,
video: { video: {
width: { qvga : { width: { ideal: 320 }, height: { ideal: 240 } },
min: 640, vga : { width: { ideal: 640 }, height: { ideal: 480 } },
max: 1920, hd : { width: { ideal: 1280 }, height: { ideal: 720 } }
},
height: {
min: 400,
max: 1080,
}
} }
}) })
.then(streamSuccess) .then(streamSuccess)
.catch(error => { .catch(error => {
console.log(error.message) console.log(error.message)
}) })
navigator.permissions.query(
{ name: 'microphone' }
).then((permissionStatus) =>{
console.log('🟨 [PERMISSION] permissionStatus', permissionStatus); // granted, denied, prompt
// It will block the code from execution and display "Permission denied" if we don't have microphone permissions
})
} }
const goConnect = () => { const goConnect = () => {
@ -167,7 +179,6 @@ const goCreateTransport = () => {
// server side to send/recive media // server side to send/recive media
const createDevice = async () => { const createDevice = async () => {
try { try {
console.log('[createDevice]');
device = new mediasoupClient.Device() device = new mediasoupClient.Device()
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#device-load // https://mediasoup.org/documentation/v3/mediasoup-client/api/#device-load
@ -178,7 +189,8 @@ const createDevice = async () => {
}) })
console.log('Device RTP Capabilities', device.rtpCapabilities) console.log('Device RTP Capabilities', device.rtpCapabilities)
console.log('[createDevice] device', device);
// once the device loads, create transport // once the device loads, create transport
goCreateTransport() goCreateTransport()
@ -207,18 +219,20 @@ const getRtpCapabilities = () => {
} }
const createSendTransport = () => { const createSendTransport = () => {
console.log('[createSendTransport');
// see server's socket.on('createWebRtcTransport', sender?, ...) // see server's socket.on('createWebRtcTransport', sender?, ...)
// this is a call from Producer, so sender = true // this is a call from Producer, so sender = true
socket.emit('createWebRtcTransport', { sender: true, callId }, ({ params }) => { socket.emit('createWebRtcTransport', { sender: true, callId }, (value) => {
console.log(`[createWebRtcTransport] value: ${JSON.stringify(value)}`);
const params = value.params;
// The server sends back params needed // The server sends back params needed
// to create Send Transport on the client side // to create Send Transport on the client side
if (params.error) { if (params.error) {
console.log(params.error) console.log(params.error)
return return
} }
console.log(params)
// creates a new WebRTC Transport to send media // creates a new WebRTC Transport to send media
// based on the server's producer transport params // based on the server's producer transport params
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#TransportOptions // https://mediasoup.org/documentation/v3/mediasoup-client/api/#TransportOptions
@ -244,10 +258,10 @@ const createSendTransport = () => {
}) })
producerTransport.on('produce', async (parameters, callback, errback) => { producerTransport.on('produce', async (parameters, callback, errback) => {
console.log(parameters) console.log('[produce] parameters', parameters)
try { try {
// tell the server to create a Producer // Tell the server to create a Producer
// with the following parameters and produce // with the following parameters and produce
// and expect back a server side producer id // and expect back a server side producer id
// see server's socket.on('transport-produce', ...) // see server's socket.on('transport-produce', ...)
@ -270,20 +284,42 @@ const createSendTransport = () => {
} }
const connectSendTransport = async () => { const connectSendTransport = async () => {
// we now call produce() to instruct the producer transport
console.log('[connectSendTransport] producerTransport');
// We now call produce() to instruct the producer transport
// to send media to the Router // to send media to the Router
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#transport-produce // https://mediasoup.org/documentation/v3/mediasoup-client/api/#transport-produce
// this action will trigger the 'connect' and 'produce' events above // this action will trigger the 'connect' and 'produce' events above
producer = await producerTransport.produce(params)
// Produce video
producerVideo = await producerTransport.produce(videoParams)
console.log('videoParams', videoParams);
console.log('producerVideo', producerVideo);
producer.on('trackended', () => { producerVideo.on('trackended', () => {
console.log('track ended') console.log('track ended')
// close video track // close video track
}) })
producer.on('transportclose', () => { producerVideo.on('transportclose', () => {
console.log('transport ended') console.log('transport ended')
// close video track // close video track
})
// Produce audio
producerAudio = await producerTransport.produce(audioParams)
console.log('audioParams', audioParams);
console.log('producerAudio', producerAudio);
producerAudio.on('trackended', () => {
console.log('track ended')
// close audio track
})
producerAudio.on('transportclose', () => {
console.log('transport ended')
// close audio track
}) })
const answer = { const answer = {
@ -294,7 +330,7 @@ const connectSendTransport = async () => {
origin_asset_type_name: ASSET_TYPE, origin_asset_type_name: ASSET_TYPE,
origin_asset_name: ASSET_NAME, origin_asset_name: ASSET_NAME,
video_call_id: callId, video_call_id: callId,
answer: 'accepted', // answer: 'rejected' answer: 'accepted', // answer: accepted/rejected
}; };
console.log('SEND answer', answer); console.log('SEND answer', answer);
@ -310,7 +346,7 @@ const connectSendTransport = async () => {
const createRecvTransport = async () => { const createRecvTransport = async () => {
console.log('createRecvTransport'); console.log('createRecvTransport');
// see server's socket.on('consume', sender?, ...) // See server's socket.on('consume', sender?, ...)
// this is a call from Consumer, so sender = false // this is a call from Consumer, so sender = false
await socket.emit('createWebRtcTransport', { sender: false, callId }, ({ params }) => { await socket.emit('createWebRtcTransport', { sender: false, callId }, ({ params }) => {
// The server sends back params needed // The server sends back params needed
@ -320,15 +356,15 @@ const createRecvTransport = async () => {
return return
} }
console.log(params) console.log('[createRecvTransport] params', params)
// creates a new WebRTC Transport to receive media // Creates a new WebRTC Transport to receive media
// based on server's consumer transport params // based on server's consumer transport params
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#device-createRecvTransport // https://mediasoup.org/documentation/v3/mediasoup-client/api/#device-createRecvTransport
consumerTransport = device.createRecvTransport(params) consumerTransport = device.createRecvTransport(params)
// https://mediasoup.org/documentation/v3/communication-between-client-and-server/#producing-media // https://mediasoup.org/documentation/v3/communication-between-client-and-server/#producing-media
// this event is raised when a first call to transport.produce() is made // This event is raised when a first call to transport.produce() is made
// see connectRecvTransport() below // see connectRecvTransport() below
consumerTransport.on('connect', async ({ dtlsParameters }, callback, errback) => { consumerTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
try { try {
@ -353,7 +389,8 @@ const resetCallSettings = () => {
localVideo.srcObject = null localVideo.srcObject = null
remoteVideo.srcObject = null remoteVideo.srcObject = null
consumer = null consumer = null
producer = null producerVideo = null
producerAudio = null
producerTransport = null producerTransport = null
consumerTransport = null consumerTransport = null
device = undefined device = undefined
@ -361,7 +398,7 @@ const resetCallSettings = () => {
const connectRecvTransport = async () => { const connectRecvTransport = async () => {
console.log('connectRecvTransport'); console.log('connectRecvTransport');
// for consumer, we need to tell the server first // For consumer, we need to tell the server first
// to create a consumer based on the rtpCapabilities and consume // to create a consumer based on the rtpCapabilities and consume
// if the router can consume, it will send back a set of params as below // if the router can consume, it will send back a set of params as below
await socket.emit('consume', { await socket.emit('consume', {
@ -373,7 +410,7 @@ const connectRecvTransport = async () => {
return return
} }
// then consume with the local consumer transport // Then consume with the local consumer transport
// which creates a consumer // which creates a consumer
consumer = await consumerTransport.consume({ consumer = await consumerTransport.consume({
id: params.id, id: params.id,
@ -416,6 +453,7 @@ const closeCall = () => {
resetCallSettings() resetCallSettings()
} }
btnLocalVideo.addEventListener('click', getLocalStream) btnLocalVideo.addEventListener('click', getLocalStream)
btnRecvSendTransport.addEventListener('click', goConnect) btnRecvSendTransport.addEventListener('click', goConnect)
btnCloseCall.addEventListener('click', closeCall) btnCloseCall.addEventListener('click', closeCall)