[*] 优化logger
This commit is contained in:
@@ -10,7 +10,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": "^8.12.0",
|
||||
"debug": "^4.3.1",
|
||||
"mediasoup": "file:./mediasoup"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -13,12 +13,15 @@ module.exports = {
|
||||
listenIp: "0.0.0.0",
|
||||
listenPort: process.env.HTTPS_LISTEN_PORT || 4443,
|
||||
// WebSocket连接密码
|
||||
username: 'taoyao',
|
||||
password: 'taoyao',
|
||||
username: "taoyao",
|
||||
password: "taoyao",
|
||||
tls: {
|
||||
cert: process.env.HTTPS_CERT_PUBLIC_KEY || `${__dirname}/certs/publicKey.pem`,
|
||||
key: process.env.HTTPS_CERT_PRIVATE_KEY || `${__dirname}/certs/privateKey.pem`,
|
||||
}
|
||||
cert:
|
||||
process.env.HTTPS_CERT_PUBLIC_KEY || `${__dirname}/certs/publicKey.pem`,
|
||||
key:
|
||||
process.env.HTTPS_CERT_PRIVATE_KEY ||
|
||||
`${__dirname}/certs/privateKey.pem`,
|
||||
},
|
||||
},
|
||||
// Mediasoup
|
||||
mediasoup: {
|
||||
@@ -133,5 +136,20 @@ module.exports = {
|
||||
},
|
||||
maxSctpMessageSize: 262144,
|
||||
},
|
||||
}
|
||||
},
|
||||
wellcome: `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>桃夭媒体服务</title>
|
||||
<style type="text/css">
|
||||
p{text-align:center;}
|
||||
a{text-decoration:none;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p><a href="https://gitee.com/acgist/taoyao">taoyao-media-server</a></p>
|
||||
<p><a href="https://www.acgist.com">acgist</a></p>
|
||||
</body>
|
||||
</html>`,
|
||||
};
|
||||
|
||||
@@ -1,44 +1,46 @@
|
||||
/**
|
||||
* 日志
|
||||
*/
|
||||
const debug = require("debug");
|
||||
const config = require("./Config");
|
||||
|
||||
class Logger {
|
||||
|
||||
//
|
||||
name = config.name;
|
||||
|
||||
constructor(prefix) {
|
||||
const appName = config.name;
|
||||
if (prefix) {
|
||||
this._debug = debug(`${appName}:DEBUG:${prefix}`);
|
||||
this._info = debug(`${appName}:INFO:${prefix}`);
|
||||
this._warn = debug(`${appName}:WARN:${prefix}`);
|
||||
this._error = debug(`${appName}:ERROR:${prefix}`);
|
||||
} else {
|
||||
this._debug = debug(`${appName}:DEBUG`);
|
||||
this._info = debug(`${appName}:INFO`);
|
||||
this._warn = debug(`${appName}:WARN`);
|
||||
this._error = debug(`${appName}:ERROR`);
|
||||
this.name = this.name + ':' + prefix;
|
||||
}
|
||||
this._debug.log = console.debug.bind(console);
|
||||
this._info.log = console.info.bind(console);
|
||||
this._warn.log = console.warn.bind(console);
|
||||
this._error.log = console.error.bind(console);
|
||||
}
|
||||
|
||||
get debug() {
|
||||
return this._debug.log;
|
||||
debug(...args) {
|
||||
this.log(console.debug, 'DEBUG', args);
|
||||
}
|
||||
|
||||
get info() {
|
||||
return this._info.log;
|
||||
info(...args) {
|
||||
this.log(console.info, 'INFO', args);
|
||||
}
|
||||
|
||||
get warn() {
|
||||
return this._warn.log;
|
||||
warn(...args) {
|
||||
this.log(console.warn, 'WARN', args);
|
||||
}
|
||||
|
||||
get error() {
|
||||
return this._error.log;
|
||||
error(...args) {
|
||||
this.log(console.error, 'ERROR', args);
|
||||
}
|
||||
|
||||
log(out, level, args) {
|
||||
if(!args) {
|
||||
return;
|
||||
}
|
||||
if(args.length > 1 && args[0].length > 0) {
|
||||
out(`${this.name}:${level}:${args[0]}`, ...args.slice(1));
|
||||
} else if(args.length === 1 && args[0].length > 0) {
|
||||
out(`${this.name}:${level}:${args[0]}`);
|
||||
} else {
|
||||
out("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
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");
|
||||
@@ -83,7 +83,7 @@ async function buildSignalServer() {
|
||||
logger.info("配置HTTPS服务...");
|
||||
httpsServer = https.createServer(tls, (request, response) => {
|
||||
response.writeHead(200);
|
||||
response.end("taoyao media server");
|
||||
response.end(config.wellcome);
|
||||
});
|
||||
logger.info("配置WebSocket服务...");
|
||||
webSocketServer = new ws.Server({ server: httpsServer });
|
||||
@@ -125,7 +125,7 @@ async function buildSignalServer() {
|
||||
async function main() {
|
||||
logger.info("开始启动:%s", config.name);
|
||||
// 启动Mediasoup服务
|
||||
await buildMediasoupWorkers();
|
||||
// await buildMediasoupWorkers();
|
||||
// 启动服务
|
||||
await buildSignalServer();
|
||||
logger.info("启动完成:%s", config.name);
|
||||
|
||||
@@ -20,7 +20,10 @@ class Signal {
|
||||
* @param {*} message 消息
|
||||
* @param {*} session websocket
|
||||
*/
|
||||
on(message, session) {}
|
||||
on(message, session) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Signal;
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
/**
|
||||
* 配置
|
||||
*/
|
||||
const os = require("os");
|
||||
|
||||
module.exports = {
|
||||
// 系统名称
|
||||
name: "taoyao-media-server",
|
||||
// 交互式命令行
|
||||
command: true,
|
||||
// 信令服务
|
||||
https: {
|
||||
listenIp: "0.0.0.0",
|
||||
listenPort: process.env.HTTPS_LISTEN_PORT || 4443,
|
||||
// WebSocket连接密码
|
||||
username: 'taoyao',
|
||||
password: 'taoyao',
|
||||
tls: {
|
||||
cert: process.env.HTTPS_CERT_PUBLIC_KEY || `${__dirname}/certs/publicKey.pem`,
|
||||
key: process.env.HTTPS_CERT_PRIVATE_KEY || `${__dirname}/certs/privateKey.pem`,
|
||||
}
|
||||
},
|
||||
// Mediasoup
|
||||
mediasoup: {
|
||||
// 按照CPU数量配置进程数量
|
||||
numWorkers: Object.keys(os.cpus()).length,
|
||||
// Worker:https://mediasoup.org/documentation/v3/mediasoup/api/#WorkerSettings
|
||||
workerSettings: {
|
||||
logLevel: "warn",
|
||||
logTags: [
|
||||
"bwe",
|
||||
"ice",
|
||||
"rtp",
|
||||
"rtx",
|
||||
"svc",
|
||||
"dtls",
|
||||
"info",
|
||||
"sctp",
|
||||
"srtp",
|
||||
"rtcp",
|
||||
"score",
|
||||
"message",
|
||||
"simulcast",
|
||||
],
|
||||
rtcMinPort: process.env.MEDIASOUP_MIN_PORT || 40000,
|
||||
rtcMaxPort: process.env.MEDIASOUP_MAX_PORT || 49999,
|
||||
},
|
||||
// Router:https://mediasoup.org/documentation/v3/mediasoup/api/#RouterOptions
|
||||
routerOptions: {
|
||||
mediaCodecs: [
|
||||
{
|
||||
kind: "audio",
|
||||
mimeType: "audio/opus",
|
||||
clockRate: 48000,
|
||||
channels: 2,
|
||||
},
|
||||
{
|
||||
kind: "video",
|
||||
mimeType: "video/VP8",
|
||||
clockRate: 90000,
|
||||
parameters: {
|
||||
"x-google-start-bitrate": 1000,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "video",
|
||||
mimeType: "video/VP9",
|
||||
clockRate: 90000,
|
||||
parameters: {
|
||||
"profile-id": 2,
|
||||
"x-google-start-bitrate": 1000,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "video",
|
||||
mimeType: "video/h264",
|
||||
clockRate: 90000,
|
||||
parameters: {
|
||||
"packetization-mode": 1,
|
||||
"profile-level-id": "4d0032",
|
||||
"level-asymmetry-allowed": 1,
|
||||
"x-google-start-bitrate": 1000,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "video",
|
||||
mimeType: "video/h264",
|
||||
clockRate: 90000,
|
||||
parameters: {
|
||||
"packetization-mode": 1,
|
||||
"profile-level-id": "42e01f",
|
||||
"level-asymmetry-allowed": 1,
|
||||
"x-google-start-bitrate": 1000,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// WebRtcServer:https://mediasoup.org/documentation/v3/mediasoup/api/#WebRtcServerOptions
|
||||
webRtcServerOptions: {
|
||||
listenInfos: [
|
||||
{
|
||||
protocol: "udp",
|
||||
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
||||
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP,
|
||||
port: 44444,
|
||||
},
|
||||
{
|
||||
protocol: "tcp",
|
||||
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
||||
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP,
|
||||
port: 44444,
|
||||
},
|
||||
],
|
||||
},
|
||||
// WebRtcTransport:https://mediasoup.org/documentation/v3/mediasoup/api/#WebRtcTransportOptions
|
||||
webRtcTransportOptions: {
|
||||
listenIps: [
|
||||
{
|
||||
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
||||
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP,
|
||||
},
|
||||
],
|
||||
initialAvailableOutgoingBitrate: 1000000,
|
||||
minimumAvailableOutgoingBitrate: 600000,
|
||||
maxSctpMessageSize: 262144,
|
||||
maxIncomingBitrate: 1500000,
|
||||
},
|
||||
// PlainTransport:https://mediasoup.org/documentation/v3/mediasoup/api/#PlainTransportOptions
|
||||
plainTransportOptions: {
|
||||
listenIp: {
|
||||
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
||||
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP,
|
||||
},
|
||||
maxSctpMessageSize: 262144,
|
||||
},
|
||||
}
|
||||
};
|
||||
@@ -1,138 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 服务
|
||||
*/
|
||||
const fs = require("fs");
|
||||
const ws = require("ws");
|
||||
const https = require("https");
|
||||
const mediasoup = require("mediasoup");
|
||||
const config = require("./Config");
|
||||
const Logger = require("./Logger");
|
||||
const Signal = require("./Signal");
|
||||
const command = require("./Command");
|
||||
|
||||
// 日志
|
||||
const logger = new Logger();
|
||||
// 信令
|
||||
const signal = new Signal();
|
||||
// HTTPS server
|
||||
let httpsServer;
|
||||
// WebSocket server
|
||||
let webSocketServer;
|
||||
// Mediasoup Worker
|
||||
const mediasoupWorkers = [];
|
||||
|
||||
process.title = config.name;
|
||||
process.env.DEBUG = process.env.DEBUG || "*mediasoup* *INFO* *WARN* *ERROR*";
|
||||
|
||||
/**
|
||||
* 启动Mediasoup Worker
|
||||
*/
|
||||
async function buildMediasoupWorkers() {
|
||||
const { numWorkers } = config.mediasoup;
|
||||
logger.info("启动Mediasoup服务(%d Worker)...", numWorkers);
|
||||
for (let i = 0; i < numWorkers; i++) {
|
||||
// 新建Worker
|
||||
const worker = await mediasoup.createWorker({
|
||||
logLevel: config.mediasoup.workerSettings.logLevel,
|
||||
logTags: config.mediasoup.workerSettings.logTags,
|
||||
rtcMinPort: Number(config.mediasoup.workerSettings.rtcMinPort),
|
||||
rtcMaxPort: Number(config.mediasoup.workerSettings.rtcMaxPort),
|
||||
});
|
||||
// 监听停止服务事件
|
||||
worker.on("died", () => {
|
||||
logger.error(
|
||||
"Mediasoup Worker停止服务(两秒之后自动退出)... [PID:%d]",
|
||||
worker.pid
|
||||
);
|
||||
setTimeout(() => process.exit(1), 2000);
|
||||
});
|
||||
// 加入队列
|
||||
mediasoupWorkers.push(worker);
|
||||
// 配置WebRTC服务
|
||||
if (process.env.MEDIASOUP_USE_WEBRTC_SERVER !== "false") {
|
||||
// 每个Worker端口不能相同
|
||||
const portIncrement = mediasoupWorkers.length - 1;
|
||||
const webRtcServerOptions = JSON.parse(JSON.stringify(config.mediasoup.webRtcServerOptions));
|
||||
for (const listenInfo of webRtcServerOptions.listenInfos) {
|
||||
listenInfo.port += portIncrement;
|
||||
}
|
||||
const webRtcServer = await worker.createWebRtcServer(webRtcServerOptions);
|
||||
worker.appData.webRtcServer = webRtcServer;
|
||||
}
|
||||
// 定时记录使用日志
|
||||
setInterval(async () => {
|
||||
const usage = await worker.getResourceUsage();
|
||||
logger.info(
|
||||
"Mediasoup Worker使用情况 [pid:%d]: %o",
|
||||
worker.pid,
|
||||
usage
|
||||
);
|
||||
}, 120 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动信令服务
|
||||
*/
|
||||
async function buildSignalServer() {
|
||||
const tls = {
|
||||
cert: fs.readFileSync(config.https.tls.cert),
|
||||
key: fs.readFileSync(config.https.tls.key),
|
||||
};
|
||||
logger.info("配置HTTPS服务...");
|
||||
httpsServer = https.createServer(tls, (request, response) => {
|
||||
response.writeHead(200);
|
||||
response.end("taoyao media server");
|
||||
});
|
||||
logger.info("配置WebSocket服务...");
|
||||
webSocketServer = new ws.Server({ server: httpsServer });
|
||||
webSocketServer.on("connection", (session) => {
|
||||
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("message", (message) => {
|
||||
logger.debug("收到信令消息: %s", message);
|
||||
try {
|
||||
signal.on(JSON.parse(message), session);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`处理信令消息异常:
|
||||
%s
|
||||
%o`,
|
||||
message,
|
||||
error
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
// 打开监听
|
||||
httpsServer.listen(
|
||||
Number(config.https.listenPort),
|
||||
config.https.listenIp,
|
||||
() => {
|
||||
logger.info("信令服务启动完成");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
logger.info("开始启动:%s", config.name);
|
||||
// 启动Mediasoup服务
|
||||
await buildMediasoupWorkers();
|
||||
// 启动服务
|
||||
await buildSignalServer();
|
||||
logger.info("启动完成:%s", config.name);
|
||||
// 交互式命令行
|
||||
if (config.command) {
|
||||
await command();
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* 信令
|
||||
* 1. 终端媒体流向
|
||||
* 2. 处理音频视频:降噪、水印等等
|
||||
*/
|
||||
class Signal {
|
||||
|
||||
// Mediasoup Worker列表
|
||||
mediasoupWorkers = [];
|
||||
// Mediasoup Worker下个索引
|
||||
nextMediasoupWorkerIndex = 0;
|
||||
|
||||
constructor(mediasoupWorkers) {
|
||||
this.mediasoupWorkers = mediasoupWorkers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理事件
|
||||
*
|
||||
* @param {*} message 消息
|
||||
* @param {*} session websocket
|
||||
*/
|
||||
on(message, session) {}
|
||||
}
|
||||
|
||||
module.exports = Signal;
|
||||
Reference in New Issue
Block a user