Ошибка — transports.recv.Состояние соединения застряло в новом статусе — Mediasoup (3.7)

#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. Я застрял с этой ошибкой на довольно долгое время. Любая помощь будет признательна. Заранее спасибо.