ok, i did again, but i still have the same thing, the connection is complete and connected, but still not media stream showing in my video element
Does the consumer and producer should use the same transport ?
About what i saw i can have a transport for my producer and another one for my consumer.
there is not inbound-rtp packet for consumer but for producer i have ountbound and inbound rtp traffic
maybe if the connection status is connected after the consume can cause the issue ?
No, as already described producers and consumers can’t go together in one transport.
@indie this will be really difficult to help at this point without seeing what you are doing. The only possible way is that you share with us minimum working code to see what you are doing wrong.
I don’t know what to provide more, i am stuck since week with this lib
@indie you are not supposed to stuck with the library for that long if you have understood the basic principles of working with the library. You may have missed some critical things in the documentation may be you were hurry.
Run a demo on your local system it will surely work and after that customise it as per your needs this will give you more understanding of library plus it will save your time.
So why i have a connection and why no inbound-rtp packet are received in consumer side ?
I don’t want to loose another month, i don’t know what should i do.
Try to invest another month or try to use another library
Only you can find the root cause, we have shared with you the possible causes.
Have you run the demo on your system? does it work?
wich one ? this one ?
I left to try, it’s a hell to make this run.
I can’t even npm install
does i have to use an ssl in my project ??
First thing, is why i don’t even have an error message with my issue ?
Yes this one. What is the issue you are facing with installation?
I have a meson error/
I don’t want to loose one week trying to make a demo project work and try another month trying to make my own code working.
I have lost already one month
Give it a try to resolve the issue, if you were able to run mediasoup in your system then the demo should run as well.
I show you all my code with the details:
I start first with the full producer/
Producer side (Front End):
/**
* Create local producer and stream media stream to SFU Server
*/
async createProduceAndStream(responseStreamCreated: any) {
try {
const device = new Device();
const routerRtpCapabilities: RtpCapabilities = responseStreamCreated.transport.rtpCapabilities;
console.log("routerRtpCapabilities");
console.log(routerRtpCapabilities);
console.log("responseStreamCreated.transport.transportOptions");
console.log(responseStreamCreated.transport.transportOptions);
await device.load({routerRtpCapabilities});
console.log("device");
console.log(device);
This is console.log(routerRtpCapabilities):

This is console.log(responseStreamCreated.transport.transportOptions):
This is the console.log(device):
const sendTransport = await device.createSendTransport(responseStreamCreated.transport.transportOptions);
console.log("responseStreamCreated");
console.log(responseStreamCreated);
await new Promise<void>(async (resolve) => {
try {
sendTransport.on('connect', ({ dtlsParameters }, callback) => {
console.log("sendTransport connect dtlsParameters:");
console.log(dtlsParameters);
// Send dtlsParameters to the backend
this.streamingService.sendDtlsParameters({
transportId: responseStreamCreated.transport.transportOptions.id,
dtlsParameters
});
callback();
});
sendTransport.on("produce", async (parameters, callback, errback) => {
console.log("parameters produce");
console.log(parameters);
console.log("responseStreamCreated produce");
console.log(responseStreamCreated);
// Send dtlsParameters to the backend
this.streamingService.produceProducer({
transportId: responseStreamCreated.transport.transportOptions.id,
streamId: responseStreamCreated.stream.streaming_id,
userId: this.userId,
kind: parameters.kind,
rtpParameters: parameters.rtpParameters,
appData: parameters.appData,
});
this.streamingService.receiveProduceProducer().subscribe((producerId: string) => {
console.log("receiveProduceProducer producerId");
console.log(producerId);
callback({id: producerId});
});
});
sendTransport.on('connectionstatechange', (state) => {
console.log("connectionstatechange producer 1");
console.log(state);
if (state === 'failed' || state === 'closed') {
// Handle transport failure
console.log("connectionstatechange failure producer 1");
}
Those console.log returns:

});
this.localStream.getTracks().forEach(async (track: MediaStreamTrack) => {
const producer = await sendTransport.produce({
track: track,
codecOptions: {
opusStereo: true,
opusDtx: true,
},
});
});
sendTransport.on('connectionstatechange', (state) => {
console.log("connectionstatechange producer 1");
console.log(state);
if (state === 'failed' || state === 'closed') {
// Handle transport failure
console.log("connectionstatechange failure producer 1");
}
});
resolve();
} catch (Exception) {
console.log('Exception Mediasoup Produce');
console.log(Exception);
}
});
this.handleProducerEvent(this.producer);
} catch (Exception) {
console.log("Exception");
console.log(Exception);
}
}
/**
* Handle close and end transport's event
*/
handleProducerEvent(producer: Producer) {
producer.on('transportclose', () => {
// Handle transport close event
});
producer.on('trackended', () => {
// Handle track ended event
});
producer.on("@close", () => {
// Handle producer close event
});
}
And here is the Producer Back end:
This is how my server options looks like:
const serverOptions: WebRtcServerOptions = {
listenInfos: [
{
ip: '0.0.0.0',
announcedIp: '127.0.0.1',
port: port,
protocol: 'udp'
},
{
ip: '0.0.0.0',
announcedIp: '127.0.0.1',
port: port,
protocol: 'tcp'
},
],
appData: {
customData: 'This is my custom data'
}
};
This is how i create my worker:
async createWorker(index: number): Promise<mediasoup.types.Worker> {
const worker = await mediasoup.createWorker({
logLevel: 'debug',
logTags :
[
'info',
'ice',
'dtls',
'rtp',
'srtp',
'rtcp',
'rtx',
'bwe',
'score',
'simulcast',
'svc',
'sctp'
],
rtcMinPort: this.configService.get('PORT_MIN_SFU'), // 2000
rtcMaxPort: this.configService.get('PORT_MAX_SFU'), // 2020
});
worker.on('died', () => {
console.error('mediasoup worker died, exiting in 2 seconds... [pid:%d]', worker.pid);
setTimeout(() => process.exit(1), 2000);
});
return worker;
}
This is how i create my router:
async createRouterFromWorker(worker: mediasoup.types.Worker): Promise<mediasoup.types.Router> {
const mediaCodecs: Array<mediasoup.types.RtpCodecCapability> = [
{
kind: 'audio',
mimeType: 'audio/opus',
clockRate: 48000,
channels: 2,
},
{
kind: 'video',
mimeType: 'video/VP8',
clockRate: 90000,
parameters: {
'x-google-start-bitrate': 1000,
},
},
];
return await worker.createRouter({mediaCodecs});
}
This is how i create my transports, for both producer and consumer:
async createTransportForRouter(router: mediasoup.types.Router, server: mediasoup.types.WebRtcServer) {
const stunServer = {
urls: 'stun:stun.l.google.com:19302'
};
const transport = await router.createWebRtcTransport(
{
webRtcServer : server, // Or ListenIps
// listenIps : [ { ip: "0.0.0.0", announcedIp: "127.0.0.1" } ],
enableUdp : true,
enableTcp : true,
preferUdp : true,
initialAvailableOutgoingBitrate: 1000000,
numSctpStreams: { OS: 1024, MIS: 1024 },
} as WebRtcTransportOptions
);
transport.on("icestatechange", (iceState) => {
console.log(`ICE state changed to ${iceState}`);
});
transport.on('dtlsstatechange', dtlsState => {
if (dtlsState === 'closed') {
console.log('dtlsstatechange transport closed');
transport.close();
}
})
transport.on('@close', () => {
console.log('transport closed');
})
return transport;
}
This is how i create the producer:
async createPipeProducer(userStreamerId: string, stream: any) {
const transport = await this.createTransportForRouter(this.stream.get(stream.indexWorker).router, this.stream.get(stream.indexWorker).server);
this.transportId = transport.id;
// Get the supported RTP capabilities
const rtpCapabilities: mediasoup.types.RtpCapabilities = this.stream.get(stream.indexWorker).router.rtpCapabilities;
// const rtpParameters: mediasoup.types.RtpParameters = rtpCapabilities.codecs.find(codecs => codecs.mimeType.toLowerCase() === "video/vp8");
const codec: mediasoup.types.RtpCodecCapability = rtpCapabilities.codecs.find(codecs => codecs.mimeType.toLowerCase() === "video/vp8");
if (!codec) {
throw new Error(`Router does not support this mime type`);
}
const rtpCodecParameters: mediasoup.types.RtpCodecParameters = {
// name: codec.name,
payloadType: codec.preferredPayloadType,
clockRate: codec.clockRate,
mimeType: codec.mimeType,
parameters: {
'x-google-start-bitrate': 1000,
},
};
const rtpParameters: mediasoup.types.RtpParameters = {
codecs: [rtpCodecParameters],
rtcp: {
cname: 'mediasoup-client',
reducedSize: true,
mux: true,
},
encodings: [{ ssrc: 1001 }],
};
const transportOptions = {
id: transport.id,
iceParameters: transport.iceParameters,
iceCandidates: transport.iceCandidates,
dtlsParameters: transport.dtlsParameters,
};
const room: Room = {
transports: new Map().set(transport.id, transport),
router: this.stream.get(stream.indexWorker).router,
streamId: stream.streaming_id,
};
this.rooms.set(stream.streaming_id, room);
this.transports.set(transport.id, transport);
return {
transportOptions: transportOptions,
rtpCapabilities: rtpCapabilities
}
} catch (Exception) {
console.log("createPipeProducer Exception");
console.log(Exception);
}
}
When i call sendDtlsParameters in front end, like this:
sendTransport.on('connect', ({ dtlsParameters }, callback) => {
console.log("sendTransport connect dtlsParameters:");
console.log(dtlsParameters);
// Send dtlsParameters to the backend
this.streamingService.sendDtlsParameters({
transportId: responseStreamCreated.transport.transportOptions.id,
dtlsParameters
});
// this.streamingService.receiveDtlsParameterCallResponse().subscribe(() => {
// callback();
// });
callback();
});
This is what is called in back end:
async producerTransportConnect(transportConnect) {
try {
await this.transports.get(transportConnect.transportId).connect({dtlsParameters: transportConnect.dtlsParameters});
} catch (Exception) {
console.log("Exception");
console.log(Exception);
}
}
Now when in front end i call:
this.streamingService.produceProducer({
transportId: responseStreamCreated.transport.transportOptions.id,
streamId: responseStreamCreated.stream.streaming_id,
userId: this.userId,
kind: parameters.kind,
rtpParameters: parameters.rtpParameters,
appData: parameters.appData,
});
This is what is called in the back end:
async producerTransportProduce(rtpParameters) {
try {
const producer = await this.transports.get(rtpParameters.transportId).produce({
kind: rtpParameters.kind,
rtpParameters: rtpParameters.rtpParameters,
});
this.rooms.get(rtpParameters.streamId).producer = producer;
producer.on('transportclose', () => {
console.log('transport for this producer closed ')
producer.close()
})
console.log({id: producer.id, clientId: rtpParameters.clientId, streamId: rtpParameters.streamId});
// Send back to the client the Producer's id
this.publisher.publish('receiveProduceProducer', JSON.stringify({id: producer.id, clientId: rtpParameters.clientId, streamId: rtpParameters.streamId}));
} catch (Exception) {
console.log("Exception");
console.log(Exception);
}
}
I use Angular in Front end and NestJS in back end btw.
Seems all ok, the connectionstate is not going to connected here?:
Have you verified the logs in server side whether the connect, produce related function are being called and executed properly?
You have shared the code here, why don’t you share with me the minimum project here? I mean just this call related frontend, backend. It is really difficult to catch otherwise.
And you are also sending the connect parameters to server on ‘connect’ event of transport in case of consumer right?

