Hey everyone. First of all the obligatory praise for mediasoup. It’s an amazing library and I appreciate your work on this project! I have already completed a Virtual Office project using Mediasoup and it’s working nicely.
My new assignment, though, causes me a bit of a headache. We are trying to integrate WebRTC using Mediasoup SFU in Unity.
After many days of trying and debugging I finally got it to work. However, it only works with Video. The audio that is sent from the application is not being transmitted ( Empty Producer Stats ). Which is puzzling to me as in the core there shouldn’t be any difference, no?
I am turning to you guys in hopes that someone could enlighten me where the problem could be. Now I know that Mediasoup is only one part of my setup and the error could be somewhere else along the line but I am out of ideas at this point.
My setup is:
MixedReality WebRTC for Unity
OpenVidu’s Mediasoup SDP Bridge fork
Mediasoup
The process is simple. MR WebRTC works with a mostly vanilla approach. It’s a standard Offer-Answer model with trickle-ice.
I translate the SDP messages using the SDP bridge and populate Mediasoup transports.
Again, for Video it works absolutely fine already. However, the Audio track is not being sent.
I have already tried different things, like:
- Remove video track and send only Audio (same result)
- Use different codecs (same result)
- Combed through MR WebRTC Issues on GH and this forum here (no specific results)
If I use the Unity App in vanilla mode (direct p2p via a PeerConnection) audio works fine. That’s why I’m thinking the problem is probably server-side somewhere.
I would greatly appreciate any hints that could lead me to resolve this issue. I’ll attach several bits of information that could help find the problem.
SDP Offer/Answer from the broken Audio connection:
Offer
v=0
o=- 8534608570643004729 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:xvmp
a=ice-pwd:DysEU3DkZiiT2J7mU4S2Vtb8
a=ice-options:trickle
a=fingerprint:sha-256 13:FB:6B:28:1D:B9:BF:CF:B3:3D:78:06:4C:5E:F5:D0:91:75:9F:D0:A3:46:0B:77:32:38:5A:2B:B0:EB:D8:49
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=sendrecv
a=msid:- da6e57c5-9b77-4f99-b477-445eea6d9780
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:102 ILBC/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:2171558851 cname:KmmmiQWE7gsElCJV
a=ssrc:2171558851 msid: da6e57c5-9b77-4f99-b477-445eea6d9780
a=ssrc:2171558851 mslabel:
a=ssrc:2171558851 label:da6e57c5-9b77-4f99-b477-445eea6d9780
Answer
v=0
o=mediasoup-client 10000 1 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-lite
a=fingerprint:sha-512 E2:16:9F:63:40:AC:E1:AE:62:B8:AA:22:E1:C3:4E:04:FE:9A:EC:10:09:EF:19:67:23:8B:84:9F:BD:39:2B:42:93:EC:A6:61:D8:0E:80:8A:45:98:E9:C2:EB:0F:56:D0:DE:BE:C7:74:A8:23:68:77:BE:02:84:E0:77:84:A7:29
a=msid-semantic: WMS *
a=group:BUNDLE 0
m=audio 7 UDP/TLS/RTP/SAVPF 111
c=IN IP4 127.0.0.1
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=rtcp-fb:111 transport-cc
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=setup:active
a=mid:0
a=recvonly
a=ice-ufrag:lmvojj3yknu0tf5v
a=ice-pwd:abohg4ovhgr9ekuwfopu5p94614enxjp
a=candidate:udpcandidate 1 udp 1076302079 XXXXXXXXX 43009 typ host
a=candidate:tcpcandidate 1 tcp 1076302079 XXXXXXXXX 40267 typ host tcptype passive
a=end-of-candidates
a=ice-options:renomination
a=rtcp-mux
a=rtcp-rsize
As a comparison, here’s the Answer from when I try it with the vanilla implementation (audio works fine)
data=v=0
o=- 6722375024708538588 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:oFYw
a=ice-pwd:Q05S8q0lleRv8SlllM2veqQw
a=ice-options:trickle
a=fingerprint:sha-256 8D:9D:F1:DE:51:79:72:EB:AF:C5:CA:36:70:E3:7D:D3:7A:78:3A:00:AE:F7:46:D0:F9:38:14:EC:30:A9:1D:9D
a=setup:active
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=sendrecv
a=msid:- f572eaa1-7b6c-4a1c-94c9-8b594eb61cf5
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:102 ILBC/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:270015488 cname:4vlIriUyG5mguaM/
Finally, here are some server logs of a test run including parsed producerParameters
new producer created [worker.pid:16464, router.id:e7b241ca-5150-4209-a25a-17620978ea3e, transport.id:fc3e619e-dc71-4ae3-a7b3-7975aebc2094, producer.id:b59463af-8712-4abe-911
b-92e675f1c15a]
PRODUCERPARAMS
{"mid":"0",
"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:ssrc-audio-level","id":1,"encrypt":false,"parameters":{}},{"uri":"urn:ietf:pa
rams:rtp-hdrext:sdes:mid","id":9,"encrypt":false,"parameters":{}}],
"encodings":[{"ssrc":3187872821,"dtx":false}],
"rtcp":{"cname":"IfkdEfLUVL+AjF+H","reducedSize":true,"mux": true}}
[SdpEndpoint.processOffer] mediasoup Producer created, kind: audio, type: simple, paused: false
[SdpEndpoint.createAnswer] Make 'recvonly' SDP Answer
mediasoup:Channel [pid:16464] RTC::IceServer::HandleTuple() | transition from state 'new' to 'connected' [hasUseCandidate:false, hasNomination:false, nomination:0] +1s
mediasoup:Channel [pid:16464] RTC::WebRtcTransport::OnIceServerSelectedTuple() | ICE selected tuple +0ms
mediasoup:Channel [pid:16464] RTC::WebRtcTransport::OnIceServerConnected() | ICE connected +0ms
mediasoup:Channel [pid:16464] RTC::WebRtcTransport::MayRunDtlsTransport() | running DTLS transport in local role 'client' +1ms
mediasoup:Channel [pid:16464] RTC::WebRtcTransport::OnDtlsTransportConnecting() | DTLS connecting +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::Run() | running [role:client] +0ms
transport ICE state changed to connected
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | DTLS handshake start +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'before SSL initialization'] +1ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS write client hello'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | role: client, waiting:'SSLv3/TLS write client hello'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS write client hello'] +108ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS read server hello'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS read server certificate'] +1ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS read server key exchange'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS read server certificate request'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS read server done'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS write client certificate'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS write client key exchange'] +1ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS write certificate verify'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS write change cipher spec'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS write finished'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | role: client, waiting:'SSLv3/TLS write finished'] +0ms
mediasoup:Channel [pid:16464] RTC::IceServer::HandleTuple() | transition from state 'connected' to 'completed' [hasUseCandidate:true, hasNomination:false, nomination:0] +3
3ms
mediasoup:Channel [pid:16464] RTC::WebRtcTransport::OnIceServerCompleted() | ICE completed +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS write finished'] +75ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS read change cipher spec'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | [role:client, action:'SSLv3/TLS read finished'] +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::OnSslInfo() | DTLS handshake done +1ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::CheckRemoteFingerprint() | valid remote fingerprint +0ms
mediasoup:Channel [pid:16464] RTC::DtlsTransport::GetNegotiatedSrtpCryptoSuite() | chosen SRTP crypto suite: SRTP_AES128_CM_SHA1_80 +0ms
mediasoup:Channel [pid:16464] RTC::WebRtcTransport::OnDtlsTransportConnected() | DTLS connected +0ms
mediasoup:Producer getStats() +5s
mediasoup:Channel request() [method:producer.getStats, id:6] +4s
mediasoup:Channel request succeeded [method:producer.getStats, id:6] +0ms
Audio Producer Stats in 5 s interval
[]
Thank you so much for any help in advance. If there’s something else I could provide to help with this issue, please let me know.