Router cannot consume producer data

Hi, I have a problem where my router.canConsume(data) is returning false. I read the two threads UnsupportedError: cannot consume this Producer and the other one but they did not help me at all to find the cause of the problem.

async function createConsumer(socket, transport, producer, rtpCapabilities) {
  const router = getRoom(socket).router;
  console.log("Room router:", router);
  console.log("Create Consumer Producer:", producer);
  console.log("Create Consumer RTP Capabilities:", rtpCapabilities);
  const data = { producerId: producer.id, rtpCapabilities };
  if (!router.canConsume(data)) {
    console.error('can not consume');
    return;
  }
  // ...

I am following the code of this example project mkhahani/ mediasoup-sample-app but my app is written in Vue.js. I keep double checking and cross checking my own code with his and I can’t seem to figure out why my router cannot consume but his can (I ran the project in my own machine and it works).

I also compared our producer and rtpCapabilities objects and they are almost exactly the same (the producers are slightly different but the rtpCapabilities are exactly the same).

Here is my rtpCapabilities object:

{ codecs:
   [ { mimeType: 'audio/opus',
       kind: 'audio',
       preferredPayloadType: 100,
       clockRate: 48000,
       channels: 2,
       parameters: [Object],
       rtcpFeedback: [Array] },
     { mimeType: 'video/VP8',
       kind: 'video',
       preferredPayloadType: 101,
       clockRate: 90000,
       parameters: {},
       rtcpFeedback: [Array] },
     { mimeType: 'video/rtx',
       kind: 'video',
       preferredPayloadType: 102,
       clockRate: 90000,
       parameters: [Object],
       rtcpFeedback: [] } ],
  headerExtensions:
   [ { kind: 'audio',
       uri: 'urn:ietf:params:rtp-hdrext:sdes:mid',
       preferredId: 1,
       preferredEncrypt: false,
       direction: 'sendrecv' },
     { kind: 'video',
       uri: 'urn:ietf:params:rtp-hdrext:sdes:mid',
       preferredId: 1,
       preferredEncrypt: false,
       direction: 'sendrecv' },
     { kind: 'audio',
       uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
       preferredId: 4,
       preferredEncrypt: false,
       direction: 'sendrecv' },
     { kind: 'video',
       uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
       preferredId: 4,
       preferredEncrypt: false,
       direction: 'sendrecv' },
     { kind: 'video',
       uri:
        'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01',
       preferredId: 5,
       preferredEncrypt: false,
       direction: 'sendrecv' },
     { kind: 'video',
       uri:
        'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07',
       preferredId: 6,
       preferredEncrypt: false,
       direction: 'sendrecv' },
     { kind: 'audio',
       uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level',
       preferredId: 10,
       preferredEncrypt: false,
       direction: 'sendrecv' },
     { kind: 'video',
       uri: 'urn:3gpp:video-orientation',
       preferredId: 11,
       preferredEncrypt: false,
       direction: 'sendrecv' },
     { kind: 'video',
       uri: 'urn:ietf:params:rtp-hdrext:toffset',
       preferredId: 12,
       preferredEncrypt: false,
       direction: 'sendrecv' } ] }
{
  "codecs": [
    {
      "mimeType": "audio/opus",
      "payloadType": 111,
      "clockRate": 48000,
      "channels": 2,
      "parameters": {
        "minptime": 10,
        "useinbandfec": 1
      },
      "rtcpFeedback": [
        {
          "type": "transport-cc",
          "parameter": ""
        }
      ]
    }
  ],
  "headerExtensions": [
    {
      "uri": "urn:ietf:params:rtp-hdrext:sdes:mid",
      "id": 4,
      "encrypt": false,
      "parameters": {}
    },
    {
      "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
      "id": 2,
      "encrypt": false,
      "parameters": {}
    },
    {
      "uri": "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
      "id": 3,
      "encrypt": false,
      "parameters": {}
    },
    {
      "uri": "urn:ietf:params:rtp-hdrext:ssrc-audio-level",
      "id": 1,
      "encrypt": false,
      "parameters": {}
    }
  ],
  "encodings": [
    {
      "ssrc": 12338707,
      "dtx": false
    }
  ],
  "rtcp": {
    "cname": "rezabl/mISmZX+wr",
    "reducedSize": true
  },
  "mid": "1"
}

Where did you get those rtpCapabilities from? Do their preferredPayloadType values match those in router.rtpCapabilities?

I get the rtpCapabilities from my server via Socket.io with this request:

    socket.on("getRouterRtpCapabilities", (data, callback) => {
      if (defaultRoom.router) {
        callback(null, defaultRoom.router.rtpCapabilities);
      } else {
        callback({ text: "ERROR - Router not ready" }, null);
      }
    });

And the room object is created like this:

async function startWorker() {
  // const mediaCodecs = config.mediasoup.routerOptions.mediaCodecs;
  worker = await mediasoup.createWorker();
  defaultRoom = await setupRoom("_default_room");
  console.log("-- mediasoup worker start. -- room:", defaultRoom.name);
}
async function setupRoom(name) {
  console.log(`--- Creating new room. roomId=${name}`);
  const room = new Room(name);
  const mediaCodecs = config.mediasoup.routerOptions.mediaCodecs;
  console.log("media codecs:", mediaCodecs);
  const router = await worker.createRouter({ mediaCodecs });
  router.roomname = name;

  router.observer.on("close", () => {
    console.log("-- router closed. room=%s", name);
  });

  router.observer.on("newtransport", transport => {
    console.log("-- router newtransport. room=%s", name);
  });

  room.router = router;
  Room.addRoom(room, name);
  return room;
}

mediaCodecs:

// mediasoup Router options.
    // See https://mediasoup.org/documentation/v3/mediasoup/api/#RouterOptions
    routerOptions:
    {
      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/VP9',
          //   clockRate: 90000,
          //   parameters:
          //   {
          //     'profile-id': 2,
          //     '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
          //   }
          // }
        ]
    },

