Spaces:
Sleeping
Sleeping
| const express = require('express'); | |
| const app = express(); | |
| const bodyParser = require('body-parser'); | |
| const webrtc = require('wrtc'); | |
| // Instead of one global stream, keep one per room | |
| const roomStreams = {}; // { [roomId]: MediaStream } | |
| app.use(express.static('public')); | |
| app.use(bodyParser.json()); | |
| app.use(bodyParser.urlencoded({ extended: true })); | |
| // Consumer endpoint: front-end must POST { sdp, roomId } | |
| app.post("/consumer", async ({ body }, res) => { | |
| const { sdp, roomId } = body; | |
| const stream = roomStreams[roomId]; | |
| if (!stream) { | |
| return res.status(404).json({ error: "No broadcast for room " + roomId }); | |
| } | |
| const peer = new webrtc.RTCPeerConnection({ | |
| iceServers: [{ urls: "stun:stun.stunprotocol.org" }] | |
| }); | |
| // add the broadcaster’s tracks for this room | |
| stream.getTracks().forEach(track => peer.addTrack(track, stream)); | |
| await peer.setRemoteDescription(new webrtc.RTCSessionDescription(sdp)); | |
| const answer = await peer.createAnswer(); | |
| await peer.setLocalDescription(answer); | |
| res.json({ sdp: peer.localDescription }); | |
| }); | |
| // Broadcast endpoint: front-end must POST { sdp, roomId } | |
| app.post("/broadcast", async ({ body }, res) => { | |
| const { sdp, roomId } = body; | |
| const peer = new webrtc.RTCPeerConnection({ | |
| iceServers: [{ urls: "stun:stun.stunprotocol.org" }] | |
| }); | |
| peer.ontrack = ({ streams }) => { | |
| // store the incoming stream under its roomId | |
| roomStreams[roomId] = streams[0]; | |
| }; | |
| await peer.setRemoteDescription(new webrtc.RTCSessionDescription(sdp)); | |
| const answer = await peer.createAnswer(); | |
| await peer.setLocalDescription(answer); | |
| res.json({ sdp: peer.localDescription }); | |
| }); | |
| app.listen(7860, () => console.log('SFU server running on port 5000')); | |