Pepguy's picture
Update app.js
42e18e6 verified
raw
history blame
4.27 kB
// server.js
const http = require('http');
const WebSocket = require('ws');
const mediasoup = require('mediasoup');
const PORT = 7860;
let worker, router;
const producerTransports = new Map(); // ws → { transport, producer }
const consumerTransports = new Map(); // ws → [ { transport, consumer } ]
(async () => {
// 1) Start HTTP + WebSocket server
const server = http.createServer();
const wss = new WebSocket.Server({ server });
server.listen(PORT, () => console.log(`Server running on ${PORT}`));
// 2) Create a single Mediasoup Worker + Router
worker = await mediasoup.createWorker();
router = await worker.createRouter({ mediaCodecs: [
{ kind: 'audio', mimeType: 'audio/opus', clockRate: 48000, channels: 2 },
{ kind: 'video', mimeType: 'video/VP8', clockRate: 90000 },
]});
wss.on('connection', ws => {
ws.on('message', async msg => {
const { action, data } = JSON.parse(msg);
switch (action) {
case 'createProducerTransport': {
// Create transport for broadcaster
const transport = await router.createWebRtcTransport({ listenIps: ['127.0.0.1'], enableUdp: true, enableTcp: true });
producerTransports.set(ws, { transport, producer: null });
ws.send(JSON.stringify({
action: 'producerTransportCreated',
data: { id: transport.id, iceParameters: transport.iceParameters, iceCandidates: transport.iceCandidates, dtlsParameters: transport.dtlsParameters }
}));
break;
}
case 'connectProducerTransport': {
const { dtlsParameters } = data;
const { transport } = producerTransports.get(ws);
await transport.connect({ dtlsParameters });
ws.send(JSON.stringify({ action: 'producerTransportConnected' }));
break;
}
case 'produce': {
const { kind, rtpParameters } = data;
const { transport } = producerTransports.get(ws);
const producer = await transport.produce({ kind, rtpParameters });
producerTransports.get(ws).producer = producer;
ws.send(JSON.stringify({ action: 'produced', data: { producerId: producer.id } }));
break;
}
case 'createConsumerTransport': {
// Create transport for a viewer
const transport = await router.createWebRtcTransport({ listenIps: ['127.0.0.1'], enableUdp: true, enableTcp: true });
const arr = consumerTransports.get(ws) || [];
arr.push({ transport, consumer: null });
consumerTransports.set(ws, arr);
ws.send(JSON.stringify({
action: 'consumerTransportCreated',
data: { id: transport.id, iceParameters: transport.iceParameters, iceCandidates: transport.iceCandidates, dtlsParameters: transport.dtlsParameters }
}));
break;
}
case 'connectConsumerTransport': {
const { dtlsParameters } = data;
// assume latest transport
const arr = consumerTransports.get(ws);
await arr[arr.length - 1].transport.connect({ dtlsParameters });
ws.send(JSON.stringify({ action: 'consumerTransportConnected' }));
break;
}
case 'consume': {
// find the broadcaster’s producer
const producerEntry = [...producerTransports.values()].find(e => e.producer);
if (!producerEntry) {
ws.send(JSON.stringify({ action: 'consumeError', data: 'No producer available yet' }));
return;
}
const producer = producerEntry.producer;
const arr = consumerTransports.get(ws);
const { transport } = arr[arr.length - 1];
const consumer = await transport.consume({
producerId: producer.id,
rtpCapabilities: router.rtpCapabilities,
paused: false
});
arr[arr.length - 1].consumer = consumer;
ws.send(JSON.stringify({
action: 'consumed',
data: {
producerId: producer.id,
id: consumer.id,
kind: consumer.kind,
rtpParameters: consumer.rtpParameters
}
}));
break;
}
}
});
});
})();