I’m afraid that’s not answering my question. I asked about the endpoint’s rtpCapabilities. Please don’t share all your code, I’m just asking about those rtpCapabilities.

This is the consumer’s device’s rtpCapabilities

{
  "codecs": [
    {
      "mimeType": "audio/opus",
      "kind": "audio",
      "preferredPayloadType": 100,
      "clockRate": 48000,
      "channels": 2,
      "parameters": {
        "minptime": 10,
        "useinbandfec": 1
      },
      "rtcpFeedback": [
        {
          "type": "transport-cc",
          "parameter": ""
        }
      ]
    },
    {
      "mimeType": "video/VP8",
      "kind": "video",
      "preferredPayloadType": 101,
      "clockRate": 90000,
      "parameters": {},
      "rtcpFeedback": [
        {
          "type": "goog-remb",
          "parameter": ""
        },
        {
          "type": "transport-cc",
          "parameter": ""
        },
        {
          "type": "ccm",
          "parameter": "fir"
        },
        {
          "type": "nack",
          "parameter": ""
        },
        {
          "type": "nack",
          "parameter": "pli"
        }
      ]
    },
    {
      "mimeType": "video/rtx",
      "kind": "video",
      "preferredPayloadType": 102,
      "clockRate": 90000,
      "parameters": {
        "apt": 101
      },
      "rtcpFeedback": []
    }
  ],
  "headerExtensions": [
    {
      "kind": "audio",
      "uri": "urn:ietf:params:rtp-hdrext:sdes:mid",
      "preferredId": 1,
      "preferredEncrypt": false,
      "direction": "sendrecv"
    },
    {
      "kind": "video",
      "uri": "urn:ietf:params:rtp-hdrext:sdes:mid",
      "preferredId": 1,
      "preferredEncrypt": false,
      "direction": "sendrecv"
    },
    {
      "kind": "audio",
      "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
      "preferredId": 4,
      "preferredEncrypt": false,
      "direction": "sendrecv"
    },
    {
      "kind": "video",
      "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
      "preferredId": 4,
      "preferredEncrypt": false,
      "direction": "sendrecv"
    },
    {
      "kind": "video",
      "uri": "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
      "preferredId": 5,
      "preferredEncrypt": false,
      "direction": "sendrecv"
    },
    {
      "kind": "video",
      "uri": "http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07",
      "preferredId": 6,
      "preferredEncrypt": false,
      "direction": "sendrecv"
    },
    {
      "kind": "audio",
      "uri": "urn:ietf:params:rtp-hdrext:ssrc-audio-level",
      "preferredId": 10,
      "preferredEncrypt": false,
      "direction": "sendrecv"
    },
    {
      "kind": "video",
      "uri": "urn:3gpp:video-orientation",
      "preferredId": 11,
      "preferredEncrypt": false,
      "direction": "sendrecv"
    },
    {
      "kind": "video",
      "uri": "urn:ietf:params:rtp-hdrext:toffset",
      "preferredId": 12,
      "preferredEncrypt": false,
      "direction": "sendrecv"
    }
  ]
}

The preferred payload types seem to be the same for the router and this device. It has three preferredPayloadType attributes 100, 101, 102.

I don’t see any reason for canConsume() return false in your scenario, but this is not a bug in mediasoup obviously so just review your code, please.

When my producer transport emits the produce event I checked the rtpParameters and the payloadType is different (96, 97, 111), does this have implications for my problem?

Adding Producer(id=41508d14-69bf-4f0d-894c-09900cf3c2b5) for socket.id=FLSLdounp-Q1XLvPAAAC, kind=video
rtpParameters: { codecs:
   [ { mimeType: 'video/VP8',
       payloadType: 96,
       clockRate: 90000,
       parameters: {},
       rtcpFeedback: [Array] },
     { mimeType: 'video/rtx',
       payloadType: 97,
       clockRate: 90000,
       parameters: [Object],
       rtcpFeedback: [] } ],
Adding Producer(id=209f5f2a-268c-4a45-967b-18f385d00c45) for socket.id=FLSLdounp-Q1XLvPAAAC, kind=audio
rtpParameters: { codecs:
   [ { mimeType: 'audio/opus',
       payloadType: 111,
       clockRate: 48000,
       channels: 2,
       parameters: [Object],
       rtcpFeedback: [Array] } ],

No, that’s ok.

Thanks for the help, I found my mistakes. The cause is really just mistakes in my code.

Hey, do you happen to remember what precisely was the mistake in your code? I’m in a similar situation as you right now, with canConsume failing occasionally and I’m wondering why it does.