Compare commits

..

52 Commits

Author SHA1 Message Date
43eee11c7e LINXD-2222: Update 2022-09-19 16:53:32 +03:00
0033cd528d LINXD-2222: Update 2022-09-19 16:53:09 +03:00
5022d88b1d LINXD-2222: Update 2022-09-19 16:51:15 +03:00
52b922825f LINXD-2222: Update 2022-09-19 16:48:46 +03:00
07be8af9ae LINXD-2222: Update 2022-09-19 16:46:43 +03:00
29737fe5d8 LINXD-2222: Fix middleware typo 2022-09-19 16:44:29 +03:00
1f5755b72d LINXD-2222: Added wildcard; Replace httpolyglot with https; Set CORS to * 2022-09-19 16:21:50 +03:00
a2c878f91c Merge pull request 'Delete the whole call(with id) when we call closeCall' (#5) from delete-whole-call-id into master
Reviewed-on: #5
2022-09-17 08:43:57 +00:00
7b6f78725b LINXD-2209: Call closeCall from producerclose and transportclose on consumer handlers; Update README.md 2022-09-16 18:49:56 +03:00
41c6ad281d Delete the whole call(with id) when we call closeCall 2022-09-16 11:08:02 +03:00
f5406f163f Merge pull request 'Allow io3 on server creation' (#4) from Allow-io3 into master
Reviewed-on: #4
2022-09-15 14:54:41 +00:00
28497fda91 Merge with master 2022-09-15 17:53:37 +03:00
4a98a79630 Merge pull request 'LINXD-2209-black-screen-when-2-video-calls-are-answered-simultaneously' (#3) from LINXD-2209-black-screen-when-2-video-calls-are-answered-simultaneously into master
Reviewed-on: #3
2022-09-15 14:49:55 +00:00
22e8b4d364 LINXD-2209: Refactor how we close the call; Check for callId in createRoom event 2022-09-15 17:07:47 +03:00
575dbd69b0 Allow io3 on server creation 2022-09-15 14:49:10 +03:00
a51a757d17 LINXD-2209: Correctly close the call 2022-09-15 09:57:57 +03:00
c059dd5afc LINXD-2209: Correctly close the call 2022-09-15 09:56:32 +03:00
19808da24e LINXD-2209: Get callId from soekct dictionary in consumer-resume case 2022-09-15 09:43:59 +03:00
2f6c25c171 LINXD-2209: Correctly set router to videoCalls 2022-09-15 09:41:24 +03:00
ead0069aa8 LINXD-2209: Correctly set router to videoCalls 2022-09-15 09:39:52 +03:00
434c8f744c LINXD-2209: Correctly set router to videoCalls 2022-09-15 09:35:35 +03:00
7198dc91b1 LINXD-2209: Check for router in videoCalls 2022-09-15 09:33:30 +03:00
f629012712 LINXD-2209: Check for router in videoCalls 2022-09-15 09:32:41 +03:00
41b50d2a11 LINXD-2209: Identify the callId from dictionary 2022-09-15 09:19:04 +03:00
b85ba68c9c LINXD-2209: Added comments 2022-09-13 22:24:10 +03:00
6acd276324 LINXD-2209: Refactor how we save router, consumer, producer, producerTransport and consumerTransport 2022-09-13 22:16:51 +03:00
294dbdf38d LINXD-2209: Added logs 2022-09-13 21:43:16 +03:00
c3d50fdc4e LINXD-2209: Add 4000ms delay between room creation 2022-09-13 21:38:06 +03:00
c12ececf47 LINXD-2209: Add 2000ms delay between room creation 2022-09-13 21:35:26 +03:00
47eb302f5f LINXD-2209: Added logs on consume 2022-09-13 21:33:04 +03:00
accf960aa7 LINXD-2209: Added logs on consume 2022-09-13 21:15:51 +03:00
ab685270f1 LINXD-2209: Add 1000ms delay between room creation 2022-09-13 21:08:14 +03:00
6938e751fe LINXD-2209: Add 100ms delay between room creation 2022-09-13 21:08:03 +03:00
031a7bc4c5 LINXD-2209: Remove console.logs 2022-09-13 21:05:24 +03:00
d7486d0fd6 LINXD-2209: Add 10ms delay between room creation 2022-09-13 21:04:42 +03:00
38931f0654 LINXD-2209: Add 50ms delay between room creation 2022-09-13 21:02:29 +03:00
bb684ca4db LINXD-2209: Add 300ms delay 2022-09-13 20:59:55 +03:00
25a76c343b LINXD-2209: Move getRtpCapa outside of room creation 2022-09-13 20:59:12 +03:00
817a49204d LINXD-2209: Added logs 2022-09-13 20:58:06 +03:00
91b4db1982 LINXD-2209: Added logs 2022-09-13 20:54:35 +03:00
8562f6c58c LINXD-2209: Added logs 2022-09-13 20:49:40 +03:00
5abc309502 LINXD-2209: Added logs 2022-09-13 20:28:07 +03:00
ecb5a88a2c LINXD-2209: Update port 2022-09-13 20:10:34 +03:00
782b749ea3 LINXD-2209: Check queue length 2022-09-13 20:09:25 +03:00
b834016dcb LINXD-2209: Create rooms in sequence 2022-09-13 19:56:06 +03:00
523945271e Remove callback with producer id from transport-produce 2022-08-31 17:06:54 +03:00
0af7ddd786 Remove callback with producer id from transport-produce 2022-08-31 16:53:08 +03:00
ba5add489d Remove callback with producer id from transport-produce 2022-08-31 16:49:23 +03:00
d5cb144799 Remove callback with producer id from transport-produce 2022-08-31 16:47:54 +03:00
4e92f6cdd3 Remove callback with producer id from transport-produce 2022-08-31 16:43:59 +03:00
aaa1c5cea4 Remove callback with producer id from transport-produce 2022-08-31 16:40:38 +03:00
4f302570a2 Remove callback with producer id from transport-produce 2022-08-31 16:24:21 +03:00
7 changed files with 181 additions and 613 deletions

View File

@ -1,5 +1,11 @@
# Video server # Video server
### Generating certificates
##### To generate SSL certificates you must:
1. Go to `/server/ssl`
2. Execute `openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem`
### Development ### Development

534
app.js
View File

@ -8,24 +8,39 @@ import 'dotenv/config'
/* https://mediasoup.org/documentation/v3/mediasoup/installation/ */ /* https://mediasoup.org/documentation/v3/mediasoup/installation/ */
import express from 'express' import express from 'express'
const app = express() const app = express()
// const app = require('express')();
import https from 'httpolyglot' import https from 'httpolyglot'
import fs from 'fs' import fs from 'fs'
import path from 'path' import path from 'path'
const __dirname = path.resolve() const __dirname = path.resolve()
// const FFmpegStatic = require("ffmpeg-static") // import Server from 'socket.io'
import FFmpegStatic from 'ffmpeg-static' import mediasoup from 'mediasoup'
import Server from 'socket.io' // import * as https from "http";
import mediasoup, { getSupportedRtpCapabilities } from 'mediasoup' import Server from "socket.io";
import Process from 'child_process' // import middleware from 'socketio-wildcard'
// const app = express.default();
let worker let worker
let router = {} /**
let producerTransport * videoCalls
let consumerTransport * |-> Router
let producer * |-> Producer
let consumer * |-> Consumer
* |-> Producer Transport
* |-> Consumer Transport
*
* '<callId>': {
* router: Router,
* producer: Producer,
* producerTransport: Producer Transport,
* consumer: Consumer,
* consumerTransport: Consumer Transport
* }
*
**/
let videoCalls = {}
let socketDetails = {}
app.get('/', (_req, res) => { app.get('/', (_req, res) => {
res.send('Hello from mediasoup app!') res.send('Hello from mediasoup app!')
@ -39,281 +54,28 @@ const options = {
cert: fs.readFileSync('./server/ssl/cert.pem', 'utf-8') cert: fs.readFileSync('./server/ssl/cert.pem', 'utf-8')
} }
const httpsServer = https.createServer(options, app) const server = https.createServer(options, app);
const io = new Server(server, { allowEIO3: true });
// const io = new Server(server, { origins: '*:*', allowEIO3: true });
httpsServer.listen(process.env.PORT, () => { // io.use(middleware);
console.log('Listening on port:', process.env.PORT) // const httpsServer = https.createServer(options, app)
})
const startRecordingFfmpeg = () => { // httpsServer.listen(process.env.PORT, () => {
// Return a Promise that can be awaited // console.log('Listening on port:', process.env.PORT)
let recResolve; // })
const promise = new Promise((res, _rej) => {
recResolve = res;
});
// const useAudio = audioEnabled(); // const io = new Server(httpsServer, {
// const useVideo = videoEnabled(); // allowEIO3: true
// const useH264 = h264Enabled(); // });
// const cmdProgram = "ffmpeg"; // Found through $PATH
const cmdProgram = FFmpegStatic; // From package "ffmpeg-static"
let cmdInputPath = `${__dirname}/recording/input-vp8.sdp`;
let cmdOutputPath = `${__dirname}/recording/output-ffmpeg-vp8.webm`;
let cmdCodec = "";
let cmdFormat = "-f webm -flags +global_header";
// Ensure correct FFmpeg version is installed
const ffmpegOut = Process.execSync(cmdProgram + " -version", {
encoding: "utf8",
});
const ffmpegVerMatch = /ffmpeg version (\d+)\.(\d+)\.(\d+)/.exec(ffmpegOut);
let ffmpegOk = false;
if (ffmpegOut.startsWith("ffmpeg version git")) {
// Accept any Git build (it's up to the developer to ensure that a recent
// enough version of the FFmpeg source code has been built)
ffmpegOk = true;
} else if (ffmpegVerMatch) {
const ffmpegVerMajor = parseInt(ffmpegVerMatch[1], 10);
if (ffmpegVerMajor >= 4) {
ffmpegOk = true;
}
}
if (!ffmpegOk) {
console.error("FFmpeg >= 4.0.0 not found in $PATH; please install it");
process.exit(1);
}
// if (useAudio) {
// cmdCodec += " -map 0:a:0 -c:a copy";
// }
// if (useVideo) {
cmdCodec += " -map 0:v:0 -c:v copy";
// if (useH264) {
cmdInputPath = `${__dirname}/recording/input-h264.sdp`;
cmdOutputPath = `${__dirname}/recording/output-ffmpeg-h264.mp4`;
// "-strict experimental" is required to allow storing
// OPUS audio into MP4 container
cmdFormat = "-f mp4 -strict experimental";
// }
// }
// Run process
const cmdArgStr = [
"-nostdin",
"-protocol_whitelist file,rtp,udp",
"-loglevel debug",
"-analyzeduration 5M",
"-probesize 5M",
"-fflags +genpts",
`-i ${cmdInputPath}`,
cmdCodec,
cmdFormat,
`-y ${cmdOutputPath}`,
]
.join(" ")
.trim();
console.log('💗', cmdCodec);
console.log(`Run command: ${cmdProgram} ${cmdArgStr}`);
let recProcess = Process.spawn(cmdProgram, cmdArgStr.split(/\s+/));
global.recProcess = recProcess;
recProcess.on("error", (err) => {
console.error("Recording process error:", err);
});
recProcess.on("exit", (code, signal) => {
console.log("Recording process exit, code: %d, signal: %s", code, signal);
global.recProcess = null;
stopMediasoupRtp();
if (!signal || signal === "SIGINT") {
console.log("Recording stopped");
} else {
console.warn(
"Recording process didn't exit cleanly, output file might be corrupt"
);
}
});
// FFmpeg writes its logs to stderr
recProcess.stderr.on("data", (chunk) => {
chunk
.toString()
.split(/\r?\n/g)
.filter(Boolean) // Filter out empty strings
.forEach((line) => {
console.log(line);
if (line.startsWith("ffmpeg version")) {
setTimeout(() => {
recResolve();
}, 1000);
}
});
});
return promise;
}
const startRecordingGstreamer = () => {
// Return a Promise that can be awaited
let recResolve;
const promise = new Promise((res, _rej) => {
recResolve = res;
});
// const useAudio = audioEnabled();
// const useVideo = videoEnabled();
// const useH264 = h264Enabled();
let cmdInputPath = `${__dirname}/recording/input-vp8.sdp`;
let cmdOutputPath = `${__dirname}/recording/output-gstreamer-vp8.webm`;
let cmdMux = "webmmux";
let cmdAudioBranch = "";
let cmdVideoBranch = "";
// if (useAudio) {
// // prettier-ignore
// cmdAudioBranch =
// "demux. ! queue \
// ! rtpopusdepay \
// ! opusparse \
// ! mux.";
// }
// if (useVideo) {
// if (useH264) {
cmdInputPath = `${__dirname}/recording/input-h264.sdp`;
cmdOutputPath = `${__dirname}/recording/output-gstreamer-h264.mp4`;
cmdMux = `mp4mux faststart=true faststart-file=${cmdOutputPath}.tmp`;
// prettier-ignore
cmdVideoBranch =
"demux. ! queue \
! rtph264depay \
! h264parse \
! mux.";
// } else {
// // prettier-ignore
// cmdVideoBranch =
// "demux. ! queue \
// ! rtpvp8depay \
// ! mux.";
// }
// }
// Run process
const cmdProgram = "gst-launch-1.0"; // Found through $PATH
const cmdArgStr = [
"--eos-on-shutdown",
`filesrc location=${cmdInputPath}`,
"! sdpdemux timeout=0 name=demux",
`${cmdMux} name=mux`,
`! filesink location=${cmdOutputPath}`,
cmdAudioBranch,
cmdVideoBranch,
]
.join(" ")
.trim();
console.log(
`Run command: ${cmdProgram} ${cmdArgStr}`
);
let recProcess = Process.spawn(cmdProgram, cmdArgStr.split(/\s+/));
global.recProcess = recProcess;
recProcess.on("error", (err) => {
console.error("Recording process error:", err);
});
recProcess.on("exit", (code, signal) => {
console.log("Recording process exit, code: %d, signal: %s", code, signal);
global.recProcess = null;
stopMediasoupRtp();
if (!signal || signal === "SIGINT") {
console.log("Recording stopped");
} else {
console.warn(
"Recording process didn't exit cleanly, output file might be corrupt"
);
}
});
// GStreamer writes some initial logs to stdout
recProcess.stdout.on("data", (chunk) => {
chunk
.toString()
.split(/\r?\n/g)
.filter(Boolean) // Filter out empty strings
.forEach((line) => {
console.log(line);
if (line.startsWith("Setting pipeline to PLAYING")) {
setTimeout(() => {
recResolve();
}, 1000);
}
});
});
// GStreamer writes its progress logs to stderr
recProcess.stderr.on("data", (chunk) => {
chunk
.toString()
.split(/\r?\n/g)
.filter(Boolean) // Filter out empty strings
.forEach((line) => {
console.log(line);
});
});
return promise;
}
function stopMediasoupRtp() {
console.log("Stop mediasoup RTP transport and consumer");
// const useAudio = audioEnabled();
// const useVideo = videoEnabled();
// if (useAudio) {
// global.mediasoup.rtp.audioConsumer.close();
// global.mediasoup.rtp.audioTransport.close();
// }
// if (useVideo) {
// global.mediasoup.rtp.videoConsumer.close();
// global.mediasoup.rtp.videoTransport.close();
// }
}
const io = new Server(httpsServer)
// socket.io namespace (could represent a room?) // socket.io namespace (could represent a room?)
const peers = io.of('/mediasoup') const peers = io.of('/mediasoup')
/**
* Worker
* |-> Router(s)
* |-> Producer Transport(s)
* |-> Producer
* |-> Consumer Transport(s)
* |-> Consumer
**/
const createWorker = async () => { const createWorker = async () => {
worker = await mediasoup.createWorker({ worker = await mediasoup.createWorker({
rtcMinPort: 32256, rtcMinPort: 2000,
rtcMaxPort: 65535, rtcMaxPort: 2020,
}) })
console.log(`[createWorker] worker pid ${worker.pid}`) console.log(`[createWorker] worker pid ${worker.pid}`)
@ -335,69 +97,65 @@ worker = createWorker()
// https://github.com/versatica/mediasoup/blob/v3/src/supportedRtpCapabilities.ts // https://github.com/versatica/mediasoup/blob/v3/src/supportedRtpCapabilities.ts
const mediaCodecs = [ const mediaCodecs = [
{ {
kind: "audio", kind: 'audio',
mimeType: "audio/opus", mimeType: 'audio/opus',
preferredPayloadType: 111,
clockRate: 48000, clockRate: 48000,
channels: 2, channels: 2,
parameters: {
minptime: 10,
useinbandfec: 1,
},
}, },
{ {
kind: "video", kind: 'video',
mimeType: "video/VP8", mimeType: 'video/VP8',
preferredPayloadType: 96,
clockRate: 90000,
},
{
kind: "video",
mimeType: "video/H264",
preferredPayloadType: 125,
clockRate: 90000, clockRate: 90000,
parameters: { parameters: {
"level-asymmetry-allowed": 1, 'x-google-start-bitrate': 1000,
"packetization-mode": 1,
"profile-level-id": "42e01f",
}, },
}, },
] ]
const closeCall = (callId) => {
if (videoCalls[callId]) {
videoCalls[callId].producer?.close();
videoCalls[callId].consumer?.close();
videoCalls[callId]?.consumerTransport.close();
videoCalls[callId]?.producerTransport.close();
videoCalls[callId].router.close();
delete videoCalls[callId];
}
}
const getRtpCapabilities = (callId, callback) => {
console.log('[getRtpCapabilities] callId', callId);
const rtpCapabilities = videoCalls[callId].router.rtpCapabilities;
callback({ rtpCapabilities });
}
peers.on('connection', async socket => { peers.on('connection', async socket => {
console.log('[connection] socketId:', socket.id) console.log('[connection] socketId:', socket.id)
socket.emit('connection-success', { socket.emit('connection-success', {
socketId: socket.id, socketId: socket.id
existsProducer: producer ? true : false,
}) })
socket.on('disconnect', () => { socket.on('disconnect', () => {
// do some cleanup // do some cleanup
console.log('peer disconnected') console.log('peer disconnected | socket.id', socket.id)
delete socketDetails[socket.id];
}) })
socket.on('createRoom', async ({ callId }, callback) => { socket.on('createRoom', async ({ callId }, callback) => {
console.log('[createRoom] callId', callId); if (callId) {
console.log('Router length:', Object.keys(router).length); console.log(`[createRoom] socket.id ${socket.id} callId ${callId}`);
if (router[callId] === undefined) { if (!videoCalls[callId]) {
// worker.createRouter(options) console.log('[createRoom] callId', callId);
// options = { mediaCodecs, appData } videoCalls[callId] = { router: await worker.createRouter({ mediaCodecs }) }
// mediaCodecs -> defined above console.log(`[createRoom] Router ID: ${videoCalls[callId].router.id}`);
// appData -> custom application data - we are not supplying any }
// none of the two are required socketDetails[socket.id] = callId;
router[callId] = await worker.createRouter({ mediaCodecs }) getRtpCapabilities(callId, callback);
console.log(`[createRoom] Router ID: ${router[callId].id}`) } else {
console.log(`[createRoom] missing callId ${callId}`);
} }
getRtpCapabilities(callId, callback)
}) })
const getRtpCapabilities = (callId, callback) => {
const rtpCapabilities = router[callId].rtpCapabilities
callback({ rtpCapabilities })
}
// Client emits a request to create server side Transport // Client emits a request to create server side Transport
// We need to differentiate between the producer and consumer transports // We need to differentiate between the producer and consumer transports
socket.on('createWebRtcTransport', async ({ sender, callId }, callback) => { socket.on('createWebRtcTransport', async ({ sender, callId }, callback) => {
@ -405,138 +163,91 @@ peers.on('connection', async socket => {
// The client indicates if it is a producer or a consumer // The client indicates if it is a producer or a consumer
// if sender is true, indicates a producer else a consumer // if sender is true, indicates a producer else a consumer
if (sender) if (sender)
producerTransport = await createWebRtcTransportLayer(callId, callback) videoCalls[callId].producerTransport = await createWebRtcTransportLayer(callId, callback)
else else
consumerTransport = await createWebRtcTransportLayer(callId, callback) videoCalls[callId].consumerTransport = await createWebRtcTransportLayer(callId, callback)
}) })
// see client's socket.emit('transport-connect', ...) // see client's socket.emit('transport-connect', ...)
socket.on('transport-connect', async ({ dtlsParameters }) => { socket.on('transport-connect', async ({ dtlsParameters }) => {
console.log('[transport-connect] DTLS PARAMS... ', { dtlsParameters }) const callId = socketDetails[socket.id];
await producerTransport.connect({ dtlsParameters }) console.log(`[transport-connect] socket.id ${socket.id} | callId ${callId} | DTLS PARAMS... ${dtlsParameters}`)
await videoCalls[callId].producerTransport.connect({ dtlsParameters })
}) })
// see client's socket.emit('transport-produce', ...) // see client's socket.emit('transport-produce', ...)
socket.on('transport-produce', async ({ kind, rtpParameters, callId }, callback) => { socket.on('transport-produce', async ({ kind, rtpParameters, appData }) => {
const callId = socketDetails[socket.id];
console.log('[transport-produce] | socket.id', socket.id, '| callId', callId);
// call produce based on the prameters from the client // call produce based on the prameters from the client
producer = await producerTransport.produce({ videoCalls[callId].producer = await videoCalls[callId].producerTransport.produce({
kind, kind,
rtpParameters, rtpParameters,
}) })
console.log(`[transport-produce] Producer ID: ${videoCalls[callId].producer.id} | kind: ${videoCalls[callId].producer.kind}`)
console.log(`[transport-produce] Producer ID: ${producer.id} | kind: ${producer.kind}`) videoCalls[callId].producer.on('transportclose', () => {
const callId = socketDetails[socket.id];
producer.on('transportclose', () => {
console.log('transport for this producer closed', callId) console.log('transport for this producer closed', callId)
closeCall(callId);
// https://mediasoup.org/documentation/v3/mediasoup/api/#producer-close
producer.close()
// https://mediasoup.org/documentation/v3/mediasoup/api/#router-close
router[callId].close()
delete router[callId]
}) })
// Send back to the client the Producer's id
callback({
id: producer.id
})
console.log('🔴', callId);
const rtpTransport = await router[callId].createPlainTransport({
comedia: false,
rtcpMux: false,
listenIp: { ip: "127.0.0.1", announcedIp: null }
});
await rtpTransport.connect({
ip: "127.0.0.1",
port: 5006,
rtcpPort: 5007,
});
console.log(
"mediasoup VIDEO RTP SEND transport connected: %s:%d <--> %s:%d (%s)",
rtpTransport.tuple.localIp,
rtpTransport.tuple.localPort,
rtpTransport.tuple.remoteIp,
rtpTransport.tuple.remotePort,
rtpTransport.tuple.protocol
);
console.log(
"mediasoup VIDEO RTCP SEND transport connected: %s:%d <--> %s:%d (%s)",
rtpTransport.rtcpTuple.localIp,
rtpTransport.rtcpTuple.localPort,
rtpTransport.rtcpTuple.remoteIp,
rtpTransport.rtcpTuple.remotePort,
rtpTransport.rtcpTuple.protocol
);
const rtpConsumer = await rtpTransport.consume({
// producerId: global.mediasoup.webrtc.videoProducer.id,
producerId: producer.id,
// rtpCapabilities: router.rtpCapabilities,
rtpCapabilities: router[callId].rtpCapabilities,
paused: true,
});
// console.log('🟡 producerId:', producer.id, 'rtpCapabilities:', router[callId].rtpCapabilities, 'paused:', true);
await startRecordingFfmpeg();
// await startRecordingGstreamer();
rtpConsumer.resume();
}) })
// see client's socket.emit('transport-recv-connect', ...) // see client's socket.emit('transport-recv-connect', ...)
socket.on('transport-recv-connect', async ({ dtlsParameters }) => { socket.on('transport-recv-connect', async ({ dtlsParameters }) => {
console.log(`[transport-recv-connect] DTLS PARAMS: ${dtlsParameters}`) const callId = socketDetails[socket.id];
await consumerTransport.connect({ dtlsParameters }) console.log(`[transport-recv-connect] socket.id ${socket.id} | callId ${callId} | DTLS PARAMS: ${dtlsParameters}`);
await videoCalls[callId].consumerTransport.connect({ dtlsParameters })
}) })
socket.on('consume', async ({ rtpCapabilities, callId }, callback) => { socket.on('consume', async ({ rtpCapabilities }, callback) => {
const callId = socketDetails[socket.id];
console.log('[consume] callId', callId);
try { try {
console.log('consume', rtpCapabilities, callId); // console.log('consume', rtpCapabilities, callId);
// check if the router can consume the specified producer // check if the router can consume the specified producer
if (router[callId].canConsume({ if (videoCalls[callId].router.canConsume({
producerId: producer.id, producerId: videoCalls[callId].producer.id,
rtpCapabilities rtpCapabilities
})) { })) {
console.log('[consume] Can consume', callId);
// transport can now consume and return a consumer // transport can now consume and return a consumer
consumer = await consumerTransport.consume({ videoCalls[callId].consumer = await videoCalls[callId].consumerTransport.consume({
producerId: producer.id, producerId: videoCalls[callId].producer.id,
rtpCapabilities, rtpCapabilities,
paused: true, paused: true,
}) })
consumer.on('transportclose', () => { // https://mediasoup.org/documentation/v3/mediasoup/api/#consumer-on-transportclose
console.log('transport close from consumer', callId) videoCalls[callId].consumer.on('transportclose', () => {
// closeRoom(callId) const callId = socketDetails[socket.id];
delete router[callId] console.log('transport close from consumer', callId);
closeCall();
}) })
consumer.on('producerclose', () => { // https://mediasoup.org/documentation/v3/mediasoup/api/#consumer-on-producerclose
console.log('producer of consumer closed', callId) videoCalls[callId].consumer.on('producerclose', () => {
const callId = socketDetails[socket.id];
// https://mediasoup.org/documentation/v3/mediasoup/api/#router-close console.log('producer of consumer closed', callId);
router[callId].close() closeCall();
delete router[callId]
}) })
// from the consumer extract the following params // from the consumer extract the following params
// to send back to the Client // to send back to the Client
const params = { const params = {
id: consumer.id, id: videoCalls[callId].consumer.id,
producerId: producer.id, producerId: videoCalls[callId].producer.id,
kind: consumer.kind, kind: videoCalls[callId].consumer.kind,
rtpParameters: consumer.rtpParameters, rtpParameters: videoCalls[callId].consumer.rtpParameters,
} }
// send the parameters to the client // send the parameters to the client
callback({ params }) callback({ params })
} else {
console.log('[canConsume] Can\'t consume')
} }
} catch (error) { } catch (error) {
console.log(error.message) console.log('[consume] Error', error.message)
callback({ callback({
params: { params: {
error: error error: error
@ -546,8 +257,9 @@ peers.on('connection', async socket => {
}) })
socket.on('consumer-resume', async () => { socket.on('consumer-resume', async () => {
console.log(`[consumer-resume]`) const callId = socketDetails[socket.id];
await consumer.resume() console.log(`[consumer-resume] callId ${callId}`)
await videoCalls[callId].consumer.resume()
}) })
}) })
@ -565,14 +277,12 @@ const createWebRtcTransportLayer = async (callId, callback) => {
enableUdp: true, enableUdp: true,
enableTcp: true, enableTcp: true,
preferUdp: true, preferUdp: true,
initialAvailableOutgoingBitrate: 300000
} }
// console.log('webRtcTransport_options', webRtcTransport_options); // console.log('webRtcTransport_options', webRtcTransport_options);
// console.log('router', router, '| router[callId]', router[callId]);
// https://mediasoup.org/documentation/v3/mediasoup/api/#router-createWebRtcTransport // https://mediasoup.org/documentation/v3/mediasoup/api/#router-createWebRtcTransport
let transport = await router[callId].createWebRtcTransport(webRtcTransport_options) let transport = await videoCalls[callId].router.createWebRtcTransport(webRtcTransport_options)
console.log(`callId: ${callId} | transport id: ${transport.id}`) console.log(`callId: ${callId} | transport id: ${transport.id}`)
transport.on('dtlsstatechange', dtlsState => { transport.on('dtlsstatechange', dtlsState => {
@ -592,8 +302,6 @@ const createWebRtcTransportLayer = async (callId, callback) => {
dtlsParameters: transport.dtlsParameters, dtlsParameters: transport.dtlsParameters,
} }
console.log('params', params);
// send back to the client the following prameters // send back to the client the following prameters
callback({ callback({
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#TransportOptions // https://mediasoup.org/documentation/v3/mediasoup-client/api/#TransportOptions

223
package-lock.json generated
View File

@ -12,13 +12,13 @@
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"express": "^4.18.1", "express": "^4.18.1",
"ffmpeg-static": "^5.0.2",
"httpolyglot": "^0.1.2", "httpolyglot": "^0.1.2",
"mediasoup": "^3.10.4", "mediasoup": "^3.10.4",
"mediasoup-client": "^3.6.54", "mediasoup-client": "^3.6.54",
"parcel": "^2.7.0", "parcel": "^2.7.0",
"socket.io": "^2.0.3", "socket.io": "^2.0.3",
"socket.io-client": "^2.0.3" "socket.io-client": "^2.0.3",
"socketio-wildcard": "^2.0.0"
}, },
"devDependencies": { "devDependencies": {
"nodemon": "^2.0.19", "nodemon": "^2.0.19",
@ -128,47 +128,6 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/@derhuerst/http-basic": {
"version": "8.2.4",
"resolved": "https://registry.npmjs.org/@derhuerst/http-basic/-/http-basic-8.2.4.tgz",
"integrity": "sha512-F9rL9k9Xjf5blCz8HsJRO4diy111cayL2vkY2XE4r4t3n0yPXVYy3KD3nJ1qbrSn9743UWSXH4IwuCa/HWlGFw==",
"dependencies": {
"caseless": "^0.12.0",
"concat-stream": "^2.0.0",
"http-response-object": "^3.0.1",
"parse-cache-control": "^1.0.1"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@derhuerst/http-basic/node_modules/concat-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
"integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
"engines": [
"node >= 6.0"
],
"dependencies": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.0.2",
"typedarray": "^0.0.6"
}
},
"node_modules/@derhuerst/http-basic/node_modules/readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/@jridgewell/gen-mapping": { "node_modules/@jridgewell/gen-mapping": {
"version": "0.3.2", "version": "0.3.2",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
@ -2250,6 +2209,7 @@
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"dev": true,
"dependencies": { "dependencies": {
"debug": "4" "debug": "4"
}, },
@ -2261,6 +2221,7 @@
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "2.1.2"
}, },
@ -2276,7 +2237,8 @@
"node_modules/agent-base/node_modules/ms": { "node_modules/agent-base/node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}, },
"node_modules/amp": { "node_modules/amp": {
"version": "0.3.1", "version": "0.3.1",
@ -2945,11 +2907,6 @@
} }
] ]
}, },
"node_modules/caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
},
"node_modules/chalk": { "node_modules/chalk": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
@ -3765,14 +3722,6 @@
"url": "https://github.com/fb55/entities?sponsor=1" "url": "https://github.com/fb55/entities?sponsor=1"
} }
}, },
"node_modules/env-paths": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"engines": {
"node": ">=6"
}
},
"node_modules/error-ex": { "node_modules/error-ex": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@ -4037,21 +3986,6 @@
"integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==", "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==",
"dev": true "dev": true
}, },
"node_modules/ffmpeg-static": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.0.2.tgz",
"integrity": "sha512-rYeA04AGbvxbUxov6Cn/KDKIzw2rmzwPlgHoqn837NZt0xPdOVA9mJMILz9IX27R45hhSlXS6nThk85XxDivLg==",
"hasInstallScript": true,
"dependencies": {
"@derhuerst/http-basic": "^8.2.0",
"env-paths": "^2.2.0",
"https-proxy-agent": "^5.0.0",
"progress": "^2.0.3"
},
"engines": {
"node": ">=16"
}
},
"node_modules/file-uri-to-path": { "node_modules/file-uri-to-path": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz",
@ -4670,19 +4604,6 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true "dev": true
}, },
"node_modules/http-response-object": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz",
"integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==",
"dependencies": {
"@types/node": "^10.0.3"
}
},
"node_modules/http-response-object/node_modules/@types/node": {
"version": "10.17.60",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
"integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw=="
},
"node_modules/httpolyglot": { "node_modules/httpolyglot": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/httpolyglot/-/httpolyglot-0.1.2.tgz", "resolved": "https://registry.npmjs.org/httpolyglot/-/httpolyglot-0.1.2.tgz",
@ -4701,6 +4622,7 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"dev": true,
"dependencies": { "dependencies": {
"agent-base": "6", "agent-base": "6",
"debug": "4" "debug": "4"
@ -4713,6 +4635,7 @@
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "2.1.2"
}, },
@ -4728,7 +4651,8 @@
"node_modules/https-proxy-agent/node_modules/ms": { "node_modules/https-proxy-agent/node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}, },
"node_modules/iconv-lite": { "node_modules/iconv-lite": {
"version": "0.4.24", "version": "0.4.24",
@ -6105,11 +6029,6 @@
"safe-buffer": "^5.1.1" "safe-buffer": "^5.1.1"
} }
}, },
"node_modules/parse-cache-control": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz",
"integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg=="
},
"node_modules/parse-json": { "node_modules/parse-json": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
@ -6565,14 +6484,6 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true "dev": true
}, },
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/promptly": { "node_modules/promptly": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz",
@ -7207,6 +7118,11 @@
"ms": "2.0.0" "ms": "2.0.0"
} }
}, },
"node_modules/socketio-wildcard": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/socketio-wildcard/-/socketio-wildcard-2.0.0.tgz",
"integrity": "sha512-Bf3ioZq15Z2yhFLDasRvbYitg82rwm+5AuER5kQvEQHhNFf4R4K5o/h57nEpN7A59T9FyRtTj34HZfMWAruw/A=="
},
"node_modules/socks": { "node_modules/socks": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz",
@ -7386,6 +7302,7 @@
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dev": true,
"dependencies": { "dependencies": {
"safe-buffer": "~5.2.0" "safe-buffer": "~5.2.0"
} }
@ -7864,7 +7781,8 @@
"node_modules/typedarray": { "node_modules/typedarray": {
"version": "0.0.6", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"dev": true
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.7.4", "version": "4.7.4",
@ -8006,7 +7924,8 @@
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
}, },
"node_modules/utility-types": { "node_modules/utility-types": {
"version": "3.10.0", "version": "3.10.0",
@ -8374,40 +8293,6 @@
"@jridgewell/trace-mapping": "0.3.9" "@jridgewell/trace-mapping": "0.3.9"
} }
}, },
"@derhuerst/http-basic": {
"version": "8.2.4",
"resolved": "https://registry.npmjs.org/@derhuerst/http-basic/-/http-basic-8.2.4.tgz",
"integrity": "sha512-F9rL9k9Xjf5blCz8HsJRO4diy111cayL2vkY2XE4r4t3n0yPXVYy3KD3nJ1qbrSn9743UWSXH4IwuCa/HWlGFw==",
"requires": {
"caseless": "^0.12.0",
"concat-stream": "^2.0.0",
"http-response-object": "^3.0.1",
"parse-cache-control": "^1.0.1"
},
"dependencies": {
"concat-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
"integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
"requires": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.0.2",
"typedarray": "^0.0.6"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
}
}
},
"@jridgewell/gen-mapping": { "@jridgewell/gen-mapping": {
"version": "0.3.2", "version": "0.3.2",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
@ -9763,6 +9648,7 @@
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"dev": true,
"requires": { "requires": {
"debug": "4" "debug": "4"
}, },
@ -9771,6 +9657,7 @@
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"requires": { "requires": {
"ms": "2.1.2" "ms": "2.1.2"
} }
@ -9778,7 +9665,8 @@
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
} }
} }
}, },
@ -10347,11 +10235,6 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001375.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001375.tgz",
"integrity": "sha512-kWIMkNzLYxSvnjy0hL8w1NOaWNr2rn39RTAVyIwcw8juu60bZDWiF1/loOYANzjtJmy6qPgNmn38ro5Pygagdw==" "integrity": "sha512-kWIMkNzLYxSvnjy0hL8w1NOaWNr2rn39RTAVyIwcw8juu60bZDWiF1/loOYANzjtJmy6qPgNmn38ro5Pygagdw=="
}, },
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
},
"chalk": { "chalk": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
@ -11035,11 +10918,6 @@
"resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
"integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q=="
}, },
"env-paths": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="
},
"error-ex": { "error-ex": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@ -11248,17 +11126,6 @@
"integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==", "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==",
"dev": true "dev": true
}, },
"ffmpeg-static": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.0.2.tgz",
"integrity": "sha512-rYeA04AGbvxbUxov6Cn/KDKIzw2rmzwPlgHoqn837NZt0xPdOVA9mJMILz9IX27R45hhSlXS6nThk85XxDivLg==",
"requires": {
"@derhuerst/http-basic": "^8.2.0",
"env-paths": "^2.2.0",
"https-proxy-agent": "^5.0.0",
"progress": "^2.0.3"
}
},
"file-uri-to-path": { "file-uri-to-path": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz",
@ -11697,21 +11564,6 @@
} }
} }
}, },
"http-response-object": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz",
"integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==",
"requires": {
"@types/node": "^10.0.3"
},
"dependencies": {
"@types/node": {
"version": "10.17.60",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
"integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw=="
}
}
},
"httpolyglot": { "httpolyglot": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/httpolyglot/-/httpolyglot-0.1.2.tgz", "resolved": "https://registry.npmjs.org/httpolyglot/-/httpolyglot-0.1.2.tgz",
@ -11727,6 +11579,7 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"dev": true,
"requires": { "requires": {
"agent-base": "6", "agent-base": "6",
"debug": "4" "debug": "4"
@ -11736,6 +11589,7 @@
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"requires": { "requires": {
"ms": "2.1.2" "ms": "2.1.2"
} }
@ -11743,7 +11597,8 @@
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
} }
} }
}, },
@ -12810,11 +12665,6 @@
"safe-buffer": "^5.1.1" "safe-buffer": "^5.1.1"
} }
}, },
"parse-cache-control": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz",
"integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg=="
},
"parse-json": { "parse-json": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
@ -13168,11 +13018,6 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true "dev": true
}, },
"progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
},
"promptly": { "promptly": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz",
@ -13683,6 +13528,11 @@
} }
} }
}, },
"socketio-wildcard": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/socketio-wildcard/-/socketio-wildcard-2.0.0.tgz",
"integrity": "sha512-Bf3ioZq15Z2yhFLDasRvbYitg82rwm+5AuER5kQvEQHhNFf4R4K5o/h57nEpN7A59T9FyRtTj34HZfMWAruw/A=="
},
"socks": { "socks": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz",
@ -13841,6 +13691,7 @@
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dev": true,
"requires": { "requires": {
"safe-buffer": "~5.2.0" "safe-buffer": "~5.2.0"
} }
@ -14173,7 +14024,8 @@
"typedarray": { "typedarray": {
"version": "0.0.6", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"dev": true
}, },
"typescript": { "typescript": {
"version": "4.7.4", "version": "4.7.4",
@ -14279,7 +14131,8 @@
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
}, },
"utility-types": { "utility-types": {
"version": "3.10.0", "version": "3.10.0",

View File

@ -17,13 +17,13 @@
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"express": "^4.18.1", "express": "^4.18.1",
"ffmpeg-static": "^5.0.2",
"httpolyglot": "^0.1.2", "httpolyglot": "^0.1.2",
"mediasoup": "^3.10.4", "mediasoup": "^3.10.4",
"mediasoup-client": "^3.6.54", "mediasoup-client": "^3.6.54",
"parcel": "^2.7.0", "parcel": "^2.7.0",
"socket.io": "^2.0.3", "socket.io": "^2.0.3",
"socket.io-client": "^2.0.3" "socket.io-client": "^2.0.3",
"socketio-wildcard": "^2.0.0"
}, },
"devDependencies": { "devDependencies": {
"nodemon": "^2.0.19", "nodemon": "^2.0.19",

View File

@ -20808,7 +20808,7 @@ const getLocalStream = () => {
}) })
.then(streamSuccess) .then(streamSuccess)
.catch(error => { .catch(error => {
console.log('getLocalStream', error) console.log(error.message)
}) })
} }
@ -20903,7 +20903,7 @@ const createSendTransport = () => {
}) })
producerTransport.on('produce', async (parameters, callback, errback) => { producerTransport.on('produce', async (parameters, callback, errback) => {
console.log('produce', parameters) console.log(parameters)
try { try {
// tell the server to create a Producer // tell the server to create a Producer
@ -20913,7 +20913,7 @@ const createSendTransport = () => {
await socket.emit('transport-produce', { await socket.emit('transport-produce', {
kind: parameters.kind, kind: parameters.kind,
rtpParameters: parameters.rtpParameters, rtpParameters: parameters.rtpParameters,
callId: callId appData: parameters.appData,
}, ({ id }) => { }, ({ id }) => {
// Tell the transport that parameters were transmitted and provide it with the // Tell the transport that parameters were transmitted and provide it with the
// server side producer's id. // server side producer's id.
@ -21009,6 +21009,7 @@ const createRecvTransport = async () => {
} }
const resetCallSettings = () => { const resetCallSettings = () => {
socket.emit('transportclose', { callId })
localVideo.srcObject = null localVideo.srcObject = null
remoteVideo.srcObject = null remoteVideo.srcObject = null
consumer = null consumer = null
@ -21059,9 +21060,9 @@ const closeCall = () => {
// Emit 'notify-end' to Hub so the consumer will know to close the video // Emit 'notify-end' to Hub so the consumer will know to close the video
const notifyEnd = { const notifyEnd = {
origin_asset_id: ASSET_ID, origin_asset_id: ASSET_ID,
dest_asset_id: originAssetId || parseInt(urlParams.get('dest_asset_id')), dest_asset_id: originAssetId || parseInt(urlParams.get('dest_asset_id')),
type: 'notify-end', type: 'notify-end',
video_call_id: callId video_call_id: callId
} }
console.log('notifyEnd', notifyEnd) console.log('notifyEnd', notifyEnd)
@ -21071,7 +21072,7 @@ const closeCall = () => {
const closeCallBtn = document.getElementById('btnCloseCall') const closeCallBtn = document.getElementById('btnCloseCall')
closeCallBtn.setAttribute('disabled', '') closeCallBtn.setAttribute('disabled', '')
// Reset settings // Reset settings and send closeTransport to video server
resetCallSettings() resetCallSettings()
} }

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
hubAddress: 'https://hub.dev.linx.safemobile.com/', hubAddress: 'https://hub.dev.linx.safemobile.com/',
// mediasoupAddress: 'https://video.safemobile.org/mediasoup', mediasoupAddress: 'https://video.safemobile.org/mediasoup',
mediasoupAddress: 'http://localhost:3000/mediasoup', // mediasoupAddress: 'http://localhost:3000/mediasoup',
} }

View File

@ -149,7 +149,7 @@ const getLocalStream = () => {
}) })
.then(streamSuccess) .then(streamSuccess)
.catch(error => { .catch(error => {
console.log('getLocalStream', error) console.log(error.message)
}) })
} }
@ -244,7 +244,7 @@ const createSendTransport = () => {
}) })
producerTransport.on('produce', async (parameters, callback, errback) => { producerTransport.on('produce', async (parameters, callback, errback) => {
console.log('produce', parameters) console.log(parameters)
try { try {
// tell the server to create a Producer // tell the server to create a Producer
@ -254,7 +254,7 @@ const createSendTransport = () => {
await socket.emit('transport-produce', { await socket.emit('transport-produce', {
kind: parameters.kind, kind: parameters.kind,
rtpParameters: parameters.rtpParameters, rtpParameters: parameters.rtpParameters,
callId: callId appData: parameters.appData,
}, ({ id }) => { }, ({ id }) => {
// Tell the transport that parameters were transmitted and provide it with the // Tell the transport that parameters were transmitted and provide it with the
// server side producer's id. // server side producer's id.