From 15bb1cd8049c03d14e40dd96ce5e65ba5730e7ed Mon Sep 17 00:00:00 2001 From: acgist <289547414@qq.com> Date: Sat, 4 Feb 2023 21:11:30 +0800 Subject: [PATCH] =?UTF-8?q?[+]=20=E4=BF=A1=E4=BB=A4=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E6=8E=88=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- taoyao-media-server/src/Command.js | 40 -------------- taoyao-media-server/src/Config.js | 4 +- taoyao-media-server/src/Logger.js | 39 ++++++++++++++ taoyao-media-server/src/Server.js | 87 +++++++++++++++++++----------- taoyao-media-server/src/Signal.js | 8 +-- 5 files changed, 102 insertions(+), 76 deletions(-) delete mode 100644 taoyao-media-server/src/Command.js diff --git a/taoyao-media-server/src/Command.js b/taoyao-media-server/src/Command.js deleted file mode 100644 index fb29091..0000000 --- a/taoyao-media-server/src/Command.js +++ /dev/null @@ -1,40 +0,0 @@ -const Logger = require("./Logger"); - -const logger = new Logger(); - -/** - * 交互式控制台 - */ -function openCommandConsole() { - logger.info("打开交互式控制台..."); - process.stdin.resume(); - process.stdin.setEncoding("utf-8"); - process.stdin.on("data", (data) => { - process.stdin.pause(); - const command = data.replace(/^\s\s*/, "").replace(/\s\s*$/, ""); - logger.info(""); - switch (command) { - case "h": - case "help": { - logger.info("- h, help : 帮助信息"); - logger.info("- os : 系统信息"); - break; - } - case "": - default: { - logger.warn(`未知命令:'${command}'`); - logger.info("查询命令:`h` | `help`"); - } - } - logger.info(""); - process.stdin.resume(); - }); -} - -module.exports = async function () { - try { - openCommandConsole(); - } catch (error) { - logger.error("执行命令异常:%o", error); - } -}; diff --git a/taoyao-media-server/src/Config.js b/taoyao-media-server/src/Config.js index 6df9477..268f646 100644 --- a/taoyao-media-server/src/Config.js +++ b/taoyao-media-server/src/Config.js @@ -4,7 +4,7 @@ const os = require("os"); module.exports = { - // 系统名称 + // 服务名称 name: "taoyao-media-server", // 交互式命令行 command: true, @@ -28,7 +28,7 @@ module.exports = { numWorkers: Object.keys(os.cpus()).length, // Worker:https://mediasoup.org/documentation/v3/mediasoup/api/#WorkerSettings workerSettings: { - logLevel: "warn", + logLevel: "info", logTags: [ "bwe", "ice", diff --git a/taoyao-media-server/src/Logger.js b/taoyao-media-server/src/Logger.js index 479cdbd..98d6ede 100644 --- a/taoyao-media-server/src/Logger.js +++ b/taoyao-media-server/src/Logger.js @@ -19,22 +19,60 @@ class Logger { } } + /** + * debug + * + * @param {...any} args 参数 + * + * @returns this + */ debug(...args) { return this.log(console.debug, '37m', 'DEBUG', args); } + /** + * info + * + * @param {...any} args 参数 + * + * @returns this + */ info(...args) { return this.log(console.info, '32m', 'INFO', args); } + /** + * warn + * + * @param {...any} args 参数 + * + * @returns this + */ warn(...args) { return this.log(console.warn, '33m', 'WARN', args); } + /** + * error + * + * @param {...any} args 参数 + * + * @returns this + */ error(...args) { return this.log(console.error, '31m', 'ERROR', args); } + /** + * 日志 + * + * @param {*} out 输出位置 + * @param {*} color 颜色 + * @param {*} level 级别 + * @param {*} args 参数 + * + * @returns this + */ log(out, color, level, args) { if(!args || this.level.indexOf(level) < this.levelIndex) { return this; @@ -44,6 +82,7 @@ class Logger { } else if(args.length === 1 && args[0].length > 0) { out(`\x1B[${color}${this.name} ${moment().format('yyyy-MM-DD HH:mm:ss')} : [${level.padEnd(5, ' ')}] : ${args[0]}\x1B[0m`); } else { + // 其他情况直接输出换行 out(""); } return this; diff --git a/taoyao-media-server/src/Server.js b/taoyao-media-server/src/Server.js index 3b77828..976a01a 100644 --- a/taoyao-media-server/src/Server.js +++ b/taoyao-media-server/src/Server.js @@ -5,11 +5,10 @@ const fs = require("fs"); const ws = require("ws"); const https = require("https"); -// const mediasoup = require("mediasoup"); +const mediasoup = require("mediasoup"); const config = require("./Config"); const Logger = require("./Logger"); const Signal = require("./Signal"); -const command = require("./Command"); // HTTPS server let httpsServer; @@ -19,9 +18,9 @@ let webSocketServer; const logger = new Logger(); // 信令 const signal = new Signal(); -// 信令终端 +// 无效信令终端列表 const client = []; -// Mediasoup Worker +// Mediasoup Worker列表 const mediasoupWorker = []; process.title = config.name; @@ -31,7 +30,7 @@ process.title = config.name; */ async function buildMediasoupWorker() { const { numWorkers } = config.mediasoup; - logger.info("启动Mediasoup服务(%d Worker)...", numWorkers); + logger.info("启动Mediasoup Worker(%d)...", numWorkers); for (let i = 0; i < numWorkers; i++) { // 新建Worker const worker = await mediasoup.createWorker({ @@ -40,7 +39,7 @@ async function buildMediasoupWorker() { rtcMinPort: Number(config.mediasoup.workerSettings.rtcMinPort), rtcMaxPort: Number(config.mediasoup.workerSettings.rtcMaxPort), }); - // 监听停止服务事件 + // 监听Worker事件 worker.on("died", () => { logger.error( "Mediasoup Worker停止服务(两秒之后自动退出)... [PID:%d]", @@ -48,18 +47,17 @@ async function buildMediasoupWorker() { ); setTimeout(() => process.exit(1), 2000); }); - // 加入队列 + // 加入Worker队列 mediasoupWorker.push(worker); // 配置WebRTC服务 if (process.env.MEDIASOUP_USE_WEBRTC_SERVER !== "false") { - // 每个Worker端口不能相同 + // 配置Worker端口 const portIncrement = mediasoupWorker.length - 1; - const webRtcServerOptions = JSON.parse( - JSON.stringify(config.mediasoup.webRtcServerOptions) - ); + const webRtcServerOptions = JSON.parse(JSON.stringify(config.mediasoup.webRtcServerOptions)); for (const listenInfo of webRtcServerOptions.listenInfos) { listenInfo.port += portIncrement; } + // 配置WebRTC服务 const webRtcServer = await worker.createWebRtcServer(webRtcServerOptions); worker.appData.webRtcServer = webRtcServer; } @@ -87,21 +85,17 @@ async function buildSignalServer() { logger.info("配置WebSocket服务..."); webSocketServer = new ws.Server({ server: httpsServer }); webSocketServer.on("connection", (session) => { + logger.info("打开信令通道: %s", session._socket.remoteAddress); session.datetime = new Date().getTime(); session.authorize = false; client.push(session); - logger.info("信令通道连接: %s", session._socket.remoteAddress); - session.on("open", (message) => { - logger.info("打开信令通道: %s", message); - }); session.on("close", (code) => { logger.info("关闭信令通道: %o", code); }); - session.on("error", (e) => { - logger.error("信令通道异常: %o", e); + session.on("error", (error) => { + logger.error("信令通道异常: %o", error); }); session.on("message", (message) => { - logger.debug("收到信令消息: %s", message); onmessage(message, session); }); }); @@ -115,14 +109,46 @@ async function buildSignalServer() { ); } +/** + * 交互式控制台 + */ + async function buildCommandConsole() { + if(!config.command) { + return; + } + process.stdin.setEncoding("UTF-8"); + process.stdin.resume(); + process.stdin.on("data", (data) => { + process.stdin.pause(); + const command = data.replace(/^\s*/, "").replace(/\s*$/, ""); + logger.info(""); + switch (command) { + case "h": + case "help": { + logger.info("- h, help : 帮助信息"); + logger.info("- os : 系统信息"); + break; + } + case "": + default: { + logger.warn(`未知命令:'${command}'`); + logger.info("查询命令:`h` | `help`"); + break; + } + } + logger.info(""); + process.stdin.resume(); + }); +} + /** * 定时清理无效信令终端 */ -async function cleanClientInterval() { +async function buildClientInterval() { setInterval(() => { const datetime = new Date().getTime(); const oldLength = client.length; - for (var i = 0; i < client.length; i++) { + for (let i = 0; i < client.length; i++) { const session = client[i]; // 超过五秒自动关闭 if (datetime - session.datetime >= 5000) { @@ -145,6 +171,7 @@ async function cleanClientInterval() { async function onmessage(message, session) { try { const data = JSON.parse(message); + // 授权验证 if (!session.authorize) { if ( data.username === config.https.username && @@ -156,7 +183,7 @@ async function onmessage(message, session) { logger.warn("授权失败:%s", session._socket.remoteAddress); session.close(); } - for (var i = 0; i < client.length; i++) { + for (let i = 0; i < client.length; i++) { if (client[i] === session) { client.splice(i, 1); break; @@ -164,6 +191,8 @@ async function onmessage(message, session) { } return; } + // 处理信令 + logger.debug("处理信令消息: %s", message); signal.on(data, session); } catch (error) { logger.error( @@ -176,20 +205,18 @@ async function onmessage(message, session) { } } +/** + * 启动方法 + */ async function main() { logger.debug("DEBUG").info("INFO").warn("WARN").error("ERROR"); logger.info("开始启动:%s", config.name); - // 启动Mediasoup服务 - // await buildMediasoupWorker(); - // 启动服务 + await buildMediasoupWorker(); await buildSignalServer(); + await buildCommandConsole(); + await buildClientInterval(); logger.info("启动完成:%s", config.name); - // 交互式命令行 - if (config.command) { - await command(); - } - // 定时清理无效信令终端 - cleanClientInterval(); } +// 启动 main(); diff --git a/taoyao-media-server/src/Signal.js b/taoyao-media-server/src/Signal.js index 37568ca..fdc623c 100644 --- a/taoyao-media-server/src/Signal.js +++ b/taoyao-media-server/src/Signal.js @@ -6,12 +6,12 @@ class Signal { // Mediasoup Worker列表 - mediasoupWorkers = []; - // Mediasoup Worker下个索引 + mediasoupWorker = []; + // Mediasoup Worker索引 nextMediasoupWorkerIndex = 0; - constructor(mediasoupWorkers) { - this.mediasoupWorkers = mediasoupWorkers; + constructor(mediasoupWorker) { + this.mediasoupWorker = mediasoupWorker; } /**