I have a question I am sure that I know the answer to… But my results are pointing to me being wrong. I wanted to ask: Must getUserMedia be called before a dataChannel can be established? I have included an example below, but my actual code has the behavior of needing the user to accept a getUserMedia dialog before the dataChannel will establish between client and server. Otherwise, the dataChannel fails with the webrtcSendTransport failing to reach the connected state, with an ice/turn failure. When a user accepts the getUserMedia reques (audio or video doesn’t matter) the data channel connects happily, even if I don’t pass any of the media streams to mediasoup, and only call the produceData on the transport.
//Called on page load, before user clicks "start" button
async connectIngressTransport(transport) {
this.producerTransport = await this.webRTCDevice.createSendTransport({
id: transport.id,
iceParameters: transport.iceParameters,
iceCandidates: transport.iceCandidates,
//iceServers: iceServersJSON,
dtlsParameters: transport.dtlsParameters,
sctpParameters: transport.sctpParameters
});
this.producerTransport.on(
"connect",
async ({ dtlsParameters }, callback, errback) => {
this.send("connectIngressTransport", {
peerId: this.avatar_id,
direction: this.producerTransport.direction,
dtlsParameters: dtlsParameters
});
callback();
}
);
this.producerTransport.on("connectionstatechange", connectionState => {
console.warn("Producer transport state:", connectionState);
});
this.producerTransport.on(
"producedata",
async ( { sctpStreamParameters, label, protocol, appData }, callback, errback) => {
// Send dataProducer data to server
this.send("produceData", {
producingPeer: this.avatar_id,
producerOptions: {
sctpStreamParameters: sctpStreamParameters,
label: label,
protocol: protocol,
appData: appData
}
});
// Wait for incoming producedData signal to set this value
await this.waitFor(_ => this.movementProducerId !== undefined);
callback({ id: this.movementProducerId });
});
}
//Called by user action button click
async start(func) {
const frameMediaOptions = { audio: true,
video: false };
await navigator.mediaDevices.getUserMedia(frameMediaOptions)
.catch( error => { console.log("Error getting shit", error) })
.finally( async () => { await this.producerTransport.produceData();
console.log("PRODUCED DATA") })
}
The example above works as expected, but if I were to comment out the getUserMedia call and move the producerTransport.produceData to be alone, it would fail. – This leads me into questioning whether the getUserMedia is needed, even if dataChannels are the only thing being used. I have checked the values, for sctp and dtls and they seem to be ok. The transport has sctp enabled, and otherwise works with the same active code, except when getUserMedia is not called. :-/
Any insights would be appreciated. The links below seemed to touch on the topic, but didn’t lead to any ‘aha!’ moments.