Hi Dorin, Please find the below code. It is not the full code but it can get you a quick start for scaling the mediasoup servers across multiple machines. You need the have the knowledge of distributed cache server redis to understand this code. Feel free to connect with me in case of any doubts…
Note : my usecase is specific to 1:many broadcasting.
Server1PipingCode.js
//The producer si sending is stream on this server. server listenIP is 1.2.3.4
//rtcMinPort : 10001 and rtcMaxPort : 12000. This can be set on config.js
//We would require a pub/sub mechanism. Here we are using redis for this. Below we can create the redis
//client object as shown
const redis = require(‘redis’)
const redisServerIp = ‘x.x.x.x’
const redisClient = redis.createClient(‘6379’, redisServerIp)
redisClient.on(‘connect’, function () {
console.log('connected to redis : ’ + redisServerIp)
//Now we have redisClient ready. It needs to subscribe to a channel where we exchange piping messages
redisClient.subscribe(‘REQUESTFORPIPING’)
})
//Here we are keeping a map of all the rooms with there respective producers in a json object/array, My use case is
//specific to one:many braodcasting, so my roommap always has two producers so i keep a json object
//roommap has --> (roomId, {video : videoProducer , audio : audioProducer})
const Rooms = require(’./Rooms’)
//All my code is in Rooms.js and the map also reside in Rooms.js
const rooms = new Rooms()
//Lets assume we have the room Id in this code. you need to have it here in this code to inform the other
//server which room streams should be piped.
let pipedTransportProducer;
redisClient.on(‘message’, async function (channel, msg) {
const message = JSON.parse(msg)
if (channel === ‘REQUESTFORPIPING’ && message.signature !== ‘1.2.3.4’) {
if (message.type === ‘CREATE_PRODUCER_PIPE’) {
//you also need to have the router object on which ur producer is present
pipedTransportProducer = await router.createPipeTransport({
enableRtx: true,
enableSrtp: true,
listenIp: ‘1.2.3.4’
})
redisClient.publish(‘REQUESTFORPIPING’, JSON.stringify({
type: ‘CREATE_CONSUMER_PIPE’,
signature: ‘1.2.3.4’,
roomId: message.roomId,
requestedIp: message.signature
}))
}
if (message.type === 'CONNECT_PRODUCER_PIPE') {
await pipedTransportProducer.connect({
ip: message.remoteIp,
port: message.remotePort,
srtpParameters: message.srtpParameters
})
redisClient.publish('REQUESTFORPIPING', JSON.stringify({
type: 'CONNECT_CONSUMER_PIPE',
remoteIp: pipedTransportProducer.tuple.localIp,
remotePort: pipedTransportProducer.tuple.localPort,
srtpParameters: pipedTransportProducer.srtpParameters,
signature: '1.2.3.4',
roomId: message.roomId,
requestedIp: message.signature
}))
}
if (message.type === 'START_PIPE_PRODUCING') {
const rtpCapabilities = router.rtpCapabilities
let videoConsumer
let audioConsumer
try {
videoConsumer = await pipedTransportProducer.consume({
producerId: rooms._roomsMap.get(message.roomId).video.id,
rtpCapabilities,
kind: 'video',
paused: false
})
} catch (error) {
console.error('video consume failed', error)
return
}
try {
audioConsumer = await pipedTransportProducer.consume({
producerId: rooms._roomsMap.get(message.roomId).audio.id,
rtpCapabilities,
kind: 'audio',
paused: false
})
} catch (error) {
console.error('audio consume failed', error)
return
}
redisClient.publish('REQUESTFORPIPING', JSON.stringify({
type: 'START_PIPE_CONSUMING',
signature: '1.2.3.4',
audioRtpParam: audioConsumer.rtpParameters,
videoRtpParam: videoConsumer.rtpParameters,
roomId: message.roomId,
requestedIp: message.signature
}))
}
}
})
Server2PipingCode.js
//The consumers receive the stream on this server. server listenIP is 5.6.7.8
//rtcMinPort : 12001 and rtcMaxPort : 14000. This can be set on config.js
//We would require a pub/sub mechanism. Here we are using redis for this. Below we can create the redis
//client object as shown
const redis = require(‘redis’)
const redisServerIp = ‘x.x.x.x’
const redisClient = redis.createClient(‘6379’, redisServerIp)
redisClient.on(‘connect’, function () {
console.log('connected to redis : ’ + redisServerIp)
//Now we have redisClient ready. It needs to subscribe to a channel where we exchange piping messages
redisClient.subscribe(‘REQUESTFORPIPING’)
})
//Here we are keeping a map of all the rooms with there respective producers in a json object/array, My use case is
//specific to one:many braodcasting, so my roommap always has two producers so i keep a json object
//roommap has --> (roomId, {video : videoProducer , audio : audioProducer})
const Rooms = require(’./Rooms’)
//All my code is in Rooms.js and the map also reside in Rooms.js
const rooms = new Rooms()
//Lets assume we have the room Id in this code. you need to have it here in this code to inform the other
//server which room streams should be piped.
let pipedTransportConsumer;
//In my case the consumers present on server2 always requests for piping of producers from server1
const obj = { type: ‘CREATE_PRODUCER_PIPE’, signature: ‘5.6.7.8’, requestedIp: ‘1.2.3.4’, roomId: roomId }
redisClient.publish(‘REQUESTFORPIPING’, JSON.stringify(obj), function () {
console.log(‘lol’)
})
redisClient.on(‘message’, async function (channel, msg) {
const message = JSON.parse(msg)
//when we publish a message on redisClient it goes to all servers connected to redis as well as to
//the server which actually published the message therefore below check of message.signature
if (channel === ‘REQUESTFORPIPING’ && message.signature !== ‘5.6.7.8’) {
if (message.type === ‘CREATE_CONSUMER_PIPE’) {
//you also need to have the router object on which ur producer is present
pipedTransportConsumer = await router.createPipeTransport({
enableRtx: true,
enableSrtp: true,
listenIp: ‘5.6.7.8’
})
redisClient.publish(‘REQUESTFORPIPING’, JSON.stringify({
type: ‘CONNECT_PRODUCER_PIPE’,
signature: ‘5.6.7.8’,
remotePort: pipedTransportConsumer.tuple.localPort,
srtpParameters: pipedTransportConsumer.srtpParameters,
roomId: message.roomId,
requestedIp: message.signature
}))
}
if (message.type === 'CONNECT_CONSUMER_PIPE') {
await pipedTransportConsumer.connect({
ip: message.remoteIp,
port: message.remotePort,
srtpParameters: message.srtpParameters
})
redisClient.publish('REQUESTFORPIPING', JSON.stringify({
type: 'START_PIPE_PRODUCING',
signature: '5.6.7.8',
roomId: message.roomId,
requestedIp: message.signature
}))
}
if (message.type === 'START_PIPE_CONSUMING') {
//here you actually have the producer which are being sent from the server1
//once you have the producers, consumer can consume on the below producers.
const videoProducer = await pipedTransportConsumer.produce({
kind: 'video',
rtpParameters: message.videoRtpParam
})
const audioProducer = await pipedTransportConsumer.produce({
kind: 'audio',
rtpParameters: message.audioRtpParam
})
videoProducer.resume()
audioProducer.resume()
}
}
})