#node.js #webrtc #mediasoup
Вопрос:
Попытка развертывания https://github.com/fmeringdal/nettu-meet который использует библиотеку mediasoup. Опробованы версии Medisoup 3.7 и 3.8
Когда пользователь включает свое видео или аудио в конференц-зале, на консоли появляется сообщение «новое транспортное соединение», а затем оно остается в этом состоянии.
Вот фрагмент кода, который выводит приведенный выше вывод.
signalingChannel.on("newConsumer", async (data: any) => {
const { joined } = useRoomStore.getState();
if (!joined) return;
const {
peerId,
producerId,
id,
kind,
rtpParameters,
type,
appData,
producerPaused,
} = data;
console.log('*************', 'utils.ts - temp log to check rtpParameters, **************')
console.log(data)
console.log(rtpParameters)
const { transports } = useTransportStore.getState();
if (!transports) return;
const consumer = await transports.recv.consume({
id,
producerId,
kind,
rtpParameters,
appData: { ...appData, peerId }, // Trick.
});
useRoomStore.getState().addConsumer(consumer);
// the server-side consumer will be started in paused state. wait
// until we're connected, then send a resume request to the server
// to get our first keyframe and start displaying video
while (transports.recv.connectionState !== "connected") {
log(" transport connstate", transports.recv.connectionState);
await sleep(100);
}
if (!producerPaused) {
// okay, we're ready. let's ask the peer to send us media
await resumeConsumer(consumer.id);
} else {
await pauseConsumer(consumer.id);
}
consumer.on("transportclose", () => {
closeConsumer(consumer.id);
});
Прикрепление ниже параметров, связанных с транспортом, на случай, если это поможет.
Когда первый пользователь присоединяется, я получаю эти параметры транспорта на клиенте.
{
"id": "2c2239b1-18e3-478c-86f3-5e3bfd31941d",
"iceParameters": {
"iceLite": true,
"password": "v128uo3o9ixphketku7pz9gtu7222lr6",
"usernameFragment": "a4t3lzi3o50ckvxw"
},
"iceCandidates": [
{
"foundation": "udpcandidate",
"ip": "0.0.0.0",
"port": 44449,
"priority": 1076558079,
"protocol": "udp",
"type": "host"
},
{
"foundation": "tcpcandidate",
"ip": "0.0.0.0",
"port": 47212,
"priority": 1076302079,
"protocol": "tcp",
"tcpType": "passive",
"type": "host"
}
],
"dtlsParameters": {
"fingerprints": [
{
"algorithm": "sha-1",
"value": "7B:A7:5D:F1:A6:EA:72:83:4B:83:21:E2:7A:8D:A1:B1:A4:8B:A6:87"
},
{
"algorithm": "sha-224",
"value": "8A:E5:5F:5C:30:34:BD:D4:75:52:B5:0A:28:1C:5C:11:6B:84:01:5F:FE:72:82:BA:C9:6F:B6:63"
},
{
"algorithm": "sha-256",
"value": "CC:D8:6A:94:DA:71:27:45:FB:1B:32:88:2C:5C:1C:26:94:6E:BF:84:47:CA:FE:41:53:5B:D7:36:D5:66:42:A0"
},
{
"algorithm": "sha-384",
"value": "FF:25:F0:2F:A5:CF:C4:D8:9E:A1:4F:D5:47:44:98:25:BE:30:12:71:53:AB:61:D1:D1:78:BA:96:65:75:7B:A5:3B:94:49:9F:61:DA:B1:C6:B9:FF:57:41:1F:2B:78:65"
},
{
"algorithm": "sha-512",
"value": "7F:D3:E0:C6:1B:D1:AB:1F:A3:35:72:7D:9C:24:91:62:BF:A0:5E:A8:1F:EE:F0:9A:1D:05:37:AD:78:B9:E8:8E:42:6E:F9:09:4B:A5:B4:66:23:26:A1:A8:DE:08:85:27:0B:3C:60:90:89:FD:3D:1F:30:73:81:F7:35:49:7D:F5"
}
],
"role": "auto"
}
}
{
"id": "5485ff92-9bd2-4f74-9c5f-9c1873cbaedb",
"iceParameters": {
"iceLite": true,
"password": "hv1nyjohkworxcrpm0icbcd29hdcy98e",
"usernameFragment": "cesy56bc7zfqg3uk"
},
"iceCandidates": [
{
"foundation": "udpcandidate",
"ip": "0.0.0.0",
"port": 41434,
"priority": 1076558079,
"protocol": "udp",
"type": "host"
},
{
"foundation": "tcpcandidate",
"ip": "0.0.0.0",
"port": 44080,
"priority": 1076302079,
"protocol": "tcp",
"tcpType": "passive",
"type": "host"
}
],
"dtlsParameters": {
"fingerprints": [
{
"algorithm": "sha-1",
"value": "7B:A7:5D:F1:A6:EA:72:83:4B:83:21:E2:7A:8D:A1:B1:A4:8B:A6:87"
},
{
"algorithm": "sha-224",
"value": "8A:E5:5F:5C:30:34:BD:D4:75:52:B5:0A:28:1C:5C:11:6B:84:01:5F:FE:72:82:BA:C9:6F:B6:63"
},
{
"algorithm": "sha-256",
"value": "CC:D8:6A:94:DA:71:27:45:FB:1B:32:88:2C:5C:1C:26:94:6E:BF:84:47:CA:FE:41:53:5B:D7:36:D5:66:42:A0"
},
{
"algorithm": "sha-384",
"value": "FF:25:F0:2F:A5:CF:C4:D8:9E:A1:4F:D5:47:44:98:25:BE:30:12:71:53:AB:61:D1:D1:78:BA:96:65:75:7B:A5:3B:94:49:9F:61:DA:B1:C6:B9:FF:57:41:1F:2B:78:65"
},
{
"algorithm": "sha-512",
"value": "7F:D3:E0:C6:1B:D1:AB:1F:A3:35:72:7D:9C:24:91:62:BF:A0:5E:A8:1F:EE:F0:9A:1D:05:37:AD:78:B9:E8:8E:42:6E:F9:09:4B:A5:B4:66:23:26:A1:A8:DE:08:85:27:0B:3C:60:90:89:FD:3D:1F:30:73:81:F7:35:49:7D:F5"
}
],
"role": "auto"
}
}
When the second user joins the meet room, I am getting these transport options on the client.
{
"id": "4abfb816-734a-4b66-a860-2dd88fd95f8a",
"iceParameters": {
"iceLite": true,
"password": "ze87is9bl32vwx0ko7d8v1qgm0fk1u9h",
"usernameFragment": "alrip3oyoaluv83n"
},
"iceCandidates": [
{
"foundation": "udpcandidate",
"ip": "0.0.0.0",
"port": 41783,
"priority": 1076558079,
"protocol": "udp",
"type": "host"
},
{
"foundation": "tcpcandidate",
"ip": "0.0.0.0",
"port": 45051,
"priority": 1076302079,
"protocol": "tcp",
"tcpType": "passive",
"type": "host"
}
],
"dtlsParameters": {
"fingerprints": [
{
"algorithm": "sha-1",
"value": "7B:A7:5D:F1:A6:EA:72:83:4B:83:21:E2:7A:8D:A1:B1:A4:8B:A6:87"
},
{
"algorithm": "sha-224",
"value": "8A:E5:5F:5C:30:34:BD:D4:75:52:B5:0A:28:1C:5C:11:6B:84:01:5F:FE:72:82:BA:C9:6F:B6:63"
},
{
"algorithm": "sha-256",
"value": "CC:D8:6A:94:DA:71:27:45:FB:1B:32:88:2C:5C:1C:26:94:6E:BF:84:47:CA:FE:41:53:5B:D7:36:D5:66:42:A0"
},
{
"algorithm": "sha-384",
"value": "FF:25:F0:2F:A5:CF:C4:D8:9E:A1:4F:D5:47:44:98:25:BE:30:12:71:53:AB:61:D1:D1:78:BA:96:65:75:7B:A5:3B:94:49:9F:61:DA:B1:C6:B9:FF:57:41:1F:2B:78:65"
},
{
"algorithm": "sha-512",
"value": "7F:D3:E0:C6:1B:D1:AB:1F:A3:35:72:7D:9C:24:91:62:BF:A0:5E:A8:1F:EE:F0:9A:1D:05:37:AD:78:B9:E8:8E:42:6E:F9:09:4B:A5:B4:66:23:26:A1:A8:DE:08:85:27:0B:3C:60:90:89:FD:3D:1F:30:73:81:F7:35:49:7D:F5"
}
],
"role": "auto"
}
}
{
"id": "6f2e2284-2468-4a79-928b-b044765a6777",
"iceParameters": {
"iceLite": true,
"password": "b2tjomcqdmno3bjig7q85rpr2jwd4s8j",
"usernameFragment": "eho67d7lw16nee2l"
},
"iceCandidates": [
{
"foundation": "udpcandidate",
"ip": "0.0.0.0",
"port": 48942,
"priority": 1076558079,
"protocol": "udp",
"type": "host"
},
{
"foundation": "tcpcandidate",
"ip": "0.0.0.0",
"port": 49477,
"priority": 1076302079,
"protocol": "tcp",
"tcpType": "passive",
"type": "host"
}
],
"dtlsParameters": {
"fingerprints": [
{
"algorithm": "sha-1",
"value": "7B:A7:5D:F1:A6:EA:72:83:4B:83:21:E2:7A:8D:A1:B1:A4:8B:A6:87"
},
{
"algorithm": "sha-224",
"value": "8A:E5:5F:5C:30:34:BD:D4:75:52:B5:0A:28:1C:5C:11:6B:84:01:5F:FE:72:82:BA:C9:6F:B6:63"
},
{
"algorithm": "sha-256",
"value": "CC:D8:6A:94:DA:71:27:45:FB:1B:32:88:2C:5C:1C:26:94:6E:BF:84:47:CA:FE:41:53:5B:D7:36:D5:66:42:A0"
},
{
"algorithm": "sha-384",
"value": "FF:25:F0:2F:A5:CF:C4:D8:9E:A1:4F:D5:47:44:98:25:BE:30:12:71:53:AB:61:D1:D1:78:BA:96:65:75:7B:A5:3B:94:49:9F:61:DA:B1:C6:B9:FF:57:41:1F:2B:78:65"
},
{
"algorithm": "sha-512",
"value": "7F:D3:E0:C6:1B:D1:AB:1F:A3:35:72:7D:9C:24:91:62:BF:A0:5E:A8:1F:EE:F0:9A:1D:05:37:AD:78:B9:E8:8E:42:6E:F9:09:4B:A5:B4:66:23:26:A1:A8:DE:08:85:27:0B:3C:60:90:89:FD:3D:1F:30:73:81:F7:35:49:7D:F5"
}
],
"role": "auto"
}
}
Below is the data being sent from the server which is used in code snippet pasted above when newConsumer event happens.
{
"peerId": "VZwCYhzUbcjc9nLiAAAJ",
"producerId": "c673fb19-7b32-44f9-b45d-43355a193277",
"id": "48ba5d06-942d-47ca-aaf6-3985a22de91b",
"kind": "video",
"rtpParameters": {
"codecs": [
{
"mimeType": "video/VP8",
"payloadType": 101,
"clockRate": 90000,
"parameters": {},
"rtcpFeedback": [
{
"type": "nack",
"parameter": ""
},
{
"type": "nack",
"parameter": "pli"
},
{
"type": "ccm",
"parameter": "fir"
},
{
"type": "transport-cc",
"parameter": ""
}
]
},
{
"mimeType": "video/rtx",
"payloadType": 102,
"clockRate": 90000,
"parameters": {
"apt": 101
},
"rtcpFeedback": []
}
],
"headerExtensions": [
{
"uri": "urn:ietf:params:rtp-hdrext:sdes:mid",
"id": 1,
"encrypt": false,
"parameters": {}
},
{
"uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
"id": 4,
"encrypt": false,
"parameters": {}
},
{
"uri": "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
"id": 5,
"encrypt": false,
"parameters": {}
},
{
"uri": "http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07",
"id": 6,
"encrypt": false,
"parameters": {}
},
{
"uri": "urn:ietf:params:rtp-hdrext:framemarking",
"id": 7,
"encrypt": false,
"parameters": {}
},
{
"uri": "urn:3gpp:video-orientation",
"id": 11,
"encrypt": false,
"parameters": {}
},
{
"uri": "urn:ietf:params:rtp-hdrext:toffset",
"id": 12,
"encrypt": false,
"parameters": {}
}
],
"encodings": [
{
"ssrc": 306981400,
"rtx": {
"ssrc": 306981401
}
}
],
"rtcp": {
"cname": "jjCf7Ex05NUeAQBn",
"reducedSize": true,
"mux": true
},
"mid": "0"
},
"type": "simple",
"appData": {
"mediaTag": "webcam",
"peerId": "VZwCYhzUbcjc9nLiAAAJ",
"transportId": "2c2239b1-18e3-478c-86f3-5e3bfd31941d"
},
"producerPaused": false
}
Deployment infra info.
Frontend and backend are deployed as docker containers along with nginx on aws multi docker container .
For testing purposes I opened up all tcp and udp ports on the load balancer as well as the ec2 instance.
Frontend Docker File
FROM nginx
WORKDIR /usr/share/nginx/html
RUN rm -rf ./*
COPY build/ .
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 3000
CMD ["nginx", "-g", "daemon off;"]
Backend Docker File
FROM node:14.15.4
# Install DEB dependencies and others.
RUN
set -x
amp;amp; apt-get update
amp;amp; apt-get install -y net-tools build-essential valgrind
WORKDIR /app
COPY package*.json ./
COPY tsconfig.json .
COPY src src
RUN npm install
EXPOSE 5000
EXPOSE 40000-49999
CMD ["npm", "run", "start:prod]
Nginx Docker File
FROM nginx
EXPOSE 80
RUN rm /usr/share/nginx/html/*
COPY configs/default.conf /etc/nginx/conf.d/default.conf
CMD [ "nginx", "-g", "daemon off;" ]
Https is enabled on the load balancer and node server is running as a http server.
Below is the mediasoup config file
export const config = {
// http server ip, port, and peer timeout constant
//
httpIp: '0.0.0.0',
httpPort: 5000,
httpPeerStale: 15000,
// ssl certs. we'll start as http instead of https if we don't have
// these
sslCrt: 'local.crt', // is not being used
sslKey: 'local.key',
mediasoup: {
worker: {
rtcMinPort: 40000,
rtcMaxPort: 49999,
logLevel: 'debug',
logTags: [
'info',
'ice',
'dtls',
'rtp',
'srtp',
'rtcp',
// 'rtx',
// 'bwe',
// 'score',
// 'simulcast',
// 'svc'
],
} as WorkerSettings,
router: {
mediaCodecs: [
{
kind: 'audio',
mimeType: 'audio/opus',
clockRate: 48000,
channels: 2,
},
{
kind: 'video',
mimeType: 'video/VP8',
clockRate: 90000,
parameters: {
// 'x-google-start-bitrate': 1000
},
},
{
kind: 'video',
mimeType: 'video/h264',
clockRate: 90000,
parameters: {
'packetization-mode': 1,
'profile-level-id': '4d0032',
'level-asymmetry-allowed': 1,
// 'x-google-start-bitrate' : 1000
},
},
{
kind: 'video',
mimeType: 'video/h264',
clockRate: 90000,
parameters: {
'packetization-mode': 1,
'profile-level-id': '42e01f',
'level-asymmetry-allowed': 1,
// 'x-google-start-bitrate' : 1000
},
},
] as RtpCodecCapability[],
},
// rtp listenIps are the most important thing, below. you'll need
// to set these appropriately for your network for the demo to
// run anywhere but on localhost
webRtcTransport: {
listenIps: [
{
ip: process.env.LISTEN_IP,
announcedIp: process.env.ANNOUNCEMENT_IP,
},
// { ip: '127.0.0.1', announcedIp: '192.168.65.1' },
// { ip: '172.17.0.1', announcedIp: undefined },
// { ip: '127.0.0.1', announcedIp: '192.168.1.34' },
// { ip: "192.168.42.68", announcedIp: null },
// { ip: '10.10.23.101', announcedIp: null },
] as TransportListenIp[],
initialAvailableOutgoingBitrate: 800000,
},
},
};
Ip is set to 0.0.0.0 and announcedIp is set to the public ip of the ec2 instance.
EDIT
Changed docker-compose to run the containers on host network_mode as shown below:
version: "3.9"
services:
client:
image: client_image_url
container_name: client
network_mode: host
restart: always
backend:
image: backend_image_url
container_name: backend
env_file: .env
network_mode: host
restart: always
nginx:
image: nginx_network_mode
depends_on:
- client
- backend
network_mode: host
restart: always
Ip-адрес установлен на частный ip экземпляра ec2, а объявленный IP-адрес установлен на общедоступный ip экземпляра ec2.
Теперь состояние transports.recv.ConnectionState переходит в состояние подключения и через некоторое время отключается.
Я новичок в Webrtc и mediasoup. Я застрял с этой ошибкой на довольно долгое время. Любая помощь будет признательна. Заранее спасибо.