This commit is contained in:
145
server/index.mjs
Normal file
145
server/index.mjs
Normal file
@@ -0,0 +1,145 @@
|
||||
import express from "express";
|
||||
import http from "http";
|
||||
import cors from "cors";
|
||||
import { Server } from "socket.io";
|
||||
import * as mediasoup from "mediasoup";
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(cors());
|
||||
|
||||
const server = http.createServer(app);
|
||||
const io = new Server(server, {
|
||||
cors: {
|
||||
origin: '*'
|
||||
}
|
||||
});
|
||||
|
||||
let worker;
|
||||
let router;
|
||||
const transports = new Map(); // socketId -> [transports]
|
||||
const producers = new Map(); // socketId -> [producers]
|
||||
const consumers = new Map(); // socketId -> [consumers]
|
||||
|
||||
async function createWorker() {
|
||||
worker = await mediasoup.createWorker();
|
||||
worker.on("died", () => {
|
||||
console.error("mediasoup worker died, exiting...");
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
router = await worker.createRouter({
|
||||
mediaCodecs: [
|
||||
{
|
||||
kind: "audio",
|
||||
mimeType: "audio/opus",
|
||||
clockRate: 48000,
|
||||
channels: 2,
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
console.log("Mediasoup worker & router created");
|
||||
}
|
||||
|
||||
createWorker();
|
||||
|
||||
io.on("connection", (socket) => {
|
||||
console.log("Client connected:", socket.id);
|
||||
|
||||
socket.on("getRtpCapabilities", (cb) => {
|
||||
cb(router.rtpCapabilities);
|
||||
});
|
||||
|
||||
socket.on("createTransport", async (cb) => {
|
||||
try {
|
||||
const transport = await router.createWebRtcTransport({
|
||||
listenIps: [{ ip: "0.0.0.0", announcedIp: "127.0.0.1" }],
|
||||
enableUdp: true,
|
||||
enableTcp: true,
|
||||
preferUdp: true,
|
||||
});
|
||||
|
||||
transports.set(socket.id, [...(transports.get(socket.id) || []), transport]);
|
||||
|
||||
cb({
|
||||
id: transport.id,
|
||||
iceParameters: transport.iceParameters,
|
||||
iceCandidates: transport.iceCandidates,
|
||||
dtlsParameters: transport.dtlsParameters,
|
||||
});
|
||||
|
||||
transport.observer.on("close", () => {
|
||||
console.log("transport closed", transport.id);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("createTransport error:", err);
|
||||
cb({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("connectTransport", async ({ transportId, dtlsParameters }, cb) => {
|
||||
const transport = transports.get(socket.id)?.find((t) => t.id === transportId);
|
||||
if (!transport) return cb({ error: "transport not found" });
|
||||
await transport.connect({ dtlsParameters });
|
||||
cb({ connected: true });
|
||||
});
|
||||
|
||||
socket.on("produce", async ({ transportId, kind, rtpParameters }, cb) => {
|
||||
const transport = transports.get(socket.id)?.find((t) => t.id === transportId);
|
||||
if (!transport) return cb({ error: "transport not found" });
|
||||
|
||||
const producer = await transport.produce({ kind, rtpParameters });
|
||||
producers.set(socket.id, [...(producers.get(socket.id) || []), producer]);
|
||||
|
||||
cb({ id: producer.id });
|
||||
socket.broadcast.emit("newProducer", { producerId: producer.id });
|
||||
|
||||
producer.observer.on("close", () => {
|
||||
console.log("producer closed", producer.id);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("consume", async ({ producerId, transportId, rtpCapabilities }, cb) => {
|
||||
try {
|
||||
if (!router.canConsume({ producerId, rtpCapabilities })) {
|
||||
return cb({ error: "cannot consume" });
|
||||
}
|
||||
|
||||
const transport = transports.get(socket.id)?.find((t) => t.id === transportId);
|
||||
if (!transport) return cb({ error: "transport not found" });
|
||||
|
||||
const consumer = await transport.consume({
|
||||
producerId,
|
||||
rtpCapabilities,
|
||||
paused: false,
|
||||
});
|
||||
|
||||
consumers.set(socket.id, [...(consumers.get(socket.id) || []), consumer]);
|
||||
|
||||
cb({
|
||||
id: consumer.id,
|
||||
producerId,
|
||||
kind: consumer.kind,
|
||||
rtpParameters: consumer.rtpParameters,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("consume error:", err);
|
||||
cb({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("disconnect", () => {
|
||||
console.log("Client disconnected:", socket.id);
|
||||
|
||||
transports.get(socket.id)?.forEach((t) => t.close());
|
||||
producers.get(socket.id)?.forEach((p) => p.close());
|
||||
consumers.get(socket.id)?.forEach((c) => c.close());
|
||||
|
||||
transports.delete(socket.id);
|
||||
producers.delete(socket.id);
|
||||
consumers.delete(socket.id);
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(process.env.PORT || 3000);
|
||||
Reference in New Issue
Block a user