sorry for disturbing you again but this is getting really confusing for me and i am at very last to set this up, it will be great help if you could just make changes to this code for announced ip being automatically detected on uploading on render,
i have tried using render’s public url as the announced ip but that was of no use,
i will be highly grateful to you
import express from ‘express’
const app = express()
const port = 3000;
app.use(express.json());
import fs from ‘fs’
import path from ‘path’
const __dirname = path.resolve()
import http from ‘http’;
import { Server } from ‘socket.io’
import mediasoup from ‘mediasoup’
app.use(express.static(path.join(__dirname)));
app.get(‘/’, (req, res) => {
res.sendFile(path.join(__dirname,‘home.html’));
});
app.get(‘/room/:roomNumber’, (req, res) => {
res.sendFile(path.join(__dirname, ‘room.html’));
});
const httpsServer = http.createServer( app)
httpsServer.listen(port, () => {
console.log('listening on port: ’ + ( port))
})
const io = new Server(httpsServer)
// socket.io namespace (could represent a room?)
const connections = io.of(‘/mediasoup’)
let worker
let rooms = {} // { roomName1: { Router, rooms: [ sicketId1, … ] }, …}
let peers = {} // { socketId1: { roomName1, socket, transports = [id1, id2,] }, producers = [id1, id2,] }, consumers = [id1, id2,], peerDetails }, …}
let transports = // [ { socketId1, roomName1, transport, consumer }, … ]
let producers = // [ { socketId1, roomName1, producer, }, … ]
let consumers = // [ { socketId1, roomName1, consumer, }, … ]
const createWorker = async () => {
worker = await mediasoup.createWorker({
rtcMinPort:2000,
rtcMaxPort:2050,
})
console.log(worker pid ${worker.pid}
)
worker.on(‘died’, error => {
// This implies something serious happened, so kill the application
console.error(‘mediasoup worker has died’)
setTimeout(() => process.exit(1), 2000) // exit in 2 seconds
})
return worker
}
// We create a Worker as soon as our application starts
worker = createWorker()
const mediaCodecs = [
{
kind: ‘audio’,
mimeType: ‘audio/opus’,
clockRate: 48000,
channels: 2,
},
{
kind: ‘video’,
mimeType: ‘video/VP8’,
clockRate: 90000,
parameters: {
‘x-google-start-bitrate’: 1000,
},
},
]
connections.on(‘connection’, async socket => {
console.log(socket.id)
socket.emit(‘connection-success’, {
socketId: socket.id,
})
const removeItems = (items, socketId, type) => {
items.forEach(item => {
if (item.socketId === socket.id) {
item[type].close()
}
})
items = items.filter(item => item.socketId !== socket.id)
return items
}
socket.on(‘disconnect’, () => {
console.log(‘peer disconnected’);
const peer = peers[socket.id];
if (peer) {
consumers = removeItems(consumers, socket.id, ‘consumer’);
producers = removeItems(producers, socket.id, ‘producer’);
transports = removeItems(transports, socket.id, ‘transport’);
const { roomName } = peer;
rooms[roomName] = {
router: rooms[roomName].router,
peers: rooms[roomName].peers.filter(socketId => socketId !== socket.id)
};
delete peers[socket.id];
} else {
console.log(‘Socket ID not found in peers’);
}
});
socket.on(‘joinRoom’, async ({ roomName }, callback) => {
const router1 = await createRoom(roomName, socket.id)
peers[socket.id] = {
socket,
roomName,
transports: ,
producers: ,
consumers: ,
peerDetails: {
name: ‘’,
isAdmin: false,
}
}
const rtpCapabilities = router1.rtpCapabilities
callback({ rtpCapabilities })
})
const createRoom = async (roomName, socketId) => {
let router1
let peers =
if (rooms[roomName]) {
router1 = rooms[roomName].router
peers = rooms[roomName].peers ||
} else {
router1 = await worker.createRouter({ mediaCodecs, })
}
console.log(Router ID: ${router1.id}
, peers.length)
rooms[roomName] = {
router: router1,
peers: […peers, socketId],
}
return router1
}
// Client emits a request to create server side Transport
// We need to differentiate between the producer and consumer transports
socket.on(‘createWebRtcTransport’, async ({ consumer }, callback) => {
// get Room Name from Peer’s properties
const roomName = peers[socket.id].roomName
// get Router (Room) object this peer is in based on RoomName
const router = rooms[roomName].router
createWebRtcTransport(router).then(
transport => {
callback({
params: {
id: transport.id,
iceParameters: transport.iceParameters,
iceCandidates: transport.iceCandidates,
dtlsParameters: transport.dtlsParameters,
}
})
// add transport to Peer’s properties
addTransport(transport, roomName, consumer)
},
error => {
console.log(error)
})
})
const addTransport = (transport, roomName, consumer) => {
transports = [
…transports,
{ socketId: socket.id, transport, roomName, consumer, }
]
peers[socket.id] = {
…peers[socket.id],
transports: [
…peers[socket.id].transports,
transport.id,
]
}
}
const addProducer = (producer, roomName) => {
producers = [
…producers,
{ socketId: socket.id, producer, roomName, }
]
peers[socket.id] = {
…peers[socket.id],
producers: [
…peers[socket.id].producers,
producer.id,
]
}
}
const addConsumer = (consumer, roomName) => {
// add the consumer to the consumers list
consumers = [
…consumers,
{ socketId: socket.id, consumer, roomName, }
]
// add the consumer id to the peers list
peers[socket.id] = {
…peers[socket.id],
consumers: [
…peers[socket.id].consumers,
consumer.id,
]
}
}
socket.on(‘getProducers’, callback => {
//return all producer transports
const { roomName } = peers[socket.id]
let producerList =
producers.forEach(producerData => {
if (producerData.socketId !== socket.id && producerData.roomName === roomName) {
producerList = […producerList, producerData.producer.id]
}
})
// return the producer list back to the client
callback(producerList)
})
const informConsumers = (roomName, socketId, id) => {
console.log(just joined, id ${id} ${roomName}, ${socketId}
)
// A new producer just joined
// let all consumers to consume this producer
producers.forEach(producerData => {
if (producerData.socketId !== socketId && producerData.roomName === roomName) {
const producerSocket = peers[producerData.socketId].socket
// use socket to send producer id to producer
producerSocket.emit(‘new-producer’, { producerId: id })
}
})
}
const getTransport = (socketId) => {
const [producerTransport] = transports.filter(transport => transport.socketId === socketId && !transport.consumer)
return producerTransport.transport
}
// see client’s socket.emit(‘transport-connect’, …)
socket.on(‘transport-connect’, ({ dtlsParameters }) => {
console.log('DTLS PARAMS… ', { dtlsParameters })
getTransport(socket.id).connect({ dtlsParameters })
})
// see client’s socket.emit(‘transport-produce’, …)
socket.on(‘transport-produce’, async ({ kind, rtpParameters, appData }, callback) => {
// call produce based on the prameters from the client
const producer = await getTransport(socket.id).produce({
kind,
rtpParameters,
})
// add producer to the producers array
const { roomName } = peers[socket.id]
addProducer(producer, roomName)
informConsumers(roomName, socket.id, producer.id)
console.log('Producer ID: ', producer.id, producer.kind)
producer.on(‘transportclose’, () => {
console.log('transport for this producer closed ')
producer.close()
})
// Send back to the client the Producer’s id
callback({
id: producer.id,
producersExist: producers.length>1 ? true : false
})
})
// see client’s socket.emit(‘transport-recv-connect’, …)
socket.on(‘transport-recv-connect’, async ({ dtlsParameters, serverConsumerTransportId }) => {
console.log(DTLS PARAMS: ${dtlsParameters}
)
const consumerTransport = transports.find(transportData => (
transportData.consumer && transportData.transport.id == serverConsumerTransportId
)).transport
await consumerTransport.connect({ dtlsParameters })
})
socket.on(‘consume’, async ({ rtpCapabilities, remoteProducerId, serverConsumerTransportId }, callback) => {
try {
const { roomName } = peers[socket.id]
const router = rooms[roomName].router
let consumerTransport = transports.find(transportData => (
transportData.consumer && transportData.transport.id == serverConsumerTransportId
)).transport
// check if the router can consume the specified producer
if (router.canConsume({
producerId: remoteProducerId,
rtpCapabilities
})) {
// transport can now consume and return a consumer
const consumer = await consumerTransport.consume({
producerId: remoteProducerId,
rtpCapabilities,
paused: true,
})
consumer.on(‘transportclose’, () => {
console.log(‘transport close from consumer’)
})
consumer.on(‘producerclose’, () => {
console.log(‘producer of consumer closed’)
socket.emit(‘producer-closed’, { remoteProducerId })
consumerTransport.close()
transports = transports.filter(transportData => transportData.transport.id !== consumerTransport.id)
consumer.close()
consumers = consumers.filter(consumerData => consumerData.consumer.id !== consumer.id)
})
addConsumer(consumer, roomName)
// from the consumer extract the following params
// to send back to the Client
const params = {
id: consumer.id,
producerId: remoteProducerId,
kind: consumer.kind,
rtpParameters: consumer.rtpParameters,
serverConsumerId: consumer.id,
}
// send the parameters to the client
callback({ params })
}
} catch (error) {
console.log(error.message)
callback({
params: {
error: error
}
})
}
})
socket.on(‘consumer-resume’, async ({ serverConsumerId }) => {
console.log(‘consumer resume’)
const { consumer } = consumers.find(consumerData => consumerData.consumer.id === serverConsumerId)
await consumer.resume()
})
})
const createWebRtcTransport = async (router) => {
return new Promise(async (resolve, reject) => {
try {
// https://mediasoup.org/documentation/v3/mediasoup/api/#WebRtcTransportOptions
const webRtcTransport_options = {
listenIps: [
{
ip: ‘0.0.0.0’, // replace with relevant IP address
announcedIp: ‘192.168.1.7’,
}
],
enableUdp: true,
enableTcp: true,
preferUdp: true,
}
// https://mediasoup.org/documentation/v3/mediasoup/api/#router-createWebRtcTransport
let transport = await router.createWebRtcTransport(webRtcTransport_options)
console.log(transport id: ${transport.id}
)
transport.on(‘dtlsstatechange’, dtlsState => {
if (dtlsState === ‘closed’) {
transport.close()
}
})
transport.on(‘close’, () => {
console.log(‘transport closed’)
})
resolve(transport)
} catch (error) {
reject(error)
}
})
}