mediasoup-client not working on Firefox

Hi there,
I’m trying to get mediasoup-client running on Firefox. It works fine on chrome, but with firefox, I get the following error message when trying to consume:

failed to consume [error: Error: "new transceiver not found"
    receive Firefox60.js:513
 ]

Any ideas?

Which FF version are you using?

It does not fail in the mediasoup-demo so it may be something wrong in your code, and it’s not possible to help with such a short description.

I’ve tested with FF 69, 70, etc. The current version I’m testing (the latest version) is 70.0.1. @ibc it’s working fine in Chrome, Safari, etc, as well, and I know it’s not possible to help with just a simple error message haha. Just wanted to know if you’ve seen something like that before. Are there any specific kinds of things I should look at to try and figure out what’s going?

As @ibc stated the mediasoup-demo works with FF too, so it’s an error on your side. You need to check your code by following the error your are getting.

There is lot of stats, logs and documentation in mediasoup. “It does not work in Firefox” is not a proper issue report, sorry. I cannot tell you what exactly to check.

BTW we have just fixed a bug in mediasoup “devel” branch that may affect Firefox on receiving. However we don’t even know if you were using mediasoup “devel” branch or the latest mediasoup NPM version.

Hmm, I’ll try the devel branch and see if something changes

If nothing changes remember that we have zero info about “what fails”.

So @ibc, I did a little bit of digging to see where exactly the failure happens, and it seems it’s happening when trying to consume the video. In this piece of code of mine

try {
    const audioConsumer = await transport.consume({
      id: audioConsumerId,
      kind: 'audio',
      producerId: audioProducerId,
      rtpParameters: audioRtpParameters
    });

    mediaStream.addTrack(audioConsumer.track);

// Audio works, we are good till this point
    const videoConsumer = await transport.consume({ // this call dies
      id: videoConsumerId,
      kind: 'video',
      producerId: videoProducerId,
      rtpParameters: videoRtpParameters
    });

    mediaStream.addTrack(videoConsumer.track);
  } catch(error) {
    console.error('failed to consume [error:%o]', error);
    throw error;
  }

The transport.consume call calls this function in Firefox60.js:

	async receive({ id, kind, rtpParameters })
	{
		logger.debug('receive() [id:%s, kind:%s]', id, kind);

		const localId = String(this._nextMid);

		this._remoteSdp.receive(
			{
				mid                : localId,
				kind,
				offerRtpParameters : rtpParameters,
				streamId           : rtpParameters.rtcp.cname,
				trackId            : id
			});

		const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };

		logger.debug(
			'receive() | calling pc.setRemoteDescription() [offer:%o]', offer);

		await this._pc.setRemoteDescription(offer);

		let answer = await this._pc.createAnswer();
		const localSdpObject = sdpTransform.parse(answer.sdp);
		const answerMediaObject = localSdpObject.media
			.find((m) => String(m.mid) === localId);

		// May need to modify codec parameters in the answer based on codec
		// parameters in the offer.
		sdpCommonUtils.applyCodecParameters(
			{
				offerRtpParameters : rtpParameters,
				answerMediaObject
			});

		answer = { type: 'answer', sdp: sdpTransform.write(localSdpObject) };

		if (!this._transportReady)
			await this._setupTransport({ localDtlsRole: 'client', localSdpObject });

		logger.debug(
			'receive() | calling pc.setLocalDescription() [answer:%o]', answer);

		await this._pc.setLocalDescription(answer);

		const transceiver = this._pc.getTransceivers() // returns [
			.find((t) => t.mid === localId);

		if (!transceiver)
			throw new Error('new transceiver not found');

Turns out the video tranceiver (RTCRtpTransceiver) has a null mid. MDN says “This field is null if neither a local or remote description has been applied, or if its associated m-line is rejected by either a remote offer or any answer.”

Now the question is, why only Firefox60.js?

Please describe the scenario in which that issue happens. This is, consume, stop a consumer, consume a new producer, etc.

Hi @ibc, I decided to spend some time finding the root cause of the issue, and I think I have a fair understanding of the source of the problem. I’m streaming using H.264, but for some reason, the RTCPeerConnection in Firefox always picks VP8 when generating the SDP on the line let answer = yield this._pc.createAnswer();. This issue is prevalent in both Windows and Linux, regardless of whether Firefox installs the OpenH264 plugin from Cisco to “comply with WebRTC standards”. This looks like a bug in Firefox. Here are SDP’s from both Firefox and Chrome for reference:
Firefox:

v=0

o=mozilla...THIS_IS_SDPARTA-70.0.1 1218079954126063992 1 IN IP4 0.0.0.0

s=-

t=0 0

a=fingerprint:sha-256 86:96:35:B7:F9:E6:D9:57:52:54:FE:BF:D3:AA:6B:05:9D:52:18:CE:66:00:C5:5D:B3:7C:82:83:8C:19:ED:0D

a=group:BUNDLE 0

a=ice-options:trickle

a=msid-semantic:WMS *

m=audio 49594 UDP/TLS/RTP/SAVPF 101

c=IN IP4 192.168.2.93

a=candidate:0 1 UDP 2122252543 192.168.2.93 49594 typ host

a=candidate:1 1 TCP 2105524479 192.168.2.93 9 typ host tcptype active

a=recvonly

a=end-of-candidates

a=extmap:10 urn:ietf:params:rtp-hdrext:ssrc-audio-level

a=fmtp:101 maxplaybackrate=48000;stereo=1;useinbandfec=1

a=ice-pwd:35eb68181fdebbaa5354f7d19665f65a

a=ice-ufrag:cf578493

a=mid:0

a=rtcp-mux

a=rtpmap:101 opus/48000/2

a=setup:active

a=ssrc:611453459 cname:{a3f26e74-ce7f-4859-88b7-007d7c075d2a}

m=video 0 UDP/TLS/RTP/SAVPF 120

c=IN IP4 0.0.0.0

a=inactive

a=mid:1

a=rtpmap:120 VP8/90000

Chrome:

v=0
o=- 5546074018549880748 3 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 101
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:3760668762 1 udp 2113937151 ec3ca9ff-75ee-43b8-b4a3-5d943364c0de.local 34630 typ host generation 0 network-cost 999
a=ice-ufrag:svev
a=ice-pwd:iIWWrb2kDk8pd9jn/fbFdDCl
a=ice-options:trickle
a=fingerprint:sha-256 85:D3:C4:08:39:7B:17:6A:A3:2B:22:EE:49:84:5F:77:E7:79:AC:5B:62:60:FB:1D:A0:97:6F:BE:2F:75:9D:72
a=setup:active
a=mid:0
a=extmap:10 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=rtcp-mux
a=rtpmap:101 opus/48000/2
a=fmtp:101 minptime=10;stereo=1;useinbandfec=1
m=video 9 UDP/TLS/RTP/SAVPF 102 100
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:svev
a=ice-pwd:iIWWrb2kDk8pd9jn/fbFdDCl
a=ice-options:trickle
a=fingerprint:sha-256 85:D3:C4:08:39:7B:17:6A:A3:2B:22:EE:49:84:5F:77:E7:79:AC:5B:62:60:FB:1D:A0:97:6F:BE:2F:75:9D:72
a=setup:active
a=mid:1
a=extmap:12 urn:ietf:params:rtp-hdrext:toffset
a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:11 urn:3gpp:video-orientation
a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:6 http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07
a=recvonly
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:102 H264/90000
a=rtcp-fb:102 transport-cc
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:100 rtx/90000
a=fmtp:100 apt=102

And from mediasoup (this._remoteSdp.getSdp()):

v=0
o=mediasoup-client 10000 3 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-lite
a=fingerprint:sha-512 E0:18:83:C8:88:23:A7:A2:A3:69:AF:47:A4:03:A5:03:75:7D:E5:28:D6:3E:C0:F5:D3:01:9F:AE:0A:9B:03:8D:0D:9D:23:D3:9B:C7:7B:7F:82:6B:8B:3C:BC:CF:64:E3:17:CB:62:58:FA:6A:C9:55:AF:6C:DF:B4:7C:56:59:5A
a=msid-semantic: WMS *
a=group:BUNDLE 0 1
m=audio 7 UDP/TLS/RTP/SAVPF 101
c=IN IP4 127.0.0.1
a=rtpmap:101 opus/48000/2
a=fmtp:101 sprop-stereo=1
a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:10 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=setup:actpass
a=mid:0
a=msid:1c3e25d7 bf24f744-60d9-401d-8faf-aefb27f194b5
a=sendonly
a=ice-ufrag:963crbj2gvywdnxr
a=ice-pwd:qrkp0gwbdofh2c6s781i5p9sq5sqvdvh
a=candidate:udpcandidate 1 udp 1076558079 51.15.192.221 43613 typ host
a=candidate:tcpcandidate 1 tcp 1076302079 51.15.192.221 41111 typ host tcptype passive
a=end-of-candidates
a=ice-options:renomination
a=ssrc:940962141 cname:1c3e25d7
a=rtcp-mux
a=rtcp-rsize
m=video 7 UDP/TLS/RTP/SAVPF 102 100
c=IN IP4 127.0.0.1
a=rtpmap:102 H264/90000
a=rtpmap:100 rtx/90000
a=fmtp:102 packetization-mode=1;level-asymmetry-allowed=1
a=fmtp:100 apt=102
a=rtcp-fb:102 transport-cc 
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack 
a=rtcp-fb:102 nack pli
a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:6 http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07
a=extmap:11 urn:3gpp:video-orientation
a=extmap:12 urn:ietf:params:rtp-hdrext:toffset
a=setup:actpass
a=mid:1
a=msid:d896a166 01363b6b-66cb-41e0-a55b-a0dd08f6af70
a=sendonly
a=ice-ufrag:963crbj2gvywdnxr
a=ice-pwd:qrkp0gwbdofh2c6s781i5p9sq5sqvdvh
a=candidate:udpcandidate 1 udp 1076558079 51.15.192.221 43613 typ host
a=candidate:tcpcandidate 1 tcp 1076302079 51.15.192.221 41111 typ host tcptype passive
a=end-of-candidates
a=ice-options:renomination
a=ssrc:241299226 cname:d896a166
a=ssrc:709775480 cname:d896a166
a=ssrc-group:FID 241299226 709775480
a=rtcp-mux
a=rtcp-rsize

You are just showing a single remote SDP offer, probably the one that mediasoup-client generates in Chrome.

No idea which media codecs you are enabling in the mediasoup Router, so hard to help. Also, you know that h264 in each browser depends on profile-level-id value, right? (Sorry, I won’t explain that).

1 Like

@ibc, wow, profile-level-id is the correct answer! Can’t believe how I left that out, although like you said, I have no idea what that means. What’s incredible is every browser that is not firefox seems to have been fine with me leaving it out. Thank you so much :slight_smile:

Not all devices support the same h264 profiles